DHIS2 Integration Software Requirements Specification
This document acts as the software requirements specification for the OpenLMIS DHIS2 integration. It pulls from numerous sources including a strategy document written by Josh, previous experience from the eLMIS community outlined in the Gap Interface feature request and a design discussion in late August 2018. The goal of this document is to define the scope of the project and develop the architecture.
User Stories
(developed from eLMIS experience)
- As a district level program administrator, I want to see LMIS logistics data triangulated with service statistics-related data separately collected in DHIS2 through custom dashboards created in DHIS2. This allows me to match the numbers reported from the supply chain against numbers reported by the health system so I can verify them across each domain and act on discrepancies.
- As a facility manager, every month, I need to report standard aggregate reports to DHIS2. This is an automated process in eLMIS and is sometimes a manual process in other implementation areas.
- I want to be able to view my facility's recorded activities each month in OpenLMIS in the standard DHIS2 report format.
- I want to be able to compare this format against my physical tally books and RnR that was submitted to OpenLMIS.
- I want to be able to adjust any numbers in the system and submit the report to DHIS2 for the particular period.
- (External to OpenLMIS) Once submitted, I want to be able to login to DHIS2 and verify that the report was submitted.
Dev team user story ideas:
- Allow person to review DHIS2 publish of metrics
- But how does that person (is it the same person even?) change what they just reviewed.
- Also due to how requisitions work in terms of timing, for the most part nothing happens for 28 days and then everyone is in a scramble.
- (tech oriented) Currently sync nightly, however there's a spike and so we should perhaps revisit doing that more freq around reporting due dates.
User Experience
This section defines the anticipated user experience for this integration. OpenLMIS will give users a standard set of reports available as a FHIR MeasureReport for each of seven measures that need to be calculated. These reports will be available to a third party system that is responsible for performing the ingestion and mapping process.
Scope
The following is within scope for this integration:
- OpenLMIS will make aggregate information available (counts over time) that target the DHIS2 DataSet report. Individual transactions targeted for the DHIS2 tracker capture are out of scope.
- OpenLMIS will focus on providing requisition information as a priority including any additional columns that are added to the RnR template.
- Facility Matching
- OpenLMIS will make a facility list available through the FHIR location API endpoint that can be matched by a third party tool.
- Indicator Calculations Definition (FHIR Measure)
- Key Performance Indicators (KPI) will be developed in the OpenLMIS reporting system and posted as FHIR Measure.
- KPIs/FHIR Measures will need to align to the Categories defined in DHIS2.
- Push MeasureReports to FHIR server
- Reports will be sent to the FHIR server where they will be made available to external consumers through an API
- Expose the FHIR server API
- External users need to expose the FHIR API
System Architecture
Systems Involved
OpenLMIS Core - OpenLMIS Core will be the primary data source. We are focusing on generating reports based on requisition information.
Apache Nifi - Nifi is the data ingestion and standardization engine. Nifi will be used to extract requisitions from OpenLMIS, convert them into multiple measureReports and post them to the HAPI FHIR server.
HAPI FHIR server - OpenLMIS contains a HAPI FHIR server built in. This FHIR server will be responsible for storing Measure Reports and make them available through the API.
Architecture Diagram
Sequence Diagrams
Field Mapping
This section maps the fields between the OpenLMIS Requisition and the FHIR data resources. We chose to use the requisition, because that is the primary unit of data collection in the majority of OpenLMIS implementations.
Below is a screenshot of a requisition:
Requisition Fields for Metrics
The view above shows the fields from the requisition that need to be mapped to the metrics. This work has already been done for the OpenLMIS reporting stack.
- Program - (Displayed as "EPI" in title) is a grouping of orderables, configuration and facility network associated with a specific funding source
- Facility - Defines the location the requisition was created from
- Reporting Period - The period of the requisition (usually, monthly or quarterly)
- Product - Each row in the requisition represents a product with a Product Code and Product name
- Beginning balance - Based on the Stock On Hand from the previous period quantified in dispensing units
- Total received quantity - Total quantity received in the reporting period quantified in dispensing units
- Total consumed quantity - Quantity dispensed/consumed in the reporting period quantified in dispensing units
- Total losses and adjustments - All kind of losses/adjustments made at the facility
- Total stockout days - Total number of days facility was out of stock
- Stock on hand - Current physical count of stock on hand quantified in dispensing units
Metrics (from DHIS2 Metric Scope and Definition Page)
Below is the list of indicators that our DHIS2 integration will support. Each one is calculated per product, reporting period, facility, and program.
Stock Status
Evaluated based on the logic below:
- Stockout: stockOnHand = 0, totalStockoutDays > 0, beginningBalance = 0, or if maxPeriodsOfStock = 0
- Understocked: 0 < maxPeriodsOfStock < 3
- Adequately Stocked: 3 <= maxPeriodsIOfStock <= 6
- Overstocked: maxPeriodsOfStock > 6
Received Quantities
The amount from the totalReceivedQuantity field on the requisition line item for that product, reporting period, and facility.
Consumed Quantities
The amount from the totalConsumedQuantity field on the requisition line item for that product, reporting period, and facility.
Total Stockout Days
The total number of days in the totalStockoutDays field on the requisition line item for that product, reporting period, and facility.
FHIR Measure Resource Crosswalk
We will create a measure for each column in the requisition that is required in the metrics defined above. The Measure, in this instance, provides a dataset definition showing what needs to be posted and it maps to the R&R template in OpenLMIS. We will build a Nifi process to create one measure per requisition column. In total we will develop 7 measures.
The measure will define a single group for each product with the group identifier and name mapping to the product code and name in OpenLMIS. We will also map the program to the
Below is a crosswalk:
OpenLMIS Requisition Field | Measure Resource Field Name | Notes |
---|---|---|
Program | group.identifier | The program will be embedded in an independent group |
Facility | The facility will not be captured within the measure. Instead, it will be captured as the "reporter" in the MeasureReport. | |
Product Code | group.identifier | Each product in the requisition will be mapped to a group |
Product | group.name | The name of the product |
Sample FHIR Messages (Using the Latest FHIR R4)
This section includes hand formed JSON to develop a proof of concept and testing purposes. The goal here is to develop a minimum set of resources to ensure FHIR can be crosswalked to a requisition.
Ordering Messages:
- We need to post the locations to the FHIR server to make sure the location exists (this is already available in OpenLMIS)
- We need to post each measure (one time activity)
- We need to post a MeasureReport for each measure every time a requisition is received
Sample Measure
The following Measure is built for the beginning balance measure. Each column in the requisition needs to be mapped to measures following this template. We only need to change the name. This measure has been shortened to only show the 4 products identified in the OpenLMIS screenshot above.
{ "resourceType": "Measure", "name": "beginning_balance", "description": "Based on the Stock On Hand from the previous period quantified in dispensing units.", "status": "draft", "experimental": true, "group": [ { "code": { "text": "programName" }, "description": "The program for this measure" }, { "code": { "text": "bcg20" }, "description": "BCG" }, { "code": { "text": "penta1" }, "description": "Pentavalent (1 dose)" }, { "code": { "text": "rota1" }, "description": "Rotavirus" }, { "code": { "text": "tetanus10" }, "description": "VAT" } ] }
Sample MeasureReport
The following MeasureReport is built for the beginning balance measure. Each column in the requisition needs to be mapped to measures following this template. We only need to change the name. This measure has been shortened to only show the 4 products identified in the OpenLMIS screenshot above. Note that measureScore is meant to store a numerical Quantity and as such our use is a temporary workaround. We will work with the FHIR community and the authors of the IHE mADX profile to find the right solution to this problem, which could be a future change to the FHIR MeasureReport definition, or the recommendation that we use an extension.
{ "resourceType": "MeasureReport", "text": { "status": "generated", "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p><b>Generated Narrative with Details</b></p></div>" }, "status": "complete", "type": "summary", "measure": "http://hapi.fhir.org/baseR4/Measure/10949", "reporter": { "reference": "Location/5772" }, "period": { "start": "2019-01-01", "end": "2019-01-31" }, "group": [ { "code": { "text": "programName" }, "measureScore": { "system": "openlmisProgramName", "code": "EPI" } }, { "code": { "text": "bcg20" }, "measureScore": { "value": "100" } }, { "code": { "text": "penta1" }, "measureScore": { "value": "100" } }, { "code": { "text": "rota1" }, "measureScore": { "value": "100" } }, { "code": { "text": "tetanus10" }, "measureScore": { "value": "100" } } ] }
ReferenceData API, User Rights and Roles
The HAPI FHIR server is not currently accessible from the public. Information is exchanged from the OpenLMIS microservices to the HAPI FHIR server to populate the information in the FHIR server. All public transactions need to go through the OpenLMIS ReferenceData API which acts as a gateway for access to the HAPI FHIR server. The ReferenceData API provides the authentication service for external consumers, forwards any valid requests to the HAPI FHIR server and returns the results to the client. This section defines the ReferenceData APIs that need to be exposed in the MVP, the user rights and roles that are required to be built in the ReferenceData API to support consuming Measures and Measure Reports.
API Endpoints
We will only expose the ability to read measures and measure reports. The creation of measures and measure reports will be completed by the OpenLMIS system's microservices and Apache Nifi. External consumers will have to initiate a change with system administrators in order to update measures.
OpenLMIS Resource | Action | Description | HAPI FHIR Resource | URL Parameters |
---|---|---|---|---|
/api/Measure | GET | This endpoint allows the user to search all measures and returns a paginated list of results. | /Measure | access_token (required) |
/api/Measure/{id} | GET | This endpoint returns a specific measure | /Measure/{id} | access_token (required) |
/api/MeasureReport | GET | This endpoint allows the user to search all measure reports and returns a paginated list of results | MeasureReport | access_token (required) measure (optional) - Filters the list of reports by measure id period (optional) - The period of the measure report reporter (optional) - This is the reporter of the measure Report. By convention, we use the location Id from the Location endpoint for all Measure Report reporters. lastUpdated (optional) - This returns all measure reports that have lastUpdated greater than or equal to this UTC dateTime |
/api/MeasureReport/{id} | GET | This endpoint returns a specific measure report | /MeasureReport/{id} | access_token (required) |
Notes:
Period is a complex type with start and end dates. We need to figure out how to represent this is a search parameter.
"period": { "start": "2018-01-01", "end": "2018-01-31" }
lastUpdated requires that we pass in a parameter to the HAPI FHIR server that states return everything that is greater than or equal to the lastUpdated date. We need to research exactly how to do this in the URL parameters (it may be something called a "mode", which defaults to mode=match, but we need something like "greater than or equal to")
Reporting Rights and Roles
Access needs to be restricted to measures and measure reports (Role Type: Reports). This section defines the logical rights and roles that should be created in the system.
Right Name | Right Description |
---|---|
View Measures (MEASURE_VIEW) | This role allows users to view measures that are returned from the /api/Measure endpoint. |
View Measure Reports (MEASUREREPORT_VIEW) | This role allows users to view measure reports that have been returned by the /api/MeasureReport endpoint. |
Reporting Role Name | Role Description | Rights |
---|---|---|
Reporting Measure and Measure Report Access | This is a new role that allows access to Measures and MeasureReports | View Measures, View Measure Reports |
(Update) Reporting Personnel | We need to update this to include the following rights | View Measures, View Measure Reports |
Work Process
We need to develop the following items:
Developing and Exposing Reports as FHIR Measure Reports:
- (Done) Develop reports in the data warehouse to return the four indicators identified
- (Done) Make those reports available to Superset for viewing
- (Done) Make those reports available through an API endpoint
- (Done) Research Measure and Measure Report in FHIR
- (Done) Research Measure and Measure Report implementation in the OpenLMIS HAPI FHIR server
- Develop roles in the referenceData microservice and demo data to support accessing the FHIR API Measure Report
- Develop a facade API in the referenceData microservice that receives external requests, verifies access controls from ReferenceData and forwards the request to the OpenLMIS HAPI FHIR server
- Test end-to-end that it functions
Transportation to DHIS2:
- DECISION: Identify if we want to build this transportation and mapping as part of OpenLMIS or use a third party tool
- Develop a Crosswalk:
- Programs
- Locations
- Orderables/Data Elements
- Measure/Indicator Map
- Setup DHIS2 System or Align OpenLMIS metadata with existing DHIS2 implementation
- Choose a country to be used for reference
- Align demo data with a DHIS2 instance
- Setup a DHIS2 instance with these indicators
- Develop the crosswalk as stated above and develop a mechanism to import that into OpenLMIS (either OpenLMIS core or the data warehouse)
- Develop a translation mechanism from Measure Report to DHIS2 ADK message
- Develop transportation mechanism as defined in Workflow 4 above
- Test end-to-end
The diagram below outlines these items as tickets.
OpenLMIS: the global initiative for powerful LMIS software