Referrals in OpenMRS

Trying to get referrals into OpenMRS core and re-reviewing this thread, it seems like we could take a small step that could meet the needs of @jdick and @angshuonline:

  • Introduce ServiceOrder
  • Extend and deprecate TestOrder (the intent would be to eventually replace all references to TestOrder with ServiceOrder)
  • Add location to ServiceOrder, in alignment with FHIR’s ServiceRequest
  • In the database, we would adding order_test.location, with the goal of eventually renaming the order_test table to order_service.

ServiceOrder would become the preferred class/resource for tests & referrals (matching FHIR’s approach) and we’d slowly phase out use of TestOrder.

Does this sound like a viable way forward (initial step) to others?

/cc @wyclif @dkayiwa @ibacher @jdick @angshuonline

I’m a little wary about deprecation and talk of removing TestOrder. Presumably a TestOrder and a ReferralOrder are 2 different things still conceptually, even if they don’t necessarily have different content. In OpenMRS, we could have both of these represented and unified with a parent class or interface (e.g., TestOrder extends ServiceOrder) without the need to deprecate or remove the TestOrder class itself. Then, we can start working with ServiceOrders generally, but still allow all existing code to deal with TestOrders as they always have. Thoughts?

Fair point, @mseaton. Order types need to be discriminated for a variety of reasons:

  • Order selection – filtering search results to specific type(s)
  • Model – drug orders have different properties from test orders
  • Behavior – APIs can differ between order types
  • Order form – which details apply to the order, which are required vs. optional, etc.
  • Order routing – drug orders to pharmacy, blood tests to lab, others may get printed, etc.

We want to discriminate between order types as needed for the reasons above, but do we discriminate with separate Java classes or with a few Java classes with properties to discriminate? Let’s consider the possible order types:

Order Type Examples
Drugs Medications, IV fluids, etc.
Tests Lab tests (chemistries, microbiology, toxicology, etc.)
Procedures (radiology, cardiology, pathology, gastroenterology, etc.)
Referrals Specialists, community services, etc.
Medical equipment Braces, walking aids, bedside commode, etc.
Nursing Hang blood products, frequency of vitals checks, etc.
Patient education/counseling Materials or guidance to give patient
Diet Limits on calories, protein, etc.
Activities Bed rest, up in chair, up as needed, etc.
Precautions Seizures, withdrawal, fall risk, etc.
Call orders Criteria for notifying provider
Code status / Advanced directives Honoring patient’s preferences on end of life care

It appears FHIR’s approach is to lump these into:

FHIR Resource Order Type(s)
MedicationRequest Drugs
DeviceRequest Medical equipment
NutritionOrder Diet
ServiceRequest Everything else (tests referrals, nursing, education/counseling, activities, precautions, call orders, code status) [ref]

So, what you’re suggesting is we can align with FHIR, but – as you suggest – create subclasses under ServiceRequest for order types that fall within FHIR service requests, starting with TestOrder and ReferralOrder:

  • TestOrder
  • ReferralOrder
  • NursingOrder
  • ActivityOrder
  • PrecautionOrder
  • CallOrder

So, we:

  1. Copy TestOrder to ServiceOrder. Should this be an abstract class?
  2. Make TestOrder extend ServiceOrder and gut it (inheriting all of its functionality from ServiceOrder).
  3. Add ReferralOrder as another extension of ServiceOrder.
  4. Add other classes for subclasses of service order as needed.
  5. When we need order for medical equipment or diet orders, we create separate classes (siblings of DrugOrder and ServiceOrder) to align with FHIR.

Did I get it right, @mseaton?


Thanks @burke for the detailed information. Certainly this seems like an approach worth exploring. There isn’t much downside in creating a ServiceOrder class and making TestOrder extend it, moving the relevant TestOrder properties into the parent class, as this is entirely backwards compatible. Then we can evaluate whether it makes sense to maintain and expand subclasses of ServiceOrder beyond this.


1 Like

Yeah, this seems like the most backwards-compatible approach to me. It may even be that what we really want to do is extend the model for Order a bit.

Order is already a concrete class with a specific table, so adding an abstract class into that hierarchy seems a little weird. I think in the ideal world, we’d be driving a good chunk of any business logic around orders from the OrderType property rather than from the Java class system (envisioning OrderType as being somewhat similar to the FHIR category field).

Hello @grace can you please remind me of the two order types you need implemented first as required from the MF squad to begin with (Followup from Platform call) so we can frame some tickets out of this.

Absolutely @tendomart.

So the imminent real-world use cases for orders are:

  1. Referral Orders (top priority)
  2. Lab Orders (lower priority)

Why: Ampath is funding design and development over the next quarter for NCD program designs in 3.x, which will include Referral Orders.

Lab Orders will be a need for 3.x very soon as well (right now we just have Medication Orders in the UI, but we are hoping to expand that to include Lab Orders soon too).

1 Like

way to go thanks. Let’s see how this goes.Iam gonna create an epic since we have a string of others orders to come later. Though there seems to be a couple of other things pending design at the moment.

1 Like

We have Lab Orders (TestOrder) already in core.

I think, though, that before we can create a ReferralOrder construct we need some basic modelling around what actually do we need to put in a ReferralOrder? Are those fields adequately captured by TestOrder / ServiceOrder? Without that, it’s hard to ticket the work (as anything other than design work).

