Skip to content

Commit

Permalink
Unit tests added for SupplyRequest and Procedure order router
Browse files Browse the repository at this point in the history
  • Loading branch information
VaishSiddharth committed Jan 16, 2025
1 parent f3a2aac commit 6d0b7b2
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 122 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,27 @@
import static org.openmrs.eip.fhir.Constants.PROCEDURE_ORDER_TYPE_UUID;
import static org.openmrs.eip.fhir.Constants.PROP_EVENT_OPERATION;

import org.apache.camel.CamelExecutionException;
import org.apache.camel.LoggingLevel;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.openmrs.eip.fhir.FhirResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.openmrs.eip.fhir.routes.resources.models.Order;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class ProcedureRouter extends BaseFhirResourceRouter {

private static final ObjectMapper objectMapper = new ObjectMapper();

ProcedureRouter() {
super(FhirResource.PROCEDURE);
}

@Autowired
private ProcedureProcessor procedureProcessor;

@Override
public void configure() throws Exception {
from(FhirResource.PROCEDURE.incomingUrl()).routeId("fhir-procedure-router").filter(isSupportedTable()).toD(
Expand All @@ -38,8 +44,37 @@ public void configure() throws Exception {
String base64Auth = getEncoder().encodeToString(auth.getBytes());
exchange.getIn().setHeader("Authorization", "Basic " + base64Auth);
}).setHeader("CamelHttpMethod", constant("GET"))
.toD("{{openmrs.baseUrl}}/ws/rest/v1/order/${exchangeProperty.event.identifier}").process(procedureProcessor)
.setHeader(HEADER_FHIR_EVENT_TYPE, simple("${exchangeProperty." + PROP_EVENT_OPERATION + "}"))
//TODO: Replace with {{openmrs.baseUrl}}
.toD("http://openmrs:8080/ws/rest/v1/order/${exchangeProperty.event.identifier}").process(exchange -> {
try {
Order order = objectMapper.readValue(exchange.getIn().getBody(String.class), Order.class);
exchange.getMessage().setBody(mapOrderToServiceRequest(order));
}
catch (Exception e) {
throw new CamelExecutionException("Error mapping Order to ServiceRequest", exchange, e);
}
}).setHeader(HEADER_FHIR_EVENT_TYPE, simple("${exchangeProperty." + PROP_EVENT_OPERATION + "}"))
.to(FhirResource.PROCEDURE.outgoingUrl()).endChoice().end();
}

private ServiceRequest mapOrderToServiceRequest(Order order) {
ServiceRequest serviceRequest = new ServiceRequest();
if (order.getAction().equals("DISCONTINUE")) {
serviceRequest.setStatus(ServiceRequest.ServiceRequestStatus.COMPLETED);
} else {
serviceRequest.setStatus(ServiceRequest.ServiceRequestStatus.ACTIVE);
}
serviceRequest.setIntent(ServiceRequest.ServiceRequestIntent.ORDER);
serviceRequest.setCode(new CodeableConcept(
new Coding().setCode(order.getConcept().getUuid()).setDisplay(order.getConcept().getDisplay()))
.setText(order.getConcept().getDisplay()));
serviceRequest.setSubject(new Reference().setReference("Patient/" + order.getPatient().getUuid()).setType("Patient")
.setDisplay(order.getPatient().getDisplay()));
serviceRequest.setEncounter(
new Reference().setReference("Encounter/" + order.getEncounter().getUuid()).setType("Encounter"));
serviceRequest.setRequester(new Reference().setReference("Practitioner/" + order.getOrderer().getUuid())
.setType("Practitioner").setDisplay(order.getOrderer().getDisplay()));

return serviceRequest;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,27 @@
import static org.openmrs.eip.fhir.Constants.PROP_EVENT_OPERATION;
import static org.openmrs.eip.fhir.Constants.SUPPLY_REQUEST_ORDER_TYPE_UUID;

import java.util.Collections;

import org.apache.camel.LoggingLevel;
import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.SupplyRequest;
import org.openmrs.eip.fhir.FhirResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.openmrs.eip.fhir.routes.resources.models.Order;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class SupplyRequestRouter extends BaseFhirResourceRouter {

private static final ObjectMapper objectMapper = new ObjectMapper();

SupplyRequestRouter() {
super(FhirResource.SUPPLYREQUEST);
}

@Autowired
private SupplyProcessor supplyProcessor;

@Override
public void configure() throws Exception {
from(FhirResource.SUPPLYREQUEST.incomingUrl()).routeId("fhir-supplyrequest-router").filter(isSupportedTable()).toD(
Expand All @@ -38,8 +44,28 @@ public void configure() throws Exception {
String base64Auth = getEncoder().encodeToString(auth.getBytes());
exchange.getIn().setHeader("Authorization", "Basic " + base64Auth);
}).setHeader("CamelHttpMethod", constant("GET"))
.toD("{{openmrs.baseUrl}}/ws/rest/v1/order/${exchangeProperty.event.identifier}").process(supplyProcessor)
.setHeader(HEADER_FHIR_EVENT_TYPE, simple("${exchangeProperty." + PROP_EVENT_OPERATION + "}"))
//TODO: Replace with {{openmrs.baseUrl}}
.toD("http://openmrs:8080/ws/rest/v1/order/${exchangeProperty.event.identifier}").process(exchange -> {
Order order = objectMapper.readValue(exchange.getIn().getBody(String.class), Order.class);
exchange.getMessage().setBody(mapOrderToSupplyRequest(order));
}).setHeader(HEADER_FHIR_EVENT_TYPE, simple("${exchangeProperty." + PROP_EVENT_OPERATION + "}"))
.to(FhirResource.SUPPLYREQUEST.outgoingUrl()).endChoice().end();
}

private SupplyRequest mapOrderToSupplyRequest(Order order) {
SupplyRequest supplyRequest = new SupplyRequest();
supplyRequest.setId(order.getUuid());
supplyRequest.setItem(new Reference().setReference("MedicalSupply/" + order.getConcept().getUuid())
.setDisplay(order.getConcept().getDisplay()));
supplyRequest.setReasonReference(Collections.singletonList(
new Reference().setType("Encounter").setReference("Encounter/" + order.getEncounter().getUuid())));
supplyRequest.setQuantity(new Quantity().setValue(order.getQuantity()).setCode(order.getQuantityUnits().getUuid()));
supplyRequest.setRequester(
new Reference().setReference(order.getOrderer().getUuid()).setDisplay(order.getOrderer().getDisplay()));
supplyRequest.setDeliverTo(new Reference().setReference("Patient/" + order.getPatient().getUuid())
.setDisplay(order.getPatient().getDisplay()));
supplyRequest.setStatus(SupplyRequest.SupplyRequestStatus.ACTIVE);

return supplyRequest;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.openmrs.eip.fhir.routes.resources;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.openmrs.eip.fhir.Constants.HEADER_FHIR_EVENT_TYPE;
import static org.openmrs.eip.fhir.Constants.PROCEDURE_ORDER_TYPE_UUID;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.camel.Endpoint;
import org.apache.camel.Message;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
import org.apache.camel.test.spring.junit5.UseAdviceWith;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openmrs.eip.fhir.FhirResource;
import org.openmrs.eip.mysql.watcher.Event;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.StaticApplicationContext;

@UseAdviceWith
class ProcedureRouterTest extends CamelSpringTestSupport {

private static final String PROCEDURE_ORDER_RESPONSE = "{\"uuid\":\"c585bffc-df49-4e57-8a90-6c1d5edb4ffd\",\"orderNumber\":\"ORD-2\",\"accessionNumber\":\"wefewf43r\",\"patient\":{\"uuid\":\"8b562184-bf0f-4ece-8852-780ee315f98e\",\"display\":\"H-3000000 - Siddharth Vaish\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/patient\\/8b562184-bf0f-4ece-8852-780ee315f98e\",\"resourceAlias\":\"patient\"}]},\"concept\":{\"uuid\":\"5a4c17ce-8305-4ea4-baca-0db107ae5ec2\",\"display\":\"Cystoscopie\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/concept\\/5a4c17ce-8305-4ea4-baca-0db107ae5ec2\",\"resourceAlias\":\"concept\"}]},\"action\":\"NEW\",\"careSetting\":{\"uuid\":\"6f0c9a92-6f24-11e3-af88-005056821db0\",\"display\":\"Outpatient\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/caresetting\\/6f0c9a92-6f24-11e3-af88-005056821db0\",\"resourceAlias\":\"caresetting\"}]},\"previousOrder\":null,\"dateActivated\":\"2025-01-08T09:11:53.000+0000\",\"scheduledDate\":null,\"dateStopped\":null,\"autoExpireDate\":null,\"encounter\":{\"uuid\":\"5a286408-167e-4883-aed8-61fb0b0e65ee\",\"display\":\"Orders 01\\/08\\/2025\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/encounter\\/5a286408-167e-4883-aed8-61fb0b0e65ee\",\"resourceAlias\":\"encounter\"}]},\"orderer\":{\"uuid\":\"adbc0d21-c77b-426e-929d-76ff08f9f250\",\"display\":\"admin - Super User\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/provider\\/adbc0d21-c77b-426e-929d-76ff08f9f250\",\"resourceAlias\":\"provider\"}]},\"orderReason\":null,\"orderReasonNonCoded\":null,\"orderType\":{\"uuid\":\"67a92e56-0f88-11ea-8d71-362b9e155667\",\"display\":\"Procedure\",\"name\":\"Procedure\",\"javaClassName\":\"org.openmrs.Order\",\"retired\":false,\"description\":\"An order for Procedure exams\",\"conceptClasses\":[{\"uuid\":\"8d490bf4-c2cc-11de-8d13-0010c6dffd0f\",\"display\":\"Procedure\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/conceptclass\\/8d490bf4-c2cc-11de-8d13-0010c6dffd0f\",\"resourceAlias\":\"conceptclass\"}]}],\"parent\":null,\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/ordertype\\/67a92e56-0f88-11ea-8d71-362b9e155667\",\"resourceAlias\":\"ordertype\"},{\"rel\":\"full\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/ordertype\\/67a92e56-0f88-11ea-8d71-362b9e155667?v=full\",\"resourceAlias\":\"ordertype\"}],\"resourceVersion\":\"1.10\"},\"urgency\":\"ROUTINE\",\"instructions\":null,\"commentToFulfiller\":null,\"display\":\"Cystoscopie\",\"links\":[{\"rel\":\"self\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/order\\/c585bffc-df49-4e57-8a90-6c1d5edb4ffd\",\"resourceAlias\":\"order\"},{\"rel\":\"full\",\"uri\":\"http:\\/\\/localhost\\/openmrs\\/ws\\/rest\\/v1\\/order\\/c585bffc-df49-4e57-8a90-6c1d5edb4ffd?v=full\",\"resourceAlias\":\"order\"}],\"type\":\"order\",\"resourceVersion\":\"1.10\"}";

@Override
protected AbstractApplicationContext createApplicationContext() {
return new StaticApplicationContext();
}

@Override
protected RoutesBuilder createRouteBuilder() {
RouteBuilder rb = new ProcedureRouter();
rb.from(FhirResource.PROCEDURE.outgoingUrl()).to("mock:result");
return rb;
}

@Override
public boolean isUseDebugger() {
return true;
}

@BeforeEach
void setup() throws Exception {
AdviceWith.adviceWith("fhir-procedure-router", context, new AdviceWithRouteBuilder() {

@Override
public void configure() throws Exception {
context.getPropertiesComponent().setLocation("classpath:application-test.properties");
weaveByToUri("http:*").replace().to("mock:http");
weaveByToUri(
"sql:SELECT ot.uuid as uuid from order_type ot join orders o on o.order_type_id = ot.order_type_id where o.uuid ='${exchangeProperty.event.identifier}'?dataSource=#openmrsDataSource")
.replace().to("mock:sql-order-type");
weaveByToUri(
"sql:SELECT voided, order_action, previous_order_id FROM orders WHERE uuid = '${exchangeProperty.event.identifier}'?dataSource=#openmrsDataSource")
.replace().to("mock:sql-orders");
}
});

Endpoint defaultEndpoint = context.getEndpoint(FhirResource.PROCEDURE.incomingUrl());
template.setDefaultEndpoint(defaultEndpoint);
}

@Test
void shouldHandleProcedureOrderEntry() throws InterruptedException {
// Arrange
MockEndpoint result = getMockEndpoint("mock:result");
result.expectedMessageCount(1);
result.setResultWaitTime(100);

MockEndpoint http = getMockEndpoint("mock:http");
http.expectedMessageCount(1);
http.whenAnyExchangeReceived((exchange) -> {
Message httpOutput = exchange.getMessage();
httpOutput.setBody(PROCEDURE_ORDER_RESPONSE);
});

MockEndpoint sqlOrderType = getMockEndpoint("mock:sql-order-type");
sqlOrderType.expectedMessageCount(1);
sqlOrderType.whenAnyExchangeReceived((exchange) -> {
Message sqlOutput = exchange.getMessage();
Map<String, String> map = new HashMap<>();
map.put("uuid", PROCEDURE_ORDER_TYPE_UUID);
sqlOutput.setBody(Collections.singletonList(map));
});

MockEndpoint sqlOrders = getMockEndpoint("mock:sql-orders");
sqlOrders.expectedMessageCount(1);
sqlOrders.whenAnyExchangeReceived((exchange) -> {
Message sqlOutput = exchange.getMessage();
Map<String, String> output = new HashMap<>();
output.put("voided", String.valueOf(0));
output.put("order_action", "NEW");
output.put("previous_order_id", String.valueOf(1));
sqlOutput.setBody(Collections.singletonList(output));
});

// Act
template.send((exchange) -> {
Event event = new Event();
event.setTableName("orders");
event.setOperation("c");
event.setIdentifier(UUID.randomUUID().toString());
exchange.setProperty("event", event);
Message in = exchange.getIn();
in.setBody("");
});

// Assert
result.assertIsSatisfied();

// Verify we got a service request object
Message message = result.getExchanges().get(0).getMessage();
assertThat(message.getHeader(HEADER_FHIR_EVENT_TYPE), equalTo("c"));

Object messageBody = message.getBody();
assertThat(messageBody, notNullValue());
assertThat(messageBody, instanceOf(ServiceRequest.class));

http.assertIsSatisfied();
sqlOrderType.assertIsSatisfied();
sqlOrders.assertIsSatisfied();
}
}
Loading

0 comments on commit 6d0b7b2

Please sign in to comment.