Backend Support for Service Delivery Queues / Workflows

As the design team approaches the time to hand off the designs for service delivery queues, we need to start considering backend support for a patient’s status within the workflow (e.g. waiting for triage, waiting for clinician etc.). At first glance the program workflow seems like a natural fit. However, one odd requirement is that a patient must be enrolled in the program before they can be assigned to a workflow within that program. It seems heavy handed to always require a patient to be enrolled in a program to make use of a workflow that is related to that program. Would be interested to hear thoughts on this as well as possible solutions?

For those interested, please see video from Ciaran of latest iteration (presented during O3 squad call) : Microfrontend Meeting - Indiana University

@ibacher @corneliouzbett @burke @mseaton @mksd

Surely it shouldn’t too much of a big deal to have a piece of code that makes sure the patient gets enrolled if they aren’t when needed by the workflow? And likewise, disenrolled on the other end.

1 Like

Say we have a generic outpatient workflow. Do we really want to force a patient to be enrolled into “Generic Outpatient Program” just to use the workflow? I realize we could but it feels like we don’t have the data model right.

I personally don’t think using Programs/Workflows/States is the best way to go here. And I don’t think we want to force everyone who wants to leverage service delivery queues to have to do so via program workflows. Can we describe a bit more what we need the API to support?

Essentially, we want to able to assign someone to a workflow state both manually (and eventually through some sort of conditions/logic). The UI will use knowledge of that state to assign the patient to a queue. The UI needs to keep track of:

  1. Which patients are in the queue
  2. How long the patient has been in the queue
  3. There must be a way to set where the patient is in the queue (this may or may not correlate to to when they were entered). One specific case is say a patient is accidentaly moved from one state to another and then has to shifted back. We don’t want to force the patient to the back of the line.
  4. The priority of the patient: high/medium/low

@grace @eachillah @aojwang can you think of other requirements?

Seems like workflows are useful when there is a specific series of states that generally follow one after the other. If the state is independent and simply either present or not, it seems more like a flag. If the duration of a patient state is what matters and this is dependent on a combination of variables (time in the state, whether manually placed or not, etc.) then it doesn’t sound like a workflow… it is more like an algorithm.

1 Like

Soapbox: The key here is “through some sort of conditions/logic”. I have NEVER worked with a PM or Software team that kept their issue tracker statuses perfectly updated manually. → We cannot expect overburdened clinical staff to keep patient statuses updated manually.


  1. Ability to change workflow state manually
  2. Ability to change workflow state through conditions/logic (e.g. “form X completed”).

FWIW @akanter @mseaton: here is an example of a design JJ is referring to. You can see the Wait, Priority, and Status examples JJ mentionend in the requirements list above.

@ddesimone I know you have been interested in NCD workflows as well. Do you have any further requirements that come to mind?

@jdick what do you think of @akanter’s point above? I think it’s a good point, though perhaps not the priority for now. Eventually we will probably want to support “labels” on patients, where a workflow is not so much algorithmic as it is boolean (e.g. imagine an HIV pediatric patient who is being seen by OCP and Nutrition, vs HIV patient who is not… these labels are workflow-esque in the clinic, but can be branching/not linear).

FYI @slubwama

The patient queue module @slubwama mentioned is worth a look as it allows us to to capture something like a status, a priority (as an integer) for a patient as well as where the patient is, where they just were and were they are next scheduled to be. This might be a good basis for exactly the kind of screen we see there.

@slubwama: I’d like to ask about some of the modelling I see in the module:

  1. The PatientQueue record seems to have a link to an Encounter. What encounter is this? Is there some workflow a patient is expected to go through before appearing in a queue?
  2. The status field seems very important. As you can see from the above mock-up, we’ve imagined quite a few plausible statuses, but the status is tied to a enum of either PENDING, COMPLETED, and PICKED. I realise we could free-text things leveraging the status comment field, but it seems like there are likely to be a fixed number of statuses for any given queue, just possibly more than 3. Could we look at migrating this field to supporting additional status types and maybe dropping the enum?
  3. priority, another key field, is represented as an integer, also with a comment. This might seem better used for something like an enum as suggested by the design above. How many levels of priority is it necessary to support?

I also would like to hear the thought process on the data model. Is the module currently in use in a production environment?

