Proposal: Medication Dispense OpenMRS module

@ibacher what are your thoughts on adding individual concept sources in CIEL for things like “Medication Dispense Status Codes”, and then have the module FHIR 2 code around that when transforming from a OpenMRS concept to a FHIR code? Or is there a better approach?

Take care, Mark

Might be slightly off-base here, but we have a pretty generic mechanism for adding FHIR mappings for basically arbitrary concept sources via a small mapping table (unfortunately) that maps between the concept source name and the FHIR URL for it. So, yes, as long as we add those sources to CIEL or some other appropriate place, we should be able to convert them to “real” FHIR codes.

1 Like

Thanks @akanter , the “H7 Medication Dispense Status: preparation” looks perfect… sorry, I was trying to look up it myself but wasn’t sure where to look… I don’t think it’s automatically updated to OCL?

@ibacher where in the FHIR2 module should I look for examples of the small mapping table you mention?


Take care, Mark

The Hibernate definition is here and a very simple Liquibase change that we use to create the mapping for LOINC (eventually, I’m planning on removing those changesets and moving the configuration to Iniz, but my initial spike on adding FHIR2 to Iniz got very messy).


@ibacher, so fhir_concept_source is being created as a shadow copy of concept_reference_source (i.e., a copy of concept sources that the FHIR module can own/control)?

It’s not exactly a copy. For concept sources, we need the URL for the system. The table is really about providing the URL associated with each concept reference source (and this implicitly determines which systems we send via the FHIR interface).

Ah. Okay. We’ve talked about the need for a canonical_url attribute on our reference sources. Can we approach the fhir_concept_source table as a temporary extension of the concept_reference_source table – i.e., only adding in those things we wish were already in the core table and eventually folding these additional attributes into core?

Yes. That’s how I’ve always thought about it.

Hi all,

I have started the work in adding this functionality to core, and have a draft PR available for review which implements the initial design document.

In the process of developing this out, I’ve run into a few questions which I wanted to bring back here for discussion and greater visibility:

Question 1: How to handle the provider or provider(s)

The initial design called for a single “provider” attribute on the MedicationDispense object. This was to reduce the complexity of implementing the FHIR model, which rather calls for a set of 1-N “performers”, where a “performer” refers to a “function” and “actor”.

Now, the current FHIR specification defines the available functions as these:

Code Display Definition
dataenterer Data Enterer Recorded the details of the request
packager Packager Prepared the medication.
checker Checker Performed initial quality assurance on the prepared medication
finalchecker Final Checker Performed the final quality assurance on the prepared medication against the request. Typically, this is a pharmacist function.

At the same time, our MedicationDispense design also calls for the following related fields: dateCreated, createdBy, whenPrepared and whenHandedOver.

A possible alternative proposal would be to add the various “performers” and functions like this (this may not be totally accurate):

  • dateCreated, createdBy (User) - This would correspond to “dataenterer” above
  • Change “whenPrepared” to datePrepared and add preparedBy (Provider) - This would correspond to “packager” above
  • dateChecked, checkedBy - This would correspond to “checker” above
  • Change “whenHandedOver” to dateDispensed and add dispensedBy (Provider) - Not sure if this would correspond to “finalchecker” or if this is different?

Another alternative would be to create a separate table/entity for tracking the various performers on the MedicationDispense, which would support an arbitrarily flexible workflow and set of functions, which would be mapped to Concepts.

Question 2: How to handle note(s) / annotations

The initial design called for a single “note” attribute on the MedicationDispense object, which is just a String. This was to reduce the complexity of implementing the FHIR model, which rather calls for a set of 1-N “annotations”, where an “annotation” contains “author”, “datetime”, and “note text”.

However, it feels to me like the more flexible and detailed model is one we would want to support. Thoughts on adding 0-N association between MedicationDispense and MedicationDispenseNote, which would be an OpenmrsData object with “provider”, “noteDatetime”, and “contents” (or similar named fields)? Alternative ideas?

Note, this is potentially something we could punt to phase 2, leaving “note” out of the data model entirely and adding it in at a later stage.

