IsantePlus / openmrs-module-isanteplus-labonfhir

A FHIR-based Lab Workflow for iSantePlus
Other
0 stars 1 forks source link

Determine if the openmrs-fhir-analytics pipeline can be leveraged for the labonfhir workflow. #4

Open pmanko opened 3 years ago

pmanko commented 3 years ago

We currently use the https://github.com/GoogleCloudPlatform/openmrs-fhir-analytics project for synchronizing OpenMRS changes with the Shared Health Record service.

The OpenHIE Lab Order Workflows (Section 4.5) use an SHR as an intermediary for lab orders flowing from EMRs to LISs.

We should think about leveraging the openmrs-fhir-analytics work for facilitating these workflows, which would reduce the risk of duplicate communication when both labonfhir and openmrs-fhir-analytics pipelines are running.

However, this change would require us to figure out a couple of issues:

  1. The lab workflows require the creation and mapping of a Task resource, which has no native OpenMRS equivalent, so the creation of this resource would need to be triggered by the lab ordering action.
  2. Customize the mappings between OpenMRS objects and FHIR. iSantePlus and a number of OpenMRS distributions use custom data models for storing concepts. In particular, iSantePlus uses Obs with specific concepts to store lab orders, results, and many other pieces of clinical data (Medications, etc.). We would need the openmrs-fhir-analytics to allow these custom mappings, and determine what type of FHIR resource to send based on the concept of an Obs object.
pmanko commented 3 years ago

@ibacher do you have any thoughts on this problem?

ibacher commented 3 years ago

Yeah, these are (some of) the reasons that I had been hoping that the analytics engine would leverage openmrs-eip, less because that project is brilliant and more because it would allow us to leverage Camel to do some workflow orchestration. Of course, the streaming-binlog does currently leverage Camel, so maybe we could take advantage of that.

The big challenge here is that right now, the openmrs-fhir-analytics pipeline is setup to map from incoming table -> FHIR Resource, so, e.g., from the sample configuration:

"obs": {
  "enabled": "true",
  "title": "Observation",
  "parentTable": "obs",
  "linkTemplates": {
    "rest": "/ws/rest/v1/obs/{uuid}?v=full",
    "fhir": "/Observation/{uuid}"
  }
},

I don't think there's anything we can do earlier in the pipeline and still get things to work. I think, instead, the answer here is to extend EventConfiguration so that it can take a custom class as the handler.

That probably means moving the logic between lines 100-121 here into a sort of "default handler". Then we could leverage a custom handler to say:

public String handleMessage(Map payload) {
    // magic happens here with custom logic to go from concept_id to how the Obs should be treated
    ObsType obsType = ObsType.from(payload.get("concept_id"));

    switch (obsType) {
        case DRUG_ORDER:
            return "https://my.server.com/openmrs/ws/fhir2/R3/DrugOrder/" + payload.get("uuid");
        case LAB_ORDER:
            return "https://my.server.com/openmrs/ws/fhir2/R3/ProcedureRequest/" + payload.get("uuid");
        default:
            return "https://my.server.com/openmrs/ws/fhir2/R3/Observation/" + payload.get("uuid");
    }
}

So with some customisation of the FHIR2 endpoints to look at the Obs table rather than the other tables and something like that, that should enable getting the right data out of OMRS in FHIR format.


Task creation is, admittedly, a bit tricker. The easiest thing to do is to just create the necessary task when a LAB_ORDER appears in the above pseudo-code. Tasks in FHIR2 are backed by a fhir_task table, so you should be able to just setup the default route handling to handle when a new FHIR Task is created, copy it to the SHR part of the workflow. That's probably sufficient for the needs here.

The more robust thing to do would be to have a secondary processor attached to the Debezium stream that does exactly the same thing, but is limited to only creating the necessary tasks. The idea of separating that out is to separate out concerns so that task creation doesn't gum up the sending to SHR process. However, it does mean probably needing some more complex setup code to get everything working.