"Order Tracking" OWA/module

At PIH we’ve been tasked with coming up with a solution for one of our hospitals to improve the workflow at their in-house lab.

In the short-term we are looking for a solution that allows:

  • Clinicians to order lab tests
  • Labels to be printed at the time of blood draw/specimen collection
  • Some level of specimen tracking
  • Lab technicians to enter results for those orders
  • Clinicians to check the status of an order

There is no LIMS currently in place at the hospital, but hopefully there will be long-term. So we are looking for creating something short-term into OpenMRS to meet some or all of those needs, while avoiding the slippery slope of building a LIMS within OpenMRS

Specimen tracking seems something that is clearly in the purvey of the LIMS, but it seems to that entering lab results manually and tracking order status is something that could fit into OpenMRS.

Our thought now is to get involved with the Order Entry OWA project and expand that to handle Test Ordering (right now it is focused on drug ordering). For tracking and entering results we were thinking of proposing a “Order Tracking” OWA/module or some combination thereof. Our ideas are still under development (and there is not 100% agreement amongst ourselves of the design) but wanted to share them with the community sooner rather than later.

The key (and perhaps only) domain model change for this would be adding an “Order Status” to an “Order”. Exactly how this would work is TBA but it seems likely it might need to be added as a separate domain object since Orders are immutable. Order Status would has a set of states like"Ordered", “Pending”, and “Reported” (names certainly could be tweaked).

Then we’d foresee an OWA that provides a few key pages:

  • List of all patients with orders in the “Ordered” state, with the ability to click into:

  • Details of all orders in the “Ordered” for a single patient, with the ability to select one or more and change them to the “Pending” state (with perhaps optional functionality to create a “Lab” encounter around this and/or print out labels); this tool would be used at the lab at the time of specimen collection

  • List of all orders in the “Pending” state, where clicking into an individual order would bring you to:

  • A results page that would allow one to enter in the results for a specific test; we would likely set up results templates for the key test types, mapping the orderable to the result set (using concepts in the CIEL dictionary).

  • Status page for an individual patient listing all Test Orders and their status, with the ability to click into results for completed tests


  • Does this seem like functionality that would generally be build into an EMR? Or is even this level of functionality generally provided by a LIMS?

  • Is this something that seems like it would be useful to have build into the Reference Application? If so, we can schedule a Design Call to discuss further as we flesh out our design.

Take care, Mark

fyi @burke @darius @mseaton @ddesimone

Hey Mark,

I know that I’m not answering your questions but I was wondering, what about leveraging OpenELIS and atom feed as it is done in Bahmni? Of course you would still need the EMR part with order tracking… etc, but could that work to provide the LIMS part?

“Manual lab result entry (for implementations without a LIMS)” surely is in-scope for an EMR. Bahmni includes this as Order Fulfillment.

I also think that knowing the status of an order also belongs in OpenMRS’s domain. (I said this to you on another thread last week: Best Practice for Modelling Order Fulfillment?, and as I said then, FHIR includes it as ProcedureRequest.status.) I don’t know offhand if we’d want this as a single mutable field on Order, or in another table so that we could track the history. But I support adding this to the core data model.

(If you’re tracking specimens or samples, this belongs in a LIMS. If you’re tracking Orders, it belongs in the EHR.)

A few quick thoughts:

  • approach this as a microservice that you can swap out later. (okay to actually implement using omod/owa)
  • plan for a future where some orders are handled by this mechanism and others are not (e.g. radiology orders go to an external system, but lab orders are still handled here)
    • some level of configurability about what can be manually managed with this app
    • also probably the UI should support a workflow where you first choose an order type
  • you don’t always have exactly one result per order. You mention “results templates” but you can also consider using existing form entry tooling for this
  • I would expect the results to be displayed on the main patient dashboard (although I guess you’d still be allowed to see them via this app)

Thanks @darius! A few thoughts

  1. I was envisioning a OWA for the front end, most likely written in React, following a similar pattern of the “Order Entry” OWA

  2. For middleware/backend (which I think is just added Order Status + REST access to it) I was envisioning a OMOD which we could eventually migrate to core (and the Web Services module)… or, even better, build it directly into core and if we aren’t able to upgrade to 2.2 (or it isn’t released by the time we need it) pull it out into a module that can simply “go away” once we upgrade to core. Since we are so close now to the bleeding edge (we are running 2.1) we’d like to get a much into Core as possible. Looks like we are spending a non-trivial amount of time migrating the Condition functionality to Core and it would be great to avoid that going forward. (If you have any other ideas of a “microservice” approach beyond creating a service in a omod, let us know. :slight_smile: )

  3. Yes, in many/most cases there won’t be one result per order. “Templates” probably was the wrong term… I was hoping that since (I think) tests & their results are generally standard and limited, we could potentially hard-code 20-30 result forms (with only a few fields apiece) and avoid having to create a generic template model, or to have to use HFE or another technology. (This would also have the benefit of allowing implementations to use it “out of box” assuming they are using a CIEL-compatible dictionary) Will require more analysis though.

  4. Yes, we’d want results displayed in the main patient dashboard. However, since we are still using a “UI Framework” based patient dashboard, I might consider handling this outside of the OWA (for now) if there’s not a clear path to use a React widget inside the UI Framework Patient Dashboard. (Although this is something we’d certainly want to figure out sooner rather than later).

