Skip to content

Commit

Permalink
Support for order processing (#28)
Browse files Browse the repository at this point in the history
* Added commit message

* Added listener for lab orders

* Generalized lab information system references from OpenELIS to a generic LIS. Added changes for triggering LIS communication based on Order class creation

* Lab order creation refactoring

* Replaced equality check symbol with object comparison method

* * Replaced equality check symbol with object comparison method
* Removed unused imports

---------

Co-authored-by: Moshonk <[email protected]>
  • Loading branch information
pmanko and moshonk authored Mar 6, 2023
1 parent 0a26d47 commit 13a1192
Show file tree
Hide file tree
Showing 15 changed files with 456 additions and 227 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ The Lab on FHir Module only generates the Lab WorkFlow Fhir Bundle When an order
see more about the [EMR-LIS FHIR Workflow](https://wiki.openmrs.org/display/projects/Lab+Integration+Workflow)

Configure the Following Global Properties Required By the Lab on Fhir Module
* `labonfhir.openElisUrl` ,The URL for the OpenELIS system to communicate with
* `labonfhir.openElisUserUuid` ,UUID for the service user that represents OpenELIS
* `labonfhir.lisUrl` ,The URL for the OpenELIS system to communicate with
* `labonfhir.lisUserUuid` ,UUID for the service user that represents OpenELIS
* `labonfhir.truststorePath` , Path to truststore for HttpClient
* `labonfhir.truststorePass` , Truststore password
* `labonfhir.keystorePath` , Path to keystore for HttpClient
Expand All @@ -44,4 +44,3 @@ Configure the Following Global Properties Required By the Lab on Fhir Module
* `labonfhir.password` ,Password for HTTP Basic Auth with the LIS



Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public IGenericClient getFhirClient() throws Exception {
configureFhirHttpClient(client);
}

IGenericClient fhirClient = fhirContext.newRestfulGenericClient(config.getOpenElisUrl());
IGenericClient fhirClient = fhirContext.newRestfulGenericClient(config.getLisUrl());
if (config.getAuthType().equals(AuthType.BASIC)) {
BasicAuthInterceptor authInterceptor = new BasicAuthInterceptor(config.getOpenElisUserName(),
config.getOpenElisPassword());
BasicAuthInterceptor authInterceptor = new BasicAuthInterceptor(config.getLisUserName(),
config.getLisPassword());
fhirClient.registerInterceptor(authInterceptor);
}
return fhirClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@

import java.util.Optional;

import org.openmrs.PatientIdentifier;
import org.openmrs.PatientIdentifierType;
import org.openmrs.api.PatientService;
import org.openmrs.module.BaseModuleActivator;
import org.openmrs.module.DaemonToken;
import org.openmrs.module.DaemonTokenAware;
import org.openmrs.module.fhir2.api.FhirPatientIdentifierSystemService;
import org.openmrs.module.fhir2.model.FhirPatientIdentifierSystem;
import org.openmrs.module.labonfhir.api.OpenElisManager;
import org.openmrs.module.labonfhir.api.LabOrderManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
Expand All @@ -43,7 +42,7 @@ public class LabOnFhirActivator extends BaseModuleActivator implements Applicati
private LabOnFhirConfig config;

@Autowired
private OpenElisManager openElisManager;
private LabOrderManager lisManager;

@Autowired
PatientService patientService;
Expand All @@ -56,11 +55,11 @@ public class LabOnFhirActivator extends BaseModuleActivator implements Applicati
public void started() {
applicationContext.getAutowireCapableBeanFactory().autowireBean(this);

openElisManager.setDaemonToken(daemonToken);
lisManager.setDaemonToken(daemonToken);

// subscribe to encounter creation events
if (config.isOpenElisEnabled()) {
openElisManager.enableOpenElisConnector();
if (config.isLisEnabled()) {
lisManager.enableLisConnector();
}
createFhirPatientIdentierSystem();

Expand All @@ -70,8 +69,8 @@ public void started() {

@Override
public void stopped() {
if (openElisManager != null) {
openElisManager.disableOpenElisConnector();
if (lisManager != null) {
lisManager.disableLisConnector();
}

log.info("Lab on FHIR Module Shut Down!");
Expand All @@ -89,19 +88,19 @@ public void setDaemonToken(DaemonToken token) {

private void createFhirPatientIdentierSystem() {
PatientIdentifierType pidType = patientService
.getPatientIdentifierTypeByUuid(config.getPatientIentifierUuid().trim());
.getPatientIdentifierTypeByUuid(config.getPatientIdentifierUuid().trim());

Optional<FhirPatientIdentifierSystem> existingIdSystem = fhirPatientIdentifierSystemService
.getFhirPatientIdentifierSystem(pidType);
if (existingIdSystem.isPresent()) {
existingIdSystem.get().setPatientIdentifierType(pidType);
existingIdSystem.get().setUrl(config.getLisIentifierSystemUrl().trim());
existingIdSystem.get().setUrl(config.getLisIdentifierSystemUrl().trim());
fhirPatientIdentifierSystemService.saveFhirPatientIdentifierSystem(existingIdSystem.get());
} else {
FhirPatientIdentifierSystem idSystem = new FhirPatientIdentifierSystem();
idSystem.setName("OpenLIS ID System");
idSystem.setPatientIdentifierType(pidType);
idSystem.setUrl(config.getLisIentifierSystemUrl().trim());
idSystem.setUrl(config.getLisIdentifierSystemUrl().trim());
fhirPatientIdentifierSystemService.saveFhirPatientIdentifierSystem(idSystem);
}
}
Expand Down
44 changes: 27 additions & 17 deletions api/src/main/java/org/openmrs/module/labonfhir/LabOnFhirConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
@Configuration
public class LabOnFhirConfig implements ApplicationContextAware {

public static final String GP_OPENELIS_URL = "labonfhir.openElisUrl";
public static final String GP_LIS_URL = "labonfhir.lisUrl";

public static final String GP_OPENELIS_USER_UUID = "labonfhir.openelisUserUuid";
public static final String GP_LIS_USER_UUID = "labonfhir.lisUserUuid";

public static final String GP_KEYSTORE_PATH = "labonfhir.keystorePath";

Expand All @@ -48,7 +48,7 @@ public class LabOnFhirConfig implements ApplicationContextAware {

public static final String GP_ACTIVATE_FHIR_PUSH = "labonfhir.activateFhirPush";

private static final String TEMP_DEFAULT_OPENELIS_URL = "https://testapi.openelisci.org:8444/hapi-fhir-jpaserver/fhir";
private static final String TEMP_DEFAULT_LIS_URL = "https://testapi.openelisci.org:8444/hapi-fhir-jpaserver/fhir";

public static final String GP_AUTH_TYPE = "labonfhir.authType";

Expand All @@ -58,8 +58,11 @@ public class LabOnFhirConfig implements ApplicationContextAware {

public static final String GP_PATIENT_IDENTIFIER_UUID = "labonfhir.openmrsPatientIdentifier.uuid";

public static final String GP_LIS_IDENTIFIER_SYSTEM_URL = "labonfhir.openElisIdentifierSystem.url";
public static final String GP_LIS_IDENTIFIER_SYSTEM_URL = "labonfhir.lisIdentifierSystem.url";

public static final String GP_ORDER_TEST_UUIDS = "labonfhir.orderTestUuids";

public static final String GP_LAB_UPDATE_TRIGGER_OBJECT = "labonfhir.labUpdateTriggerObject";
public enum AuthType{
SSL,
BASIC
Expand Down Expand Up @@ -100,12 +103,12 @@ public SSLContext sslContext() throws Exception {
return sslContextBuilder.build();
}

public String getOpenElisUrl() {
public String getLisUrl() {
//return GP_OPENELIS_URL
String url = administrationService.getGlobalProperty(GP_OPENELIS_URL);
String url = administrationService.getGlobalProperty(GP_LIS_URL);

if(StringUtils.isBlank(url)) {
url = TEMP_DEFAULT_OPENELIS_URL;
url = TEMP_DEFAULT_LIS_URL;
}

return url;
Expand All @@ -116,26 +119,33 @@ public Boolean getActivateFhirPush() {
return Boolean.valueOf(activatePush);
}

public String getOpenElisUserUuid() {
return administrationService.getGlobalProperty(GP_OPENELIS_USER_UUID);
public String getLisUserUuid() {
return administrationService.getGlobalProperty(GP_LIS_USER_UUID);
}

public String getOpenElisUserName() {
public String getLisUserName() {
return administrationService.getGlobalProperty(GP_USER_NAME);
}

public String getOpenElisPassword() {
public String getLisPassword() {
return administrationService.getGlobalProperty(GP_PASSWORD);
}

public String getPatientIentifierUuid() {
public String getPatientIdentifierUuid() {
return administrationService.getGlobalProperty(GP_PATIENT_IDENTIFIER_UUID ,"05a29f94-c0ed-11e2-94be-8c13b969e334");
}

public String getLisIentifierSystemUrl() {
public String getLisIdentifierSystemUrl() {
return administrationService.getGlobalProperty(GP_LIS_IDENTIFIER_SYSTEM_URL ,"http://openelis-global.org/pat_nationalId");
}

public String getOrderTestUuids() {
return administrationService.getGlobalProperty(GP_ORDER_TEST_UUIDS, "160046AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,165254AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}

public String getLabUpdateTriggerObject() {
return administrationService.getGlobalProperty(GP_LAB_UPDATE_TRIGGER_OBJECT, "Encounter");
}
public AuthType getAuthType() {
String authTypeGp = administrationService.getGlobalProperty(GP_AUTH_TYPE);
switch (authTypeGp.toUpperCase()) {
Expand All @@ -148,12 +158,12 @@ public AuthType getAuthType() {
}
}

public boolean isOpenElisEnabled() {
return StringUtils.isNotBlank(getOpenElisUrl());
public boolean isLisEnabled() {
return StringUtils.isNotBlank(getLisUrl());
}

public Practitioner getOpenElisPractitioner() {
return practitionerService.get(getOpenElisUserUuid());
public Practitioner getLisPractitioner() {
return practitionerService.get(getLisUserUuid());
}

private KeyStore loadKeystore(String filePath) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package org.openmrs.module.labonfhir.api;

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;

import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.Reference;
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;
import org.openmrs.module.fhir2.FhirConstants;
Expand All @@ -20,14 +22,74 @@
import org.springframework.stereotype.Component;

@Component
public class OpenElisFhirOrderHandler {
public class LabOrderHandler {

@Autowired
private LabOnFhirConfig config;

@Autowired
private FhirTaskService taskService;


public Task createOrder(Order order) throws OrderCreationException {
//TDO: MAKE THIS A GLOBAL CONFIG
final String REQUIRED_TESTS_UUIDS = config.getOrderTestUuids(); // GeneXpert
// Exit if Test Order doesn't contain required tests
boolean mappedTestsExist = false;
for (Obs obs : order.getEncounter().getObs()) {
if (Arrays.stream(REQUIRED_TESTS_UUIDS.split(",")).anyMatch(s -> s.equals(obs.getConcept().getUuid())
|| (obs.getValueCoded() != null && s.equals(obs.getValueCoded().getUuid())))) {
mappedTestsExist = true;
}
}

if (!mappedTestsExist) {
return null;
}
// Create References
List<Reference> basedOnRefs = Collections.singletonList(
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 = requesterProvider.map(
encounterProvider -> newReference(encounterProvider.getUuid(), FhirConstants.PRACTITIONER)).orElse(null);

// Create Task Resource for given Order
Task newTask = createTask(basedOnRefs, forReference, ownerRef, encounterRef);

if (order.getEncounter().getActiveEncounterProviders().isEmpty()) {
newTask.setRequester(requesterRef);
}

// Save the new Task Resource
try {
newTask = taskService.create(newTask);
}
catch (DAOException e) {
throw new OrderCreationException("Exception occurred while creating task for order " + order.getId());
}
return newTask;
}

private Task createTask(List<Reference> basedOnRefs, Reference forReference, Reference ownerRef,
Reference encounterRef) {
Task newTask = new Task();
newTask.setStatus(Task.TaskStatus.REQUESTED);
newTask.setIntent(Task.TaskIntent.ORDER);
newTask.setBasedOn(basedOnRefs);
newTask.setFor(forReference);
newTask.setOwner(ownerRef);
newTask.setEncounter(encounterRef);
return newTask;
}

public Task createOrder(Encounter encounter) throws OrderCreationException {
if (encounter.getOrders().isEmpty()) {
return null;
Expand All @@ -36,37 +98,33 @@ public Task createOrder(Encounter encounter) throws OrderCreationException {
List<Reference> basedOnRefs = encounter.getOrders().stream().map(order -> {
AtomicReference<Order> orders = new AtomicReference<>();
orders.set(order);

if (orders.get() != null) {
return newReference(orders.get().getUuid(), FhirConstants.SERVICE_REQUEST);
} else {
return null;
}
}).collect(Collectors.toList());

Reference forReference = newReference(encounter.getPatient().getUuid(), FhirConstants.PATIENT);
Reference ownerRef = newReference(config.getOpenElisUserUuid(), FhirConstants.PRACTITIONER);

Reference ownerRef = newReference(config.getLisUserUuid(), FhirConstants.PRACTITIONER);

Reference encounterRef = newReference(encounter.getUuid(), FhirConstants.ENCOUNTER);

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 = requesterProvider.isPresent() ?
newReference(requesterProvider.get().getUuid(), FhirConstants.PRACTITIONER) :
null;

// Create Task Resource for given Order
Task newTask = new Task();
newTask.setStatus(Task.TaskStatus.REQUESTED);
newTask.setIntent(Task.TaskIntent.ORDER);
newTask.setBasedOn(basedOnRefs);
newTask.setFor(forReference);
newTask.setOwner(ownerRef);
newTask.setEncounter(encounterRef);
Task newTask = createTask(basedOnRefs, forReference, ownerRef, encounterRef);
newTask.setLocation(locationRef);

if(!encounter.getActiveEncounterProviders().isEmpty()){
if (!encounter.getActiveEncounterProviders().isEmpty()) {
newTask.setRequester(requesterRef);
}

Expand All @@ -79,9 +137,9 @@ public Task createOrder(Encounter encounter) throws OrderCreationException {
}
return newTask;
}

private Reference newReference(String uuid, String type) {
return new Reference().setReference(type + "/" + uuid).setType(type);
}

}
Loading

0 comments on commit 13a1192

Please sign in to comment.