The handling and mapping of Lab Order status for the Lab Workflow

The Handling and Mapping of Order Status for the Lab Workflow

Overview of Relevant States and Value Sets

Proposed Mappings for Lab Order Workflow - 1st Iteration

Overview of the Current iSantéPlus - OpenELIS Workflow

The Handling and Mapping of Order Status for the Lab Workflow

The Lab Order workflow between OpenELIS and OpenMRS will use the FHIR Workflow Module and suggested Communication Patterns to implement the ordering of lab tests from OpenMRS to OpenELIS and returning the results to OpenMRS.

Currently, the workflow is implemented using HL7 V2.5.1 messages as documented here.

The OpenMRS data model does not seem to provide much support for storing Order status, with the version of the Order class used by most implementations supporting only the field. OpenMRS platform 2.2.0 adds another field called Order.fullfilerStatus which has values that correspond to FHIR and OpenELIS states, but I’m not sure where and how this field is used.

This post summarizes what I’ve put together so far for determining the correct handling and mapping of order states between OpenELIS and OpenMRS using FHIR, so please leave me any insight or feedback that might help with this task!

Overview of Relevant States and Value Sets

OpenELIS Order Workflow States


FHIR Task Status States

  • draft
  • requested
  • recieved
  • accepted
  • rejected
  • ready
  • cancelled
  • in-progress
  • on-hold
  • failed
  • completed
  • entered-in-error

** bold states are currently implemented in the OpenMRS FHIR Module

State Machine state-machine

FHIR ServiceRequest Status States

  • draft

  • active

  • on-hold

  • revoked

  • completed

  • entered-in-error

  • unknown

FHIR DiagnosticReport Status States

  • registered

  • partial

    • preliminary
  • final

  • ammended

    • corrected

    • appended

  • canceled

  • entered-in-error

  • unknown

FHIR Task Business Status

Workflow example uses the following values for Task.business_status:

  • Ordered

  • Accepted

  • Specimen Available

  • Preliminary Results

  • Final Results

OpenMRS Order

For the current implementation of OpenMRS Core, the Order.action attribute holds a type of order status.

  • NEW




I could not find any documentation for or test case uses of RENEW, but NEW, REVISE and DISCONTINUE seem to be used to denote the status of the order.

The OpenMRS Order class also has a recent addition (since platform v2.2.0) of the attribute Order.fullfillerStatus, with the following fields:





I’m not sure where this attribute is being used, altough these concepts do seem to map directly to OpenELIS states. Notabely, the Ref app currently does not include this change, since it runs OpenMRS Platform v2.1.3.

I also found a seemingly relevant conversation about htis topic on the OpenMRS Wiki, but the proposed system does not seem to be implemented in the code:

In general, the field does not provide a wide range of states for keeping track of Order state, and the states that do exist do not map naturally to the value sets used in OpenELIS or FHIR.

Possibly relevant pages and posts:

Proposed Mappings for Lab Order Workflow - 1st Iteration

  1. Order Created in OpenMRS
  • Order.action = NEW
  • OpenMRSTask.status = DRAFT
  1. Order sent to OpenELIS
  • OpenMRSTask.status.REQUESTED --> Task.status.REQUESTED
  • Order.action.NEW --> ServiceRequest.status.ACTIVE
  1. Order Reception Acknowledgement sent to OpenMRS
  • Task.status.RECIEVED --> OpenMRSTask.status.RECIEVED
  1. Preliminary Results sent to OpenMRS
  • PRELIMINARY_RESULT|RESULT --> DiagnosticReport.status.PARTIAL

  • Task.status.IN_PROGRESS -->
  • Task.status.IN_PROGRESS --> OpenMRSTask.status.IN_PROGRESS
  1. Final Results sent to OpenMRS
  • FINAL_RESULT --> Task.status.COMPLETED
  • FINAL_RESULT --> ServiceRequest.status.COMPLETED
  • FINAL_RESULT --> DiagnostiReqport.status.FINAL

  • Task.status.COMPLETED --> OpenMRSTask.status.COMPLETED

This simple outline does not cover all of the OpenELIS status values. Notibly, the CORRECTION value would need to be handled on the OpenMRS side to update a current result, and would likely have to set the DiagnosticReport status to AMMENDED.

Also, the OpenMRS Order class includes some Date attributes that might have to be set based on the Task and ServiceRequest statuses, like dateActivated and dateStopped.

Overview of the Current iSantéPlus - OpenELIS Workflow

  1. OML^O21 - Incoming Order Request

    • Patient ID

    • Location ID

    • Patient Last,First,Middle

    • Mother’s Name

    • Sex

    • Address

    • Civil Status

    • Religion

    • BirthCity

    • RequestType

    • Provider Id

    • Test LOINC Code

    • Encounter Type & UUID

    • OrderDateScheduled

    Mapped To:

    POST request from iSantePlus to OpenELIS containing:

    • Task Resource

    • ServiceRequest Resource w/ link to Encounter

    • Patient Resource + associated

    • Provider Resource + associated

  2. ORL^O22 - Acknowledgement of Recieved Order

    Same fields as the triggering OLM^O21

    Mapped To:

    PUT request from OpenELIS to iSantePlus containing

    Task.status updated from requested to recieved

  3. ORU^R01 - Status Updates

@slubwama @slubwama1 FYI

