Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update task resource attributes - PM #45

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,5 @@ nb-configuration.xml
##############################
.DS_Store

.flattened-pom.xml
.flattened-pom.xml
openmrs.log
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>org.openmrs.module</groupId>
<artifactId>labonfhir</artifactId>
<version>1.4.0-SNAPSHOT</version>
<version>1.4.2-SNAPSHOT</version>
</parent>

<artifactId>labonfhir-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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<EncounterProvider> 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 {
Expand All @@ -121,7 +110,7 @@ public Task createOrder(Order order) throws OrderCreationException {
}

private Task createTask(List<Reference> basedOnRefs, Reference forReference, Reference ownerRef,
Reference encounterRef, Reference locationRef ,List<Task.ParameterComponent> taskInputs) {
Reference encounterRef, Reference locationRef, Reference requesterRef ,List<Task.ParameterComponent> taskInputs) {
Task newTask = new Task();
newTask.setStatus(Task.TaskStatus.REQUESTED);
newTask.setIntent(Task.TaskIntent.ORDER);
Expand All @@ -130,6 +119,7 @@ private Task createTask(List<Reference> basedOnRefs, Reference forReference, Ref
newTask.setOwner(ownerRef);
newTask.setEncounter(encounterRef);
newTask.setLocation(locationRef);
newTask.setRequester(requesterRef);
if (taskInputs != null) {
newTask.setInput(taskInputs);
}
Expand Down Expand Up @@ -160,11 +150,7 @@ public Task createOrder(Encounter encounter) throws OrderCreationException {

Reference locationRef = newReference(encounter.getLocation().getUuid(), FhirConstants.LOCATION);

Optional<EncounterProvider> 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<Task.ParameterComponent> taskInputs = null;
if (config.addObsAsTaskInput()) {
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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));

Expand All @@ -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<LocationAttribute> 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);

Expand All @@ -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);
}
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
2 changes: 1 addition & 1 deletion omod/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>org.openmrs.module</groupId>
<artifactId>labonfhir</artifactId>
<version>1.4.0-SNAPSHOT</version>
<version>1.4.2-SNAPSHOT</version>
</parent>

<artifactId>labonfhir-omod</artifactId>
Expand Down
Loading
Loading