Drug Orders: Order Templates modelling

I’m just coming back to this thread because I’m just now noticing that the refapp is including an ordertemplates module, which I am assuming is the byproduct of the above conversation.

Is anyone using this module? I’m still a little confused as to why we need this separate module to introduce an order_template table, which is essentially just a way to link a concept or drug orderable to a free-text (likely json) template string.

We already have exactly this thing in core, in the order_set_member table. Using this was discussed in the thread above, and it seems at one point like this was going to be used, but then ultimately it wasn’t?

@burke / @ibacher / @samuel34 - can you guys summarize here what was decided in terms of why this module was created and what it offers vs. using and/or adapting the core data model?

I think there are a few things:

  1. We needed to iterate on the API, i.e., we needed to be able to get order templates by the concept or drug being ordered, but the OrderService doesn’t provide mechanisms to do that.
  2. Order sets add a level of complication to the API that we didn’t need for this feature—and we’d be abusing the concept to slot the templates in to single-item order sets. The goal of the order templates is to associate a particular drug with various metadata about the form(s) and dose(s) it is available in.
  3. Many implementations are hesitant about updating versions of core for both good and bad reasons; part of the goal with O3 is to be able to layer the new UI on top of an existing implementation; making these changes in core would require upgrading the core version, and this could lead to hesitancy in adopting O3.

Thanks @ibacher .

So, assuming we want a first class order_template domain object to exist, and this has now been sufficiently iterated upon, it would seem straightforward to just add order_template to core?

Yeah, that’s fair. I was more envisioning that we could just have one core order_set called something like “Single Order Templates”, which would then have as many members as needed, each of which would represent the same thing as one row in the new order_template table provides. The order_set would just be a grouping of these, it wouldn’t require creating single-member order sets for everything.

Perhaps order templates are conceptually different from order set members, in which case having these totally distinct and unrelated seems fine. But if actually it would be more accurate if, say, OrderSetMember extends OrderTemplate in core, then that 's something we might want to consider evolving into.

I get this, though that’s only really true if we are talking about O3 as a whole, and not about some optional feature. I would think it’s perfectly acceptable to say - if you want order templates within the order basket, you need to upgrade to OpenMRS xxx, or run a bridge module in the meantime.

1 Like

Yes. I think we’d like to see some results with lab orders and maybe referral orders first, but, yeah.

It would probably make more sense for each order template to be treated as an order set with a single member, then we would have a unified structure for both single-order sets (perhaps the majority) and multi-order sets (for well-defined protocols).

Order templates are currently a non-optional feature if you want the order basket to work. That may not be the desirable state of things (maybe we should be searching the concept dictionary directly?), but its currently how the flow works.

Oh! So the intention is that the order_template module gets incorporated into core at some point and we figure out at that point how it does or does not relate to order_set_member?

I’m not entirely sure I follow. We already have domain objects for order_set and order_set_member in core. And order_set_member has properties for orderTemplateType and orderTemplate, which is typically going to be some sort of structured (json) text in exactly the same way that this new order_template table has done. Is there a plan for how these are intended to evolve together? It feels…messy.

That’s surprising. So if I am not running the order_template module and/or I have no order templates defined within this module, I can’t order drugs with the order basket? Really?

One more thing. Talking to @aojwang , it is clear that we need to understand the relationship between a drug REGIMEN, the ingredient concepts and the dispensed drugs. Right now we have separate concepts for each of these, with the last one in the DRUG table. There is an explicit link between the drug concepts in the CONCEPT table and the dispensable drugs in the DRUG table. However, the regimen concepts (in the CONCEPT table) are not directly connected to either of the others. The REGIMEN concepts have RxNORM or SNOMED codes for the ingredients, which theoretically can be used to link back to what the patient was given. However, this is not easy.

It is important for reporting to be able to document that a patient is on a particular regimen (HIV, TB and Oncology are particular examples). A regimen can be dispensed in numerous different ways… a three drug regimen could be dispensed as A + B + C pills, or an A/B pill + C pill, A + B/C etc… Knowing that in a particular pharmacy that the regimen is given as A/B+C seems to be a pharmacy decision. Even if we ORDER using a template which makes it easy to select the components, wrapping them together for coding as a single concept needs to be designed. This is particularly true if pharmacy is making the final decision on dispensing.

@burke and others, can we have a design session about this?

@burke/@aojwang/@grace, on the SMART guidelines call today they were working on modeling workflows that include not just prescribing but also administration and dispensing of medications. I mentioned that I thought OMRS had some use cases that involved things like pediatric dosing (mg/kg) or that required dispensing in ML or bottles. Would it be possible to bullet point those use cases so that Bryn and others could ensure that their test cases are robust enough?

Hi all,

I’d like us to revive the Drug Order Templates feature. I’ve pulled the 2022–2024 discussion together into a V1 requirements wiki page. A few decisions need the community’s input. Is this the right approach?

  • A template pre-fills the order form for one common way of ordering a drug. It assists; it does not restrict.

  • A template is not mandatory to order a drug. No template → the basket opens a normal blank form, and the drug is fully orderable.

  • Deferred → weight-based/pediatric dosing, personal favourites, and order sets/regimens.

  • Please sanity-check the 4 seed templates (paracetamol, amoxicillin, amlodipine, metformin): does each represent the most common way a clinician orders them?

  • Please check out the wiki and point out anything else needing clarity.

Thanks all, and I hope we can get this moving forward.

cc: @burke @ibacher @akanter @mseaton @dkayiwa @dennis @fanderson @jayasanka

2 Likes

The O3 Drug Order Templates page is impressive. It does a terrific job of bringing together the history of discussions into a reasonable approach.

A critical target for V1 is to ensure we don’t create a drug-specific approach to templating orders. This is accomplished primarily via the template type as a versioned URI. Supporting a template “type” allows templates to flexibly match the form structure. We know forms content will vary by order type, for drug orders by dosing instruction type, and – hopefully in the future – even from one orderable concept to another (e.g., prompting clinicians to enter whether or not symptoms exist before ordering a mammogram, making clinicians confirm the patient has an ECG within the past year or one has been ordered as they refer the patient to Cardiology).

To ensure we support flexible templates, I’d propose that V1 should target simple drug orders and at least one other order type (e.g., simple test orders).

FWIW, I’m assuming we would create an OrderTemplateHandler<TemplateType> interface that allows type-specific behavior. For example, return a draft Order from the given template or return a string representation of a given Order based on the given template for display to the user.

1 Like

Following the wiki/Talk discussions and a review of openmrs-module-ordertemplates, it looks like most of the backend foundation already exists. The main work is integrating it with openmrs-esm-patient-chart (medications/common library), closing the remaining frontend gaps, and enhancing a few backend capabilities.

I thought of coming up with this Drug Order Templates architecture: Drug → Template Resolution → OrderTemplateHandler → O3 Order Draft → Clinician Review/Edit → DrugOrder The idea is to keep the architecture generic and type-driven, while keeping V1 focused on drug orders, with blank-form fallback when no template exists. Does this seem like the right direction based on the ongoing discussion?

Yes; however, I don’t want us to get too committed to a specific process to get to a template. There are many ways templates can be used in the future, including being baked into order sets, parts of decision support, formulary suggestions, etc. The most common path and first to tackle is the happy path of having one (sometimes more than one) way(s) to place an order and, using templates, allow users to place one of these ready-to-go orders into their cart with a single click instead of having to navigate an order form.

There are some important components to this that aren’t obvious in the diagram. For example, rendering an order template in a way that user’s can understand it. Once in a cart, I suspect an order would render just as if the user had used the order form to fill in some/all of the fields provided by the template. But the decision (and need to render the template) may often be happening before the order reaches the cart. This isn’t always going to be in a “template picker”. It’s more likely that we’d want to be able to render orderables in the search results as order templates. For example, you search for “aspir” and, instead of a choice for “aspirin”, you see a choice for “aspirin 81 mg by mouth daily”. Future use cases might be in the context of an order set or a decision support rule suggesting an alternate order. In any case, the common need is the ability to render the order template with pre-filled default and blanks for items that are missing or lack a default value (e.g., “metoprolol {dose} mg by mouth {frequency}”).

2 Likes

I actually think this is some of what I wanted to avoid, specifically, the idea that we go Drug → Template → Order Draft. Rather, we should be treating templates, roughly, as orderables, so it’s more like:

Drug → Order Draft (no template, no defaults, as works today)
Drug Order Template → Order Draft (template defaults and limits)

E.g.,

  • Amoxicillin 500mg
  • Amoxicillin 500mg, TID, 7 days

Where the first is from the drug table and the second from a template. In this way, there’s no separate “choose template” step; rather the template is just another selection a user can make.

Getting all of this working with order sets proper probably requires us to break-down the order basket a bit so there aren’t separate search areas for “Lab Orders” or “Drug Orders”, but these become filters we can apply to the search, which is a bigger change.

1 Like

Following the feedback during last week’s squad call, here are some further changes for review:-

Example 1 · Drug template — Amoxicillin 500mg

Template: Amoxicillin 500mg — 500mg — tablet → 1 tablet by mouth every 8 hours for 7 days · 21 tablets, 0 refills · bacterial infection

1) Search “amox” — the one search box returns the orderables that match. There is no second blank row for the same drug. Amoxicillin 250mg/5mlis an example with no template. Every row carries the same two actions: Add and Edit.

2) Add — one click, no interstitial screen. The order lands in the basket fully populated from the template, tagged New: DOSE 1 tablet — Oral — Every 8 hours — QUANTITY 21 tablet — Complete the full 7-day course. / INDICATION Bacterial infection Nothing is signed. The clinician reviews and signs deliberately.

3) Edit — opens the standard order form, with every field pre-filled: dose 1, unit Tablet, route Oral, frequency Every 8 hours, duration 7 Days, quantity 21 (Auto-calculated — 1 × 3/day × 7), refills 0, indication Bacterial infection. The clinician changes what they need, and Save order returns it to the basket. Every field stays editable.

Example 2 · No template — Amoxicillin 250mg/5ml

The same drug concept, a different formulation, and no template authored for it.

1) Search “amox” — it appears in the same result list as its templated siblings, as a bare row: Amoxicillin 250mg/5ml — 250mg/5ml with no second line, because there is no template to render. It carries the same Add and Edit actions. Nothing is hidden or de-ranked for lacking a template (see first example above)

2) Add — the order still enters the basket, but tagged Incomplete in red rather than New, with the unfilled fields visibly blank: DOSE — Oral — Once daily. Sign and close is disabled until it’s completed, so an unfinished order can’t be signed by accident. Add stays available so the clinician can queue it and finish later in the same visit.

3) Edit — opens the same standard order form, empty. The clinician fills in the dose, duration, and quantity themselves — exactly as today’s behaviour.

Example 3 · Test order template — Renal function panel

Test templates work the same way. Add puts it straight in the basket ready to sign, Edit opens the standard lab order form pre-filled with its priority and instructions. Same search, same two actions, same rules.

Example 4 · Order Set — Hypertension (New diagnosis)

1) Search — Its members don’t appear separately, and it also surfaces when you search a member (typing renal for example, returns a lab or amlodipine returns the drug and this set) - see example above

2) Add — takes the set’s authored defaults straight to the basket: Amlodipine 5mg under Drug orders, Renal function panel under Lab orders, footer Sign and close (2). For the common cases, the clinician would not need to open the set at all.

3) Edit — opens the set panel to choose before committing:

  • First-line antihypertensive (choose one) — Amlodipine 5mg (default), Hydrochlorothiazide 12.5mg, Enalapril 5mg, each showing its own template and prescribing note; picking one replaces the other. Atorvastatin 20mg sits here as optional.
  • Baseline workup (choose any) — Renal function panel, Lipid profile, Fasting blood glucose, Urinalysis, ECG (optional), each with its member tests listed.

cc: @burke @ibacher @akanter et.al., will appreciate your feedback.

I am currently not able to see this on the demo server since no templates are showing. I did notice that when I “pin” an order that I don’t see all the metadata associated with that order (such as indication) on the list of pinned drug orders.

I am also unclear on what is happening with indication. I don’t like a generic indication for “bacterial infection” as this will always be chosen rather than recording the actual infection. I probably need to better understand what we are doing with indications, how they are being recorded in the database, etc. I’ll followup about that separately.

@akanter These are just mock-ups; nothing is built as yet - but you can interact with this work here: https://openmrs-order-templates.surge.sh/.

2 Likes

Hello OpenMRS community! :waving_hand:

We are a student development team from the University of Moratuwa, Sri Lanka, working on Drug Order Templates in OpenMRS O3.

We are currently in the initial research and analysis phase, reviewing the existing drug-order workflow, the proposed Order Templates model, and previous discussions related to Drug Order Templates.

We have also prepared our initial project proposal, outlining our planned scope and objectives:

We would greatly appreciate any feedback, suggestions, or relevant resources from the OpenMRS community as we move forward. :raising_hands:

Following up on the Drug Order Templates proposal shared here, @u_wickramasinghe’s team mentioned that, and while reviewing the current state of openmrs-module-ordertemplates more closely, they believe they’ve found a few gaps between what’s already built and what the V1 design in the requirements doc describes.

Rather than assume and start building around those gaps, could you please lay them out here and get a sanity check from folks who have participated here on this discussion before we finalize our implementation plan.

@u_wickramasinghe could you each write up the specific gap(s) you found, in this format:

  • What’s missing or different: (e.g. “the ?drug= endpoint doesn’t return X” / “there’s no support for Y in the current schema”)
  • Where you confirmed it: the specific file, class, or endpoint you checked in the module (a link or path, not just “we looked at it”)
  • Whether it blocks V1 as scoped, or whether it’s something we could work around in the frontend without a backend change

Once we have that list, we have two questions for the community:

  1. Are any of these already known/tracked somewhere (JIRA, GitHub issues) that we should be aware of, rather than re-discovering?
  2. For gaps that are real: should closing them be part of this project’s scope, or should we file them as separate backend issues and work around them in the frontend for V1, similar to how the known search-parameter issue mentioned in the requirements doc was handled?

@veronica @burke @ibacher: tagging you since you’re closest to both the requirements doc and the module’s history; we’d really value a quick gut-check on whether what we’re seeing matches your understanding of the current implementation, before we can lock in a work breakdown.

Once this is sorted, we can figure out the milestone/task breakdown, so it’s visible before they start implementation rather than after.

I don’t think this has ever gotten real use, other than we sort of need the API for the way the frontend currently works. Roughly speaking, the idea for this project is to completely ignore that module or, if you like, treat it as a ground-up re-write with the functionality specified in the project plan.

The way that module thinks about ordertemplates is, in many ways, exactly the opposite of the way we want order templates to work, i.e., that module is built with the assumption that we start from a drug and then find matching templates for that drug, but, for the most part, we actually want to return templates instead of the drug, if they exist and we want to be able to embed templates in order sets that are, in a way, their own templates.

Nothing in this project is tracked anywhere other than the Wiki. Part of the task here is uncovering this stuff and ticketing it. Happy to help figuring that out.

From my perspective, at least, the primary goal of this project is getting the backend “plumbing” for the templates right. How we display them, etc. shouldn’t be hard to work out from that.

1 Like

Thanks Ian. Now that I’ve gone through some threads, yes I agree. So basically what we would need is a “template first” search API approach if I understand the context properly. This then would replace what we currently have as 2 step process (1: v1/drug?q → 2: ordertemplates/orderTemplate?drug={uuid}) as the main contact point for the order search.

Yes, or more accurately something that can combine both a raw drug search with an order templates search and de-duplicate correctly. We anticipate that there will be templates for many common drugs, but less common drugs or drugs that are prescribed, e.g., with weight-based dosing, might lack templates, but still need to be searchable. One idea is to locate a “cross-domain” search in, e.g., EMRAPI.