Question 3: Should the service method void and recreate on edit

Do we want to set up the MedicationDispenseService to ensure that - if a MedicationDispense object is saved with edits - that it first voids the existing object, then creates a new clone with the edits, in order to save this audit history? Do we want to retain a “previousVersion” between the two if so? This seems like the right thing to do, though it is not done consistently across the OpenMRS API (patient, person, person_name, person_attribute, encounter, patient_program, patient_state, relationship, etc. do not have this auditing in place).

Question 4: Should we add any indexes to the data model

Does the medication_dispense table need any indexes added to it to ensure it performs well.

Question 5: Do we need to re-think the dosing fields

The DrugOrder API in OpenMRS supports a flexible dosing model. There are standard relational fields for SimpleDosingInstructions such as dose/doseUnits/frequency/route, but there is also support for FreeTextDosingInstructions and any other custom DosingInstructions that an implementation wants to support. In FHIR, the dosing instructions are represented by a “Dosage”, which is modeled similarly but has some differences. Should our model for adding dosing-related fields to MedicationDispense be modified in any way to ensure that it can support the necessary use cases and mapping to FHIR?

There is a lot above, and probably too much for one talk post. Interested in feedback from @burke , @ibacher , @mogoodrich , @MekomSolutions , and anyone else who is interested in this feature moving forward.

Thanks, Mike

So I had a good conversation with @mogoodrich and these are some of the preliminary answers we are gravitating towards to these questions:

We retain the single Provider field on MedicationDispense, but we rename this to “dispenser”. This would map to an actor in the FHIR model with a null function (per FHIR spec - function is allowed to be null and “It should be assumed that the actor is the dispenser of the medication”). So this actually maps well to a single Provider attribute on MedicationDispense to represent the overall Provider (likely Pharmacist) responsible for the dispensed medications.

If we ever need to add support for additional actors for packager, checker, final checker, we can add these in when those use cases arise, but for this phase we’ll leave those off.

I do think this should be an additional mapped object / table in the data model. It would be good to get others to consider this and what the properties of this should be named.

I think this should be be no, as the MedicationDispense is really intended to be modified over time (eg. the status will change, the dates of preparation and hand out will get populated, etc.) as the dispensing is taking place).

Likely yes. We should review other domains and also the use cases for likely queries and predicates.

These seem fine, and better to align with the OpenMRS DrugOrder model for consistency, and evolve these together down the road if need be.

Still interested in others thoughts.

1 Like

I have updated my PR to remove the single String note property, and replace it with a new modify List property on MedicationDispense , which maps to a new table in the database. Please have a look at this commit: TRUNK-6071 - Add MedicationDispenseNote to enable 0-N notes associate… · openmrs/openmrs-core@cbde2ce · GitHub

As I reviewed this just now, I noticed that we do still have a residual “note” table in the data model. I don’t recall how or if that was used in previous versions of OpenMRS, but it doesn’t appear to have any use any more. We could resuscitate this table (which currently has optional foreign keys to patient, encounter, and obs), and add a new optional foreign key to medication_dispense. This would result it something more akin to the FHIR Annotation that we are trying to model here, I think. Interested in opinions on this - @dkayiwa , @mogoodrich , @ibacher , @mksd or others who may recall the history of this table and the Note object in OpenMRS.

The “note” table appears to have been removed in this ticket, i.e., it wasn’t really used anywhere so it was removed in 2.1. That does seem very similar to an annotation and it might make sense to bring it back rather than backing into recreating it? (I have no idea what the table was used for; it already exists in the first commit in Git history).

@burke Thoughts?

The Note class was not properly designed and has not been used for many years. There was an attempt to properly redo it [TRUNK-4106] Implement Note the right way - OpenMRS Issues and a wiki page that accompanied it Notes within OpenMRS (Design Page) - Documentation - OpenMRS Wiki but no body ever got interested in moving it forward.

I haven’t looked at the Note object, but, in general, I think it would make sense to design an “Annotation” object that maps to a FHIR Annotation rather than create a specific “MedicationDispenseNote”