1 Like

We want to add ReferralOrder, which needs to have a location property, which TestOrder should get as well. Both will be ServiceOrders.

I was proposing ServiceOrder as an abstract class extending Order with all the methods of our current TestOrder. TestOrder and ReferralOrder would extend ServiceOrder and implement getOrderType() with their respective types (Test or a new Referral order type). @ibacher didn’t like having an abstract class extending Order… but, if we head this direction and create classes for each supported order type, we could deprecate creating a typeless Order (eventually making Order abstract). This approach would be backwards compatible by maintaining TestOrder as a thin implementation of ServiceOrder, and allow FHIR to treat TestOrder & ReferralOrder along with future service order types as ServiceOrder (aligning with FHIR).

@ibacher, do you have an alternative approach in mind?

No… I suppose it’s fine to have an abstract class in the hierarchy there. Adding a concrete class would actually require a database migration (i.e., to move all the data stored in the test_order table to the service_order table). Really for these purposes I just wanted to stress that 2.5.0 will likely only have the ServiceOrder piece of this.

We discussed this proposal in the 2021-09-27 TAC call and there was general agreement on the way forward:

  • Copy TestOrder into a new abstract ServiceOrder and add location property to it. This will include adding location to the test_order table.
  • Refactor TestOrder to be an empty class that extends ServiceOrder
  • Add ReferralOrder as an order that extends ServiceOrder and introduces a new Referral order type. This will introduce a new referral_order table that looks just like the test_order table.
  • As they are needed, NursingOrder , ActivityOrder , PrecautionOrder , and CallOrder could be added as additional extensions of ServiceOrder . When they are needed, DietOrder and DeviceOrder would be added as new extensions of Order (alongside MedicationOrder and ServiceOrder ).

I’ve updated the description of TRUNK-6029 accordingly.

1 Like

Should the new location field map to OpenMRS location_id, concept_id or something else?

Great question, @dkayiwa.

It’s worth noting that, for the majority of test & referral orders, specifying a location is unnecessary because there’s a standard process in place – e.g., labs are done in the appropriate lab, cardiology referrals are sent to cardiology clinic, etc. So, we are only talking about when:

  • There isn’t an implicit/default location for the service (e.g., an “external referral” to services outside of your healthcare system)
  • You want to explicitly request the procedure be performed somewhere other than the standard location

I would expect an abstract list of locations (like departments, “Home”, “Extended Care Facility”, etc. just like FHIR’s service delivery location role types) would cover 90% of use cases and this would imply we could use concept_id (i.e., a concept set of abstract location roles). But these abstract locations could also be accomplished with location_id if one defined locations for the abstract locations (i.e., an “Abstract Locations” location with locations like “Home”, “Extended Care Facility”, etc. within it … or using location tag to tag abstract locations). Given there could be 10% of cases where implementations want to use a specific location (from their list of locations) and the abstract locations could be accommodated by defining locations for these, I’d lean to using location_id (which would be most intuitive anyway).

So, I’d say we go ahead with location_id.

Does anyone see a potential problem with allowing implementations to define abstract locations (like FHIR’s list of location roles) within their OpenMRS locations table when/if they want to order tests or referral to be performed at one of these abstract locations (e.g., “Home”, “Extended Care Facility”, “Outside Hospital”, etc.)?

/cc @jdick @angshuonline @mksd @mseaton @grace

@pmanko @mozzy Re: our conversation on this very value set.

What about pursuing the idea of having multiple possible location values, like we do for Obs values? E.g.,

  • location_id
  • location_concept

This complexity could be hidden from the user in much the same way that the Obs value is (thus if you say “the hospital lab” it might be a location_id, but “home” might be a location_concept)?

I considered this approach, but didn’t think the complexity for API usage might not justify the benefits. That is, if abstract locations (like “Home”) can be created as locations, then we’d avoid making location-specific concepts and avoid the complexity – e.g., if both location_id and location_concept are populated which takes precedence, clients don’t know if they’re going to get a Location or a Concept, etc. The benefit of this approach (use just using concepts instead of locations) would be localization support of concepts.

Given all this, perhaps a slight tweak of your suggestion might work, e.g.,

  • location_concept (FK to Concept)
  • specific_location_id (FK to Location)

Meaning we anchor on collecting location as a concept, using a value set as FHIR suggests & benefiting from localization. In those cases where someone needs to provide a specific (non-abstract) location, they could choose from locations and we’d store that as additional location info. Both of these would be optional fields.

1 Like

Makes sense. In that case, we will prob need 1 additional attribute “locationCode” which can have codes from the FHIR valueset, although I do not assume such details are needed. Another option is to use the “location tags” - and once you select. that, only the locations tagged with a specific tag can be shown.

this imo, will be closer to OMRS ref model.

If you would use concepts to indicate the locationCode, then we will have to have some other mapping or convention to show the list of locations that can entered in “servicerequest.locationreference”

at the same time, having ref to concept for codes is also ok as it provides means of mapping to different code systems.

After discussion on today’s Platform team call, we decided to implement service order (and thereby referral orders) location as a concept. Having a specific location (pointing to OpenMRS Location) can be added in the future if/when the implementation need arises.

1 Like