In Bahmni at one of our implementations we have a requirement to auto enrol patients to a particular program based on some pre-defined trigger condition for the program defined. E.g: For ANC, or pregnancy program, when for a female patient, the diagnosis is selected as “pregnancy confirmed”, and if the patient belongs to the catchment area served by the program that patient should get enrolled automatically in the appropriate program. The enrolment should happen immediately Based on our internal discussions that this would be a very common use case for many programs, such as HIV, etc. We would like to seek feedback from this community whether from a functionality perspective should we be looking at providing such a feature across programs, so that when the programs are created such triggers could be defined for auto enrolment? Or should we be looking at a custom implementation with specific triggers for specific programs based on their needs? Please share your thoughts.
My first thought is to generalize the use case beyond program enrollment to encompass performing any sort of rule upon saving an encounter. In the first pass we could just introduce a generic test+action interface, and just code the first rules in Java or groovy. Ultimately we might have a library of common actions that can be chained together through the admin UI. (Perhaps this can improve/replace the encounter save actions that we currently use e.g. to calculate BMI.)
If you don’t need the enrollment to happen synchronously in the same encounter save transaction we could try doing this via the OpenMRS event module which uses an activemq message bus.
(I think either of these have more long term utility than just having a program enrollment trigger.)
@darius Do we see it as a generic use case for OpenMRS? i.e. something we can incorporate in OpenMRS?
- Option 1: We have an ObsValueCalculator.groovy file in Bahmni. One option (as suggested by you) is to make it generic. This file currently is cluttered with lot of logic and it can become out of control after sometime.
- Option 2: We have a hook called EncounterDataPreSaveCommand. We look for the implementations of this interface and update the EncounterTransaction. This is mostly to update the encounter transaction with extra contextual information or do some implementation specific validation like this
- Option 3: Add this support OOB with OpenMRS. Like leveraging Handler annotation and have a first class support like *Validator classes
- Option 4: Can we leverage atomfeed? Have an OMOD which listens to the atomfeed events (like encounter create, patient create) and do some custom logic. Let this OMOD have generic interface and utility classes for triggers.
As we discussed a little bit on Thursday, I agree with Darius that this can be used for many important use cases. In a past life our group built a generic Triggered Logic Module like this (we called it an Event a Engine) and it had dozens of applications.
I would outline it this way (this is a very general case but it should be straightforward to pick out functionality for the first use cases):
- General case is triggered and then logic-based assertion of a status, and any actions that immediately follow from that status – that’s essentially a “clinical program”, as we’ve been using the term.
- some use cases: patient enrollment in any sort of program or intervention group (your antenatal program, other clinical programs as @akhilmalhotra has been discussing, other event-triggered CDS e.g., a missed vaccination triggered on arrival of a new birthday)
- Trigger types: usually one of these five: immediate data (responsible user just entered it, such as a new order or new diagnosis), asynchronous data (the responsible user who has to take action may not be present at the time, such as a new encounter or new lab result), absolute time (new day), relative time (six hours since admission), manual user request/report
- Triggered-Logic Module basic operation concept: When the trigger event occurs, certain logic statement(s) kept in a library then execute, and if the logic is true the patient has an action (enrolled in a group, add a diagnosis, post an alert, etc.)
A good candidate for a design meeting, maybe.
It sounds like OpenMRS has some of these components already available,
In practice we might first implement this in a module, depending on whether our implementation timeline can wait for us being ready to move Bahmni to the openmrs-core 2.x line (since this would be a new feature we’d add in openmrs-core 2.1).
It would be especially helpful if the Bahmni team can do some analysis of whether this is okay to be asynchronous and event-triggered, or whether it (sometimes) needs to happen as part of the same transaction as the encounter save.
Jonathan describes a more general feature (e.g. not just encounters as triggers), and if we go this route, it makes sense to use an event mechanism that’s asynchronous. (And we might eventually take advantage of the same thing to include more events in our atom feeds.)
If we’re only triggering on encounters, it’s more feasible to do this synchronously.