To me, the path we take hinges on #2. (If we agree to add Order Status to Ref App and/or core we can start designing the OWA as a Ref App compatible tool, otherwise it might be better to build custom OWA to meet our particular needs). Is this something people would be willing to consider and therefore should we set up a design call about it?

Take care, Mark

@mksd long-term the plan would be to use a LIMS in the lab, but due to a variety of issues that won’t be happening in the near-term and we’d like to get something in (relatively) quickly to meet a need.

That being said, I am wary of this functionality having “scope creep” to the point that just adding a LIMS earlier rather than later would have been the better solution.

Take care, Mark

Order already has some mutable fields, therefore we can always add status as an extra mutable field, whether status field should be mutable vs immutable is really a logical question and in my opinion changing the status field’s value doesn’t change the order itself.

Thanks @wyclif, makes sense. Question would be whether we want to be able to track this status over time in OpenMRS, which would have a more complicated OrderState object with startDate and endDate. This might complicate things more than needed though.

@jthomas can we schedule a design call around this? Is there formal process to request that beyond posting here? :slight_smile:

(With this=“Adding Order Status to Orders”)

I’d personally rather have status on a separate entity in the order tracking module where this entity references the tracked order otherwise I agree with @mseaton that adding it in core might complicate things since we would have to code against it.

Sorry @wyclif, I’m not sure I was clear. I believe this belongs in core either way. The question of whether this is a mutable property on Order or a separate domain object called OrderStatus might be one of whether we want to track a progression of statuses over time rather than just the latest status.


In our original design for the order service, we included an order status that was meant to track orders through a workflow, but the design was overly complex, preventing some organizations from adopting it, and we ended up stripping out features to get an order entry service in version 1.10 that everyone was willing to adopt. (@darius, remember 2012? LOL :wink:)

I would be in favor of adding orders.order_status to align with FHIR’s MedicationRequest.status, ProcedureRequest.status, NutritionOrder.status, etc. Ultimately, this could be used to track orders from draft to activated to completed.

One of the tricky bits will be approaching order status in a way that is “future proof.” Do we need to fully model all possible states up front? Or can we design in a way that can tolerate new states later without breaking all existing code? For example, if you make a service method to get all “ordered” labs, will it break if a status of “draft” or “active” is added later? Encapsulating interpretation of the order status within a service layer might be a way to handle this.

The various order status fields in FHIR should allow us to distinguish active vs. completed orders and, when we’re ready for it, draft orders. We don’t need to introduce them now, but I would favor approaching order status in a way that could also accommodate common workflows in the future. Some examples from my own experience:

  • received - The request has been received (e.g., nurse acknowledged the order, lab received the specimen, pharmacy acknowledging a script)
  • draft - The request has been created but is not yet complete or ready for action
  • needs cosign - The request is ready but should not be acted upon (marked “active”) until cosigned

Tracking specimens and generating results are LIMS. It’s perfectly acceptable to do these in a module. When/if enterprise lab features are needed (running controls, tracking data about specimens or workflow that are not patient-centric, etc.), then integrating with a separate LIMS makes more sense.

A couple additional thoughts on order tracking:

  • The order tracking features you describe seem to be focused primarily on test (specifically lab) orders. It might be worth considering how/if order tracking might apply to other types of orders (referrals, nursing orders, activity orders, prescriptions), since it could affect your design choices (e.g., instead of hardcoding lab result entry into an order tracker, have link/button that jumps to the appropriate page to enter a “result”… the first implementation jumps to a lab result entry form for lab orders, but a referral order might jump to a different form and a medication order might jump to an drug administration tool).

  • Your approach applies to a lab workflow wanting to queue orders and facilitate entry of results (connected to and “completing” orders) across patients; however, another common & related workflow is for nursing to see a patient-specific queue of outstanding orders for a given patient (i.e., a patient-specific task list). Perhaps that deserves a separate module/addon, but since it’s closely related and would also depend on and affect order status, I thought I’d mention it.