@ibacher Here is my response to the questions

  1. The encounter attachment was used as a way to move back to the encounter(s) a provider managed during the queue session. This can be rethought and find appropriate use or design. It is also important to note that it is not mandatory.

  2. On The status, I agree. During the design and development, this is one where we had lots of discussions with @dkayiwa a suggestion he offered for it to be as an enum. This can be free text to allow for more options.

  3. About Priority that can be changed.

@ibacher do you mind creating the needed changes as tickets here

1 Like

@aojwang This is the backbone for the POC implementation in UgandaEMR.

Glad to do so! I’ve got a few other questions too. I can keep asking them here or maybe we could arrange a quick call to demo what this looks like?

  1. What’s the difference between “picked” and “completed”?
  2. What’s getting stored in visit_number? (it’s a little odd that it’s a string)

One thought that occurs to me is that maybe we can better capture things if we add a new class to the domain, so, e.g., we have a PatientQueue to record the patient being in the queue and then one or more PatientQueueStates attached to the PatientQueue where we could track, e.g., how long has this patient been in this state? (I’m hoping that’s a good way of genericizing “picked” and “completed”).

@jdick I seem to recall some talk about capturing notes on patients waiting in the queue. Did that make it to the final design? If so, are these notes something that should become part of the clinical record (and so stored as a obs or similar) or can they just be attached to the queue record (and so be a bit more ephemeral)?

I think a helpful start (as suggested by Ian and Antony) is to do a design session with Ciaran as well as the Uganda team. We are floating the idea of working on improvements to this module during the openmrs conference hackathon (if there’s interest from the community). Perhaps, we could schedule such a session this Friday to help kickoff the hackathon.

1 Like

Here is the piece of code that generates the visit number. It’s a combination of date, location(first 3 characters), and next number in the queue e.g 02-12-2021-MTR-002. The documentation here is a little off.

  1. When a patient is in session with a clinician you want to block them off but not regard them as completed. So that’s when the picked comes in
  2. The visit_number is an identification for the patient on that day. when they get to check-in. The logic makes sure that one is only offered for a patient on a given day when they are at a health care facility.

@corneliouzbett It is a string because we wanted a way of resetting patient visit numbers (queue numbers) without deleting them. So since strings are easy to control on what you save in there, hence the choice at that time.

@jdick I agree. The module can be redesigned to suit more use. The Hackathon is a great idea.

When do you reset visit numbers/What triggers resetting of visit numbers?

From the data model, I notice field date_picked, does it mean patients queue for several days(remaining patients in the queue push to the next day) and If so, how does the module handle which patient comes/administered first(ordering) factoring in the priority and visit_number?

Does the PQ module allow dynamic ordering based on the priority?

I have been trying to install the PQ module on our test instance(doesn’t include 2.x UI). Well, I have to install five additional modules;

<require_module version="${appframeworkVersion}">org.openmrs.module.appframework</require_module>
<require_module version="${uiframeworkVersion}">org.openmrs.module.uiframework</require_module>
<require_module version="${uicommonsModuleVersion}">org.openmrs.module.uicommons</require_module>
<require_module version="${appuiVersion}">org.openmrs.module.appui</require_module>
<require_module version="${coreappsVersion}">org.openmrs.module.coreapps</require_module>

It makes sense when you already using 2.x UI But for those implementations interested in the rest endpoints, it doesn’t. Going forward, we should think of packaging differently i.e one with the legacy UI(2.x) and the other with just rest & API excluding the UI stuffs. Just noting down this.

1 Like

If we’re trying to solve tracking patients through clinical workflow, placing them in queues doesn’t seem like the correct approach (for that specific need); since, it requires mutually exclusive lists. This is more appropriately modeled (IMHO) as a state of the visit. FHIR has support for this in Encounter.status.

Tracking/timing stats/etc. could be done using Lists (Cohorts?) generated from querying the visit status.

When we speak of labeling patients as “priority” is that specific to the specific queue (i.e., they’re only priority when they are waiting for a lab test, but not when they are waiting to be seen by the provider)? Or is this a property of the visit (e.g., a visit attribute that marks the visit as urgent)?

As I understand the designs, “priority” is there for something like triage status. I’d tend to think, then, that it’s more a property of the patient’s state than of a visit per se, but I’m not sure it’s a clear either / or (FHIR’s Encounter.priority actually seems to me poorly modeled, which implies it isn’t widely used).