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:
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:
Copy TestOrder to ServiceOrder. Should this be an abstract class?
Make TestOrder extend ServiceOrder and gut it (inheriting all of its functionality from ServiceOrder).
Add ReferralOrder as another extension of ServiceOrder.
Add other classes for subclasses of service order as needed.
When we need order for medical equipment or diet orders, we create separate classes (siblings of DrugOrder and ServiceOrder) to align with FHIR.
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.
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.
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.
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).
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.
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.
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.)?
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.
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”
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.