My instinct would be:

  • Add this as orders.status (aligning with FHIR) as a mutable property of an order. We can log changes to order status for now.
  • Encapsulate interpretation of raw status values within the service rather than just emitting raw data and expecting clients to interpret the values consistently.

If you want to schedule a design forum, browse to https://om.rs/designtime to request design time.

Thanks @burke (and @darius), super helpful and thorough responses as always!

Regarding adding orders.status, thoughts on whether we can just link this to Concept and be done with it?

Alternatives I suppose would be order_status_type metadata or a static enum of FHIR-supported values?


Since we would presumably want to code against specific values (even within core/platform), I don’t like the idea of using concepts.

I would presume this means we should have an order_status table, which in addition to its “name” has a “meaning” column, whose value is a FHIR code. And clients should know how to interpret these values.

(If you’re suggesting that we have a bunch of Java methods like “getDraftOrders”, “getActionableOrders” (excludes draft, received, fulfilled), etc, I don’t like that idea much, and it’s hard to map it to a REST world.

In the past we have avoided preemptively defining statuses we don’t want to support yet in the application, but in practice that makes it a heavy lift to go back and change this (even adding a single enum value could require a new minor platform release, and could have a year-long timeline). Since we have now separated our platform and reference application, we are open to behave in a different way.

I propose that up-front we support all the FHIR-recommended statuses (including drafts). We don’t have to support this in the reference application yet, but the platform can offer support to anyone who wants to use it.

I pretty agree with the approach @darius suggests… I’d be fine with just having a enum mapping to FHIR codes, or going the expanded route and having a table with both name and code.

If just make this a mutable property of orders (instead of a separate table which tracks a “startDate”), do we want to add a “date_changed” to orders for some minimal change tracking?

Also, unfortunately, the default FHIR statuses don’t have a status for one important element of our use case–we want to track which orders still require a blood draw or other specimen collection action. We certainly don’t want/need a specific status for this, but I was hoping FHIR would provide some sort of a “In Process” status which we could use for this (ie, once blood is drawn and passed on to the lab, status goes from “Active” to “In Process”. Do you think we could include a state like this?

Also, I’ve requested design call time so we can discuss further.

Thanks everyone! Mark

I think we simply add orders.order_status as an Enum. My concern is, if we stop there, we are leaving it up to clients to define business logic, which could end up making things unpredictable or brittle. When we add “draft”, “received” (aka “in process”), and “cosign” (aka “needs cosign”) as additional statuses in the future, a growing number of order-related addons and reports break with each change. Do we try to predict up front all possible statuses we’ll use in the future and ask people to code against them now? Or do we provide advice on working with existing statuses that will be relatively future proof if statuses change? We don’t need to work it all out here. Happy to discuss on a design forum… just want to make sure we have the discussion.

This is the received status I mentioned above. Other potential statuses not covered by FHIR include verbal (active but needs to be signed), needs cosign (needs to be signed before becoming active), and documented (retrospective entry of orders). As an example, here are some workflow diagrams from 2011 I created when we were working through this space at Regenstrief:

I’m not suggesting that we implement all of this up front. But I’m a little concerned about heading down a path that will prevent us from being able to eventually handle these types of workflows if our API stops at CRUD and the business of managing order status is spread across an indeterminate number of addons.

Thanks @burke! I will review more, but it looks like we’ve got the Monday design call slotted for this as long as everyone can make it.

Take care, Mark

Looks forward to discussing today… my gut is that it actually may be best to have the API stop at CRUD. If we can really nail down all the business logic and use cases from day one we could include that logic in core, but if we don’t 100% get it right it makes it harder to change things once other modules start building against it.

Take care, Mark

Good discussion on today’s design forum (notes here). Here are some quick takeaways (I believe @mogoodrich is going to provide a summary).

Introduce Order.fulfillerStatus now:

  • received - order fulfiller has received the request
  • exception - an error or exception occurred during processing
  • completed - the request has been completed by fulfiller

Consider also introducing Order.status (aligning with FHIR status fields):

  • draft - unsigned, work in progress
  • active - order that may be acted upon
  • completed - all activity related to the request has been completed
  • stopped - request terminated

Some additional thoughts during the discussion:

  • We haven’t yet modeled how we would handle orders needing cosign.
  • Verbal orders will be deferred. Would be active and probably have a separate property to track authorizing signature.
  • We would not plan on supporting on hold or suspended (risk of medical errors, encourage stop and re-write instead).
  • We would not plan on implementing FHIR’s cancelled or entered in error statuses (close enough to OpenMRS voiding).
  • We wouldn’t support unknown status (would use null for this if needed later).

More details in the notes.