diff --git a/.gitignore b/.gitignore
index 6c44140..00d36d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,4 +80,5 @@ nb-configuration.xml
##############################
.DS_Store
-.flattened-pom.xml
\ No newline at end of file
+.flattened-pom.xml
+openmrs.log
diff --git a/api/pom.xml b/api/pom.xml
index 49410d3..2eecf0a 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -15,7 +15,7 @@
org.openmrs.module
labonfhir
- 1.4.0-SNAPSHOT
+ 1.4.2-SNAPSHOT
labonfhir-api
diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/LabOrderHandler.java b/api/src/main/java/org/openmrs/module/labonfhir/api/LabOrderHandler.java
index cfbd8a2..47c6f81 100644
--- a/api/src/main/java/org/openmrs/module/labonfhir/api/LabOrderHandler.java
+++ b/api/src/main/java/org/openmrs/module/labonfhir/api/LabOrderHandler.java
@@ -4,7 +4,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@@ -17,7 +16,6 @@
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.Task;
import org.openmrs.Encounter;
-import org.openmrs.EncounterProvider;
import org.openmrs.Obs;
import org.openmrs.Order;
import org.openmrs.api.db.DAOException;
@@ -87,28 +85,19 @@ public Task createOrder(Order order) throws OrderCreationException {
newReference(order.getUuid(), FhirConstants.SERVICE_REQUEST));
Reference forReference = newReference(order.getPatient().getUuid(), FhirConstants.PATIENT);
-
- Reference ownerRef = newReference(config.getLisUserUuid(), FhirConstants.PRACTITIONER);
-
+
Reference encounterRef = newReference(order.getEncounter().getUuid(), FhirConstants.ENCOUNTER);
- Optional requesterProvider = order.getEncounter().getActiveEncounterProviders().stream()
- .findFirst();
+ Reference requesterRef = newReference(order.getEncounter().getLocation().getUuid(), FhirConstants.ORGANIZATION);
- Reference requesterRef = requesterProvider.map(
- encounterProvider -> newReference(encounterProvider.getUuid(), FhirConstants.PRACTITIONER)).orElse(null);
-
- Reference locationRef = null;
- if (order.getEncounter().getLocation() != null) {
- locationRef = newReference(order.getEncounter().getLocation().getUuid(), FhirConstants.LOCATION);
- }
+ // Reference locationRef = newReference(order.getEncounter().getLocation().getUuid(), FhirConstants.LOCATION);
// Create Task Resource for given Order
- Task newTask = createTask(basedOnRefs, forReference, ownerRef, encounterRef, locationRef ,taskInputs);
+ Task newTask = createTask(basedOnRefs, forReference, null, encounterRef, null,requesterRef ,taskInputs);
- if (order.getEncounter().getActiveEncounterProviders().isEmpty()) {
- newTask.setRequester(requesterRef);
- }
+// if (order.getEncounter().getLocation() != null) {
+// newTask.setRequester(requesterRef);
+// }
// Save the new Task Resource
try {
@@ -121,7 +110,7 @@ public Task createOrder(Order order) throws OrderCreationException {
}
private Task createTask(List basedOnRefs, Reference forReference, Reference ownerRef,
- Reference encounterRef, Reference locationRef ,List taskInputs) {
+ Reference encounterRef, Reference locationRef, Reference requesterRef ,List taskInputs) {
Task newTask = new Task();
newTask.setStatus(Task.TaskStatus.REQUESTED);
newTask.setIntent(Task.TaskIntent.ORDER);
@@ -130,6 +119,7 @@ private Task createTask(List basedOnRefs, Reference forReference, Ref
newTask.setOwner(ownerRef);
newTask.setEncounter(encounterRef);
newTask.setLocation(locationRef);
+ newTask.setRequester(requesterRef);
if (taskInputs != null) {
newTask.setInput(taskInputs);
}
@@ -160,11 +150,7 @@ public Task createOrder(Encounter encounter) throws OrderCreationException {
Reference locationRef = newReference(encounter.getLocation().getUuid(), FhirConstants.LOCATION);
- Optional requesterProvider = encounter.getActiveEncounterProviders().stream().findFirst();
-
- Reference requesterRef = requesterProvider.isPresent() ?
- newReference(requesterProvider.get().getUuid(), FhirConstants.PRACTITIONER) :
- null;
+ Reference requesterRef = newReference(encounter.getLocation().getUuid(), FhirConstants.ORGANIZATION);
List taskInputs = null;
if (config.addObsAsTaskInput()) {
@@ -179,12 +165,20 @@ public Task createOrder(Encounter encounter) throws OrderCreationException {
}
// Create Task Resource for given Order
- Task newTask = createTask(basedOnRefs, forReference, ownerRef, encounterRef, locationRef ,taskInputs);
- newTask.setLocation(locationRef);
-
- if (!encounter.getActiveEncounterProviders().isEmpty()) {
- newTask.setRequester(requesterRef);
- }
+ // =========================================
+ // Summary of Payload requirements in terms of location and organization:
+ // Payload coming from OpenMRS should include only the Location and Organization resources corresponding to the MFL-based location that represents the physical spot where a lab order is being collected. This MFL code will then be mapped to the proper IPMS location (in some cases based on the type of test being ordered as well)
+ // The incoming Location should reference the Organization as a managing organization, just like a normal Org/Location pair
+ // For the incoming task resource:
+ // `for` should reference the patient
+ // `requester` should reference the Organization
+ // `owner` and `location` can be left blank
+ // Once the task is processed, owner will reference the mapped IPMS Organization, and location the IPMS location.
+ // Leave the `location ref` and `owner ref` blank. Once the task is processed, owner will reference the mapped Lab Systems Organization, and location the Lab System's location.
+ Task newTask = createTask(basedOnRefs, forReference, null, encounterRef, null, requesterRef, taskInputs);
+ //newTask.setLocation(locationRef);
+
+ //newTask.setRequester(requesterRef);
// Save the new Task Resource
try {
diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/event/LabCreationListener.java b/api/src/main/java/org/openmrs/module/labonfhir/api/event/LabCreationListener.java
index 8f07841..cba4aca 100644
--- a/api/src/main/java/org/openmrs/module/labonfhir/api/event/LabCreationListener.java
+++ b/api/src/main/java/org/openmrs/module/labonfhir/api/event/LabCreationListener.java
@@ -1,6 +1,8 @@
package org.openmrs.module.labonfhir.api.event;
import javax.jms.Message;
+
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -10,10 +12,16 @@
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenParam;
+import org.hl7.fhir.r4.model.Location;
+import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.Task;
+import org.openmrs.LocationAttribute;
+import org.openmrs.LocationAttributeType;
+import org.openmrs.api.LocationService;
import org.openmrs.api.context.Daemon;
import org.openmrs.event.EventListener;
import org.openmrs.module.DaemonToken;
@@ -31,6 +39,10 @@
public abstract class LabCreationListener implements EventListener {
+ private static final String MFL_LOCATION_IDENTIFIER_URI = "http://moh.bw.org/ext/location/identifier/mfl";
+
+ private static final String MFL_LOCATION_ATTRIBUTE_TYPE_UUID = "8a845a89-6aa5-4111-81d3-0af31c45c002";
+
private static final Logger log = LoggerFactory.getLogger(EncounterCreationListener.class);
private DaemonToken daemonToken;
@@ -47,14 +59,17 @@ public abstract class LabCreationListener implements EventListener {
private FhirContext ctx;
@Autowired
- FhirLocationService fhirLocationService ;
+ FhirLocationService fhirLocationService;
@Autowired
private FhirTaskService fhirTaskService;
@Autowired
- private LabOnFhirService labOnFhirService ;
+ private LabOnFhirService labOnFhirService;
+ @Autowired
+ private LocationService locationService;
+
public DaemonToken getDaemonToken() {
return daemonToken;
}
@@ -70,8 +85,7 @@ public void onMessage(Message message) {
Daemon.runInDaemonThread(() -> {
try {
processMessage(message);
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.error("Failed to update the user's last viewed patients property", e);
}
}, daemonToken);
@@ -87,6 +101,7 @@ public Bundle createLabBundle(Task task) {
includes.add(new Include("Task:encounter"));
includes.add(new Include("Task:based-on"));
includes.add(new Include("Task:location"));
+ includes.add(new Include("Task:requester"));
IBundleProvider labBundle = fhirTaskService.searchForTasks(new TaskSearchParams(null, null, null, uuid, null, null, includes));
@@ -96,10 +111,47 @@ public Bundle createLabBundle(Task task) {
if (!task.getLocation().isEmpty()) {
labResources.add(fhirLocationService.get(FhirUtils.referenceToId(task.getLocation().getReference()).get()));
}
+
+ if (!task.getRequester().isEmpty()) {
+ labResources.add(fhirLocationService.get(FhirUtils.referenceToId(task.getRequester().getReference()).get()));
+ }
+
for (IBaseResource r : labResources) {
Resource resource = (Resource) r;
+
+ // if resource is location, add MFL Code as location identifier
+ // TODO: Short term: Make the MFL Location attribute type to be a Global config variable
+ // TODO: Long term: Make the location translator pick and enrich the MFL Code as appropriate
+
Bundle.BundleEntryComponent component = transactionBundle.addEntry();
- component.setResource(resource);
+ if (resource instanceof Location || resource instanceof Organization) {
+ org.openmrs.Location openmrsLocation = locationService.getLocationByUuid(resource.getId());
+ if (openmrsLocation != null) {
+ LocationAttributeType mflLocationAttributeType = locationService.getLocationAttributeTypeByUuid(MFL_LOCATION_ATTRIBUTE_TYPE_UUID);
+ Collection locationAttributeTypes = openmrsLocation.getActiveAttributes();
+ if (!locationAttributeTypes.isEmpty()) {
+ locationAttributeTypes.stream().filter(locationAttribute -> locationAttribute.getAttributeType().equals(mflLocationAttributeType)).findFirst().ifPresent(locationAttribute -> {
+ String mflCode = (String) locationAttribute.getValue();
+
+ Identifier mflIdentifier = new Identifier();
+ mflIdentifier.setSystem(MFL_LOCATION_IDENTIFIER_URI);
+ mflIdentifier.setValue(mflCode);
+ if (resource instanceof Organization) {
+ Organization organization = (Organization) resource;
+ organization.addIdentifier(mflIdentifier);
+ component.setResource(organization);
+ } else if (resource instanceof Location) {
+ Location location = (Location) resource;
+ location.addIdentifier(mflIdentifier);
+ component.setResource(location);
+ }
+ });
+ }
+ }
+ } else {
+ component.setResource(resource);
+ }
+
component.getRequest().setUrl(resource.fhirType() + "/" + resource.getIdElement().getIdPart())
.setMethod(Bundle.HTTPVerb.PUT);
@@ -113,8 +165,7 @@ protected void sendTask(Task task) {
Bundle labBundle = createLabBundle(task);
try {
client.transaction().withBundle(labBundle).execute();
- }
- catch (Exception e) {
+ } catch (Exception e) {
saveFailedTask(task.getIdElement().getIdPart(), e.getMessage());
log.error("Failed to send Task with UUID " + task.getIdElement().getIdPart(), e);
}
@@ -123,7 +174,7 @@ protected void sendTask(Task task) {
}
}
- private void saveFailedTask(String taskUuid ,String error) {
+ private void saveFailedTask(String taskUuid, String error) {
FailedTask failedTask = new FailedTask();
failedTask.setError(error);
failedTask.setIsSent(false);
diff --git a/api/src/test/java/org/openmrs/module/labonfhir/api/LabOrderHandlerTest.java b/api/src/test/java/org/openmrs/module/labonfhir/api/LabOrderHandlerTest.java
index 942ea9d..1ca23ef 100644
--- a/api/src/test/java/org/openmrs/module/labonfhir/api/LabOrderHandlerTest.java
+++ b/api/src/test/java/org/openmrs/module/labonfhir/api/LabOrderHandlerTest.java
@@ -1,17 +1,78 @@
package org.openmrs.module.labonfhir.api;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+import org.hl7.fhir.r4.model.Task;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Mock;
+import org.openmrs.Encounter;
+import org.openmrs.Location;
+import org.openmrs.Obs;
+import org.openmrs.Order;
+import org.openmrs.Patient;
+import org.openmrs.api.EncounterService;
+import org.openmrs.api.LocationService;
+import org.openmrs.api.ObsService;
+import org.openmrs.api.OrderService;
+import org.openmrs.api.PatientService;
+import org.openmrs.module.labonfhir.api.fhir.OrderCreationException;
public class LabOrderHandlerTest {
+ @Mock
+ private OrderService orderService;
+ @Mock
+ private EncounterService encounterService;
+ @Mock
+ private LocationService locationService;
+ @Mock
+ private PatientService patientService;
+ @Mock
+ private ObsService obsService;
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
@Before
public void setUp() throws Exception {
}
- @Test
- public void createOrder_shouldCreateTaskAndERferenceOrder() {
+ @Test
+ public void createOrder_shouldCreateTask() throws OrderCreationException {
+ // Create a mock Order object
+ Order order = new Order();
+ order.setUuid("orderUuid");
+
+ // Create a mock Encounter object
+ Encounter encounter = new Encounter();
+ encounter.setUuid("encounterUuid");
+ encounter.setLocation(new Location());
+ encounter.getLocation().setUuid("locationUuid");
+ encounter.setPatient(new Patient());
+ encounter.getPatient().setUuid("patientUuid");
+
+ // Create a mock Obs object
+ Obs obs = new Obs();
+ obs.setUuid("obsUuid");
+ encounter.getObs().add(obs);
+
+ // Mock the necessary dependencies
+ when(orderService.getOrderByUuid("orderUuid")).thenReturn(order);
+ when(encounterService.getEncounterByUuid("encounterUuid")).thenReturn(encounter);
+ when(locationService.getLocationByUuid("locationUuid")).thenReturn(new Location());
+ when(patientService.getPatientByUuid("patientUuid")).thenReturn(new Patient());
+ when(obsService.getObsByUuid("obsUuid")).thenReturn(new Obs());
+
+ // Call the createOrder method
+ LabOrderHandler labOrderHandler = new LabOrderHandler();
+ Task task = labOrderHandler.createOrder(order);
+
+ // Assert that the task is not null
+ assertNotNull(task);
}
-}
+}
\ No newline at end of file
diff --git a/omod/pom.xml b/omod/pom.xml
index 750b938..f041b82 100644
--- a/omod/pom.xml
+++ b/omod/pom.xml
@@ -3,7 +3,7 @@
org.openmrs.module
labonfhir
- 1.4.0-SNAPSHOT
+ 1.4.2-SNAPSHOT
labonfhir-omod
diff --git a/pom.xml b/pom.xml
index e8519eb..e2c8bf4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.openmrs.module
labonfhir
- 1.4.0-SNAPSHOT
+ 1.4.2-SNAPSHOT
pom
Lab on FHIR
A module to support lab order communication between OpenMRS and an LIS like OpenELIS using FHIR-based
@@ -19,10 +19,10 @@
https://wiki.openmrs.org/x/FQ4z
- scm:git:git@github.com:openmrs/openmrs-module-labonfhir.git
- scm:git:git@github.com:openmrs/openmrs-module-labonfhir.git
- https://github.com/openmrs/openmrs-module-labonfhir/
- HEAD
+ scm:git:git@bitbucket.org:botswana-emrs/openmrs-module-labonfhir.git
+ scm:git:git@bitbucket.org:botswana-emrs/openmrs-module-labonfhir.git
+ https://bitbucket.org/botswana-emrs/openmrs-module-labonfhir
+ 1.4.0
@@ -79,7 +79,13 @@
tests
test
-
+
+ org.mockito
+ mockito-core
+ 3.12.4
+ test
+
+
org.projectlombok
lombok
1.18.12
@@ -201,6 +207,11 @@
+
+ repsy
+ Maven Repository on Repsy
+ https://repo.repsy.io/mvn/intellisoftdev/default
+
openmrs-repo
OpenMRS Nexus Repository
@@ -229,18 +240,16 @@
github-packages
-
- github-packages
- Github Maven Repo
- https://maven.pkg.github.com/openmrs/openmrs-module-labonfhir
- false
-
- github-packages
- Github Maven Repo
- https://maven.pkg.github.com/openmrs/openmrs-module-labonfhir
- true
+ repsy
+ My Private Maven Repository on Repsy
+ https://repo.repsy.io/mvn/intellisoftdev/default
+
+ repsy
+ My Private Maven Repository on Repsy
+ https://repo.repsy.io/mvn/intellisoftdev/default
+
@@ -254,4 +263,17 @@
2.3.1
4.2.0
+
+
+
+ repsy
+ My Private Maven Repository on Repsy
+ https://repo.repsy.io/mvn/intellisoftdev/default
+
+
+ repsy
+ My Private Maven Repository on Repsy
+ https://repo.repsy.io/mvn/intellisoftdev/default
+
+