Take care, Mark

From reading the ticket, it sounds as though the idea was the the Note table would handle the sorts of things we’re doing with Visit Note, etc. which is currently just stored as an obs (and also allows, e.g., uploading a PDF as a complex obs), so it seems as if OpenMRS may have moved beyond the need (or real value) to having a separate table to capture this… unless I’ve missed something.

FHIR’s version of a general “notes” feature is built on top of the DocumentReference resource with Attachments containing the actual data. This is obviously quite a bit more structured than what we currently do and implementing that would likely require a new domain.

FHIR’s Annotations are definitely different from a visit note. The idea is to capture free-text information relating to a resource, e.g., stuff like we use various fields labelled “comment” for. If we want to move towards standardising that, maybe we do need something similar to the current “note” table to basically just tie a string and author information to a context (since annotations may not all be part of the same encounter, e.g., a pharmacists comment on an order, etc.).

Is this a field we need for the MedicationDispense MVP or a discussion we can defer for a bit?

1 Like

Per what @ibacher says above, we could potentially not merge in the MedicationDispenseNote table for starters, and see how the requirements flesh out.

We do have some requirements for a “note” in the Dispensing app, but it’s not clear if this is MVP, and it’s also quite possible that we will want to store this on the Order/MedicationRequest, not on the MedicationDispensing.

See image here:

I’d be fine on holding on adding note in the short-term until we have the requirements more defined, which hopefully should be in the coming months.

Take care, Mark

Following up on this, since I’m in the process of trying to implement this in FHIR2 right now, I recall that we added a “unique_id” column (uniqueId property) to concept source in OpenMRS 2.1.0. Is this intended to be used to serve the same purpose as “canonical_url” - i.e. can we assume that if canonical_url were to go anywhere, it would go here? Or are we thinking we’d add yet another column to identify a given source? (FYI, we already have “name”, “hl7_code”, and “unique_id”.) @burke ?

I can’t recall the context of adding concept_reference_source.unique_id to the data model off the top of my head, but a varchar 255 called “unique_id” surely implies you are correct that this would be the attribute for a canonical URL. “Unique ID” may have been chosen to allow for any of the universally unique naming schemes (e.g., canonical URL, OID, URN, etc.)… but I believe the world (esp HL7) is settling on canonical URL as the best practice for this field (since DNS replaces the need for a another central authority for control the namespace).

This does vary quite a bit depending on where the code system is used. Certainly FHIR uses canonical URLs, but these are not used in all domains, e.g., in DICOM concept sources are still identified by OID. (DICOM compatibility was what was behind adding the unique_id field–this is actually why I didn’t use the unique_id field to provide this information for FHIR2). And, of course, for HL7 v2, we do still need to capture the HL7 v2 spec-defined code for the code system (or it’s OID as a fallback).

I don’t think we’re really getting to a world where DNS controls things. Even FHIR uses URIs that are not valid URLs and have no obvious recourse to the DNS system. For example, FHIR still uses OIDs as its preferred identifier for terminology systems not explicitly defined in the FHIR spec. If I had strictly followed FHIR’s guidance, CIEL codes should really be reported with a system of urn:oid:2.16.840.1.113883.3.7201 (IIRC, this was briefly the case). There are likewise few other “well-known” code systems where FHIR similarly uses URNs rather than URLs, e.g. for ISO-defined code systems like ISO 3166 (urn:iso:std:iso:3166). IETF BCP values similarly use a urn scheme like urn:ieft:bcp:47. However, I don’t know how widely-used these identifiers are outside of a FHIR context.

The point here is that I do think adding canonical URLs (or URIs) directly to concept sources is a net-win for FHIR support and probably useful, it’s not clear to me that there is any single system for uniquely identifying concept sources that can be used in any context.

I might suggest the following changes make some kind of sense:

  1. Rename unique_id to oid or object_identifier (unique_id was a poorly chosen name).
  2. Add a fhir_uri field (or something similar) to the concept_source.
  3. Drop the fhir_concept_source table altogether.