I haven’t had a chance to review this in detail yet, but just as an fyi we did add the “fulfillerStatus” with the intent that it could be used to track information from a downstream fulfillment system, so it definitely seemed like it would be relevant to what you are mapping out here. We are using it in a new Lab Workflow OWA we built (, but I don’t think there’s any particular core support for it. One key point is that unlike most parts of Order it is mutable.

Here’s some Talk posts with more details about adding FulFillerStatus:

I’ll make a note to review the rest of this post in detail in the coming days!

Take care, Mark

1 Like

@pmanko Thanks for this write-up! I’ve got a spattering of relatively random thoughts.

Actually, I think if FHIR supports an AMENDED status for DiagnosticReports, we might be all set for dealing with corrections. From the OpenMRS POV, I think we just create the Obs from the AMENDED DiagnosticReport and point the previous_version property to the prior value. AFAICT, nothing else needs to be updated. We might want to look into implementing history for the DiagnosticReport resource, so that when an AMENDED diagnostic report is encounter the client can query the previous version, but I think that’s a concern that can be addressed entirely within the FHIR module itself.

One question that’s worth asking is if OpenMRS core should support the idea of draft orders or if this is already supported somewhere (Bahmni, the Order Entry OWA, etc.). I don’t like the idea of calling something a “draft” in an interface if the underlying system doesn’t support that concept (i.e., how do we differentiate a DRAFT task from a REQUESTED one? Is this merely holding the status of “we haven’t yet sent the message to OpenELIS”?)

Surely the ServiceRequest is ACTIVE as soon as the corresponding Task is REQUESTED right?

I wouldn’t want to make this a general rule, since my impression is (and here it would be good to have the advice of someone like @burke or @jdick) that these fields primarily apply to med orders rather than lab orders. (The fields are nullable in the database, so I don’t think we need to fill them in unless they provided clinically useful information, and my sense is that they don’t for lab orders). On this, though, I’d defer to an actual clinician.

Would it be worthwhile including these fields in OpenMRS’s fulfillerStatus? It seems to me there’s a semantically meaningful difference between “the lab has received the order” and “the lab has received the order and the specimen”. Again, I’d defer to an actual clinician on this.

  1. Isn’t most of this just duplicating information in either Task.status or ServiceRequest and DiagnosticReport? Do we actually need to track this in Task?
  2. If we need this, we should probably consider adding a “Canceled” status.
  3. Since the binding for this concept isn’t specified in the FHIR spec itself, i.e., there’s no provided value set, where should these concepts be kept? Should we use the CIEL Test Status (163725) and perhaps talk to @akanter about adding other values that we need? Or is there another terminology source we can use for this?
1 Like

Thanks so much for the feedback! Here are some of my thoughts:

Good point, there’s no point in mapping a state that’s not supported by OpenMRS. My suggestion was to set the Task status to draft, and not the ServiceRequest status, since in my mind Task corresponds to the Lab order request, and ServiceRequest corresponds to the OpenMRS Order object.

Yup, good find!

Yeah, I’m not sold on implementing this field for now, as long as we are able to use Task.status, Order.action, and the DiagnosticReport implementation to support storing the status information necessary for the Lab Workflow use case.

1 Like

That makes sense to me.

I would avoid conflating the status of the request (placer) and status of the result (filler). The order action reflects the type of action being taken (e.g., is this a new order, a revision of an existing order, or the discontinuation of a previous order) and is independent of the state off the request (where the request is in the lifecycle of a request – regardless of whether the request Itself is to change something or stop doing it). The status of the fulfillment of the request is yet another state.

We choose to track the status of a result independently of the request (order), since an order may lead to many results (e.g., a complete metabolic panel is a single order that leads to over a dozen individual lab results).

It’s helpful not only to record the status of results, but also the state of the request (order). For example, an order for a full hemogram leads to a panel of blood tests, including white blood cell count, hemoglobin, hematocrit, and platelet count. When two of those lab results are complete and two are still being processed, the status for some of the results is “complete”, while others are “pending”. The original order would be “in process” until the last component was reported.

Someday, we’d like to support “draft” status for encounters & orders, but these will have no associated results – just like a draft email world never have a response.


If the “OpenMRSTask.status” field is mean to reflect the status reported by the downstream system (OpenELIS in this case), I would recommend considering using Order.fulfillerStatus field (though not 100% sure if this would be the right thing or not). Looking your proposed mappings for Lab Workflow, you’d already have the “RECEIVED, IN_PROGRESS, and COMPLETED” states. The two states missing on fulfiller status would be DRAFT and REQUESTED. Admittedly, I’d be reluctant to add those two fields since they aren’t actual statuses from the fulfiller.

We are using fulfillerStatus to track a similar thing as part of the Lab Workflow OWA, and this could potentially lead to some compatibility between the two.

Unfortunately, we’re stuck targeting platform 2.0.5, which doesn’t have the fulfillerStatus field. Ideally, we’ll have a layer for 2.2 that will support fulfillerStatus properly for implementations on that platform.

Perhaps irrelevant at this point, but has any consideration been given to unsolicited responses? In our environment, the gateway sends back all results from the lab regardless of the source being the EMR or coming in on paper from a non-EMR clinic. As long as we can relate it to the patient, if we can’t locate a request we need to create what we can from what’s in the OML.

That’s a good thought for the future. For our present purposes (a limited demo of the ability to manage lab orders with OpenELIS and FHIR), I don’t think this is something we need to worry about, but certainly for a more general-purpose case, it would be.

1 Like

Here’s the related Jira issue: