Drug Orders: Order Templates modelling

Thanks, that’s helpful context. Since EMRAPI was just one example of where this could live, wanted to add a couple more options to the mix and think through the tradeoffs together.

One thing that gives me pause about EMRAPI specifically: it’s a shared dependency for a lot of modules, so if the merge/de-dup logic lived there, EMRAPI would end up depending on ordertemplates, a small, optional module, which is the reverse of the usual direction. That’d mean either every EMRAPI consumer picks up a dependency they don’t need, or we’d want an explicit optional-dependency pattern for it.

A couple of other candidates worth weighing:

  1. Put the merge logic in ordertemplates itself, as a new search endpoint that calls into the core Drug API. That keeps the dependency direction the normal way around.
  2. Hold off on backend merging for V1 and compose it client-side instead, two calls, de-duped in the frontend. O3 already does this kind of composition in a few places, and since we don’t have real numbers yet on result-set sizes or query volume, it might be worth deferring the backend work until we know we need it. (need further discussions)

Curious which of these feels closest to what you had in mind, or if there’s another location you were thinking of that’d sidestep the dependency-direction question entirely.

On the response shape, in case it’s useful either way: here’s roughly what I’d picture a merged endpoint returning. I collapsed concept-level and drug-level templates into a single result type rather than two, since keeping them separate would add a second selection step for concept-level matches, which seemed to go against the one-step select-and-sign goal we talked about. The concept-vs-drug origin just rides along as a matchSource field, enough to show a “general default, verify dose for this strength” note on concept-level matches.

GET /orderableSearch?q={text}

{
  "results": [
    {
      "resultType": "template",
      "matchSource": "drug",
      "template": { uuid, name, dosingType, dosingInstructions },
      "drug": { uuid, display, strength, dosageForm }
    },
    {
      "resultType": "template",
      "matchSource": "concept",
      "template": { uuid, name, dosingType, dosingInstructions },
      "drug": { uuid, display, strength, dosageForm }
    },
    {
      "resultType": "drug",
      "drug": { uuid, display, strength, dosageForm }
    }
  ]
}

Two other things worth pinning down whichever direction we go:

  1. Would the current drug?q= and ordertemplates/orderTemplate?drug= endpoints stay in place for flows that already have a known drug (like the edit-order lookup)? My instinct is to keep them and add this on top rather than replace them outright, but wanted to check that lines up with your thinking.
  2. If a concept has a lot of formulations under it, resolving its template at search time could produce a pretty wide result set for one query. Not sure if that’s a real concern at our expected scale, just flagging it in case it’s worth a quick gut-check.

Quick follow-up, I went through the updated wiki page after posting the above, and it looks like it answers most of what I was asking:

  • Confirmed: a template replaces the blank result entirely rather than appearing alongside it, no separate drug/template distinction surfaced to the prescriber.
  • Confirmed: the interleaved EMRAPI endpoint is the agreed direction, with the existing per-drug fetch kept as the first increment and retired once that lands. That answers my question on whether the old endpoints stick around in the interim.
  • Confirmed: retired templates are excluded server-side.

One thing I didn’t see addressed there: since EMRAPI is a shared dependency for a lot of other modules, does the Stage 3 endpoint mean EMRAPI takes a hard dependency on ordertemplates, or is that handled as an optional one? Not trying to reopen the placement decision, just want to understand how that’s meant to work given EMRAPI’s usual role as a shared base other modules build on.

Thanks Mr. Janith. While going through the existing ordertemplates backend to better understand the current implementation and how it fits with the proposed O3 workflow, we used Copilot to help us explore the code and identify some possible gaps.

We’ve added the gaps we found to the Confluence page here:

A few things came up that we’d like to clarify before treating them as actual V1 gaps. We’re not sure which of these should be considered gaps for the proposed V1 versus intentional design choices, so we’d appreciate any clarification from the maintainers. We’re mainly trying to make sure we understand the existing architecture correctly before proposing changes. Thanks for the guidance!

So result type for an orderable would eventually include drug, test, referral, diet, nursing, … and template, where template could represent a template for any of the other types? That feels awkward. Why not return a set of orderable types with an optional template?

GET /orderableSearch?q={text}

{
  "results": [
    {
      "resultType": "drug",
      "template": { uuid, name, dosingType, dosingInstructions },
      "drug": { uuid, display, strength, dosageForm }
    },
    {
      "resultType": "drug",
      "template": { uuid, name, dosingType, dosingInstructions },
      "drug": { uuid, display, strength, dosageForm }
    },
    {
      "resultType": "drug",
      "drug": { uuid, display, strength, dosageForm }
    }
  ]
}

That’s a cleaner shape, agreed. resultType: "template" as its own value doesn’t really hold up once there’s more than one orderable type, it doesn’t tell you what it’s a template for, you’d have to unwrap it to find out anyway. Making resultType the orderable’s own type and template an optional field on top is the better axis.

Since the merged response is assembled in emrapi, that’s also the natural place for resultType to be derived from template.type at serialization, rather than stored as a separate field on the template that could drift out of sync. Keeps the module underneath just serving templates, without needing to know about the unified result shape.

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 3. As part of our system design phase, we have prepared three diagrams to represent our proposed Drug Order Templates model.

Use Case Diagram: Identifies the main actors and their interactions with the system. Activity Diagram: Illustrates the step-by-step workflow of Drug Order Templates. EER Diagram: Represents the proposed database entities and their relationships.

We have documented these diagrams with explanations in a Confluence Live Doc.

https://uom-team-op8xvwk7.atlassian.net/wiki/x/hwAB

We would greatly appreciate any feedback or suggestions from the OpenMRS community regarding our proposed design and workflows.

Thank you!

1 Like

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 3.

As part of our system design phase, we have prepared two diagrams to illustrate our proposed design:

:small_blue_diamond: Class Diagram – Represents the main classes, their attributes, methods, and relationships within the proposed Drug Order Templates model.

:small_blue_diamond: Sequence Diagram – Illustrates the interactions between system components and the sequence of messages exchanged during the Drug Order Templates workflow.

We have documented these diagrams, along with explanations, in a Confluence Live Doc.

:page_facing_up: Design Documentation: https://uom-team-tewltw5n.atlassian.net/wiki/x/CoAB

We would greatly appreciate feedback, suggestions, and recommendations from the OpenMRS community to help us refine our proposed design and ensure alignment with OpenMRS standards and existing workflows.

Thank you for your time and support! :folded_hands:

We look forward to learning from your feedback.

1 Like