diff --git a/api/pom.xml b/api/pom.xml
index 300b8b0f..6a61fe44 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -4,7 +4,7 @@
org.openmrs.module
ugandaemrsync
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
ugandaemrsync-api
diff --git a/api/src/main/java/org/openmrs/module/ugandaemrsync/api/UgandaEMRSyncService.java b/api/src/main/java/org/openmrs/module/ugandaemrsync/api/UgandaEMRSyncService.java
index a4e37be7..34cf0348 100644
--- a/api/src/main/java/org/openmrs/module/ugandaemrsync/api/UgandaEMRSyncService.java
+++ b/api/src/main/java/org/openmrs/module/ugandaemrsync/api/UgandaEMRSyncService.java
@@ -508,10 +508,11 @@ public Encounter addVLToEncounter(String vlQualitative, String vlQuantitative, S
public Order getOrderByAccessionNumber(String assessionNumber);
- public boolean validateVLFHIRBundle(String bundleJson);
+ public boolean validateTestFHIRBundle(String bundleJson,String orderConceptUuid);
public boolean isValidCPHLBarCode(String accessionNumber);
- public String getMissingVLFHIRCodesAsString(String bundleJson);
+
+ public String getMissingVLFHIRCodesAsString(String bundleJson,String orderConceptUuid);
public Concept getVLMissingCconcept(String code);
diff --git a/api/src/main/java/org/openmrs/module/ugandaemrsync/api/impl/UgandaEMRSyncServiceImpl.java b/api/src/main/java/org/openmrs/module/ugandaemrsync/api/impl/UgandaEMRSyncServiceImpl.java
index 865512fb..fbfc4da4 100644
--- a/api/src/main/java/org/openmrs/module/ugandaemrsync/api/impl/UgandaEMRSyncServiceImpl.java
+++ b/api/src/main/java/org/openmrs/module/ugandaemrsync/api/impl/UgandaEMRSyncServiceImpl.java
@@ -16,6 +16,7 @@
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Observation;
+import org.hl7.fhir.r4.model.ServiceRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -2325,7 +2326,6 @@ public void sendPrescription() {
List drugOrders = generateDrugOrderToOtherSystem(concepts);
-
try {
for (String drugOrderString : drugOrders) {
// Send prescription via POST
@@ -2339,7 +2339,6 @@ public void sendPrescription() {
);
-
int responseCode = response.get("responseCode") instanceof Integer
? (int) response.get("responseCode")
: Integer.parseInt(response.get("responseCode").toString());
@@ -2433,11 +2432,11 @@ public Map sendSingleViralLoadOrder(Order order) {
String payload = processResourceFromOrder(order);
if (payload != null) {
- if (!validateVLFHIRBundle(payload)) {
+ if (!validateTestFHIRBundle(payload,order.getConcept().getUuid())) {
String missingObsInPayload = String.format(
"Order: %s is not valid due to missing %s in the required field",
order.getAccessionNumber(),
- getMissingVLFHIRCodesAsString(payload)
+ getMissingVLFHIRCodesAsString(payload,order.getConcept().getUuid())
);
logTransaction(syncTaskType, 500, missingObsInPayload, order.getAccessionNumber(),
missingObsInPayload,
@@ -2604,14 +2603,14 @@ private Map sendViralLoadToCPHL(SyncTaskType syncTaskType, String payload, Ugand
);
if (syncResponse != null) {
- String responseFromCPHLServer=String.format("Response From CPHL Server: %s",syncResponse.get("responseMessage"));
+ String responseFromCPHLServer = String.format("Response From CPHL Server: %s", syncResponse.get("responseMessage"));
Map responseType = handleReturnedResponses(order, syncResponse);
int responseCode = Integer.parseInt(syncResponse.getOrDefault("responseCode", "500").toString());
// Handle duplicate case with a 400 response
if (responseCode == 400 && "Duplicate".equalsIgnoreCase(String.valueOf(responseType.get("responseType")))) {
responseCode = 200;
- responseFromCPHLServer = String.format("Response From CPHL Server: %s",responseType.get("responseMessage"));
+ responseFromCPHLServer = String.format("Response From CPHL Server: %s", responseType.get("responseMessage"));
}
boolean isSuccess = responseCode == 200 || responseCode == 201 || responseCode == 202 || responseCode == 208;
@@ -2807,8 +2806,8 @@ private JSONArray getProductCatalogFromEAFYA(SyncTaskType syncTaskType) {
return eAFYAProductList;
}
- public boolean validateVLFHIRBundle(String bundleJson) {
- List targetCodes = Arrays.asList(Context.getAdministrationService().getGlobalProperty("ugandaemrsync.viralloadRequiredProgramData").split(","));
+ public boolean validateTestFHIRBundle(String bundleJson,String orderConceptUuid) {
+ List targetCodes = getTargetCodes(orderConceptUuid);
Set foundCodes = new HashSet<>();
FhirContext ctx = FhirContext.forR4();
@@ -2835,12 +2834,23 @@ public boolean validateVLFHIRBundle(String bundleJson) {
return foundCodes.containsAll(targetCodes);
}
- public String getMissingVLFHIRCodesAsString(String bundleJson) {
- List targetCodes = Arrays.asList(
- Context.getAdministrationService()
- .getGlobalProperty("ugandaemrsync.viralloadRequiredProgramData")
- .split(",")
- );
+ private List getTargetCodes(String orderConceptUuid) {
+ List targetCodes = new ArrayList<>();
+ String testReferralValidators = Context.getAdministrationService().getGlobalProperty("ugandaemrsync.testReferralValidators");
+ JSONObject testReferralValidatorsObject = new JSONObject(testReferralValidators);
+
+ try {
+ targetCodes = Arrays.asList(testReferralValidatorsObject.getJSONObject("testValidators").getString(orderConceptUuid).split(","));
+ } catch (Exception exception) {
+ log.error(exception.getMessage());
+ }
+
+ return targetCodes;
+ }
+
+ public String getMissingVLFHIRCodesAsString(String bundleJson,String orderConceptUuid) {
+ List targetCodes = getTargetCodes(orderConceptUuid);
+
Set foundCodes = new HashSet<>();
FhirContext ctx = FhirContext.forR4();
@@ -2850,30 +2860,30 @@ public String getMissingVLFHIRCodesAsString(String bundleJson) {
try {
bundle = parser.parseResource(Bundle.class, bundleJson);
- for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
- if (entry.getResource() instanceof Observation) {
- Observation obs = (Observation) entry.getResource();
- for (Coding coding : obs.getCode().getCoding()) {
- if (targetCodes.contains(coding.getCode())) {
- foundCodes.add(coding.getCode());
+ for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
+ if (entry.getResource() instanceof Observation) {
+ Observation obs = (Observation) entry.getResource();
+ for (Coding coding : obs.getCode().getCoding()) {
+ if (targetCodes.contains(coding.getCode())) {
+ foundCodes.add(coding.getCode());
+ }
}
}
}
- }
- // Identify missing codes
+ // Identify missing codes
- for (String code : targetCodes) {
- if (!foundCodes.contains(code)) {
+ for (String code : targetCodes) {
+ if (!foundCodes.contains(code)) {
- Concept concept = getVLMissingCconcept(code);
- if (concept != null) {
- missingCodes.add(concept.getName().getName());
- } else {
- missingCodes.add(code);
+ Concept concept = getVLMissingCconcept(code);
+ if (concept != null) {
+ missingCodes.add(concept.getName().getName());
+ } else {
+ missingCodes.add(code);
+ }
}
}
- }
} catch (Exception exception) {
log.error(exception);
}
diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml
index c07172e5..6c466857 100644
--- a/api/src/main/resources/liquibase.xml
+++ b/api/src/main/resources/liquibase.xml
@@ -2048,4 +2048,22 @@
SELECT patient_identifier_type_id, name, 'http://health.go.ug/cr/nationalid' as url, 1, '2025-04-28 08:43:43', 0, '5e8a626e-3d70-11f0-bcbd-bf35c84f3004' FROM patient_identifier_type WHERE uuid = 'f0c16a6d-dc5f-4118-a803-616d0075d282';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/api/src/test/java/org/openmrs/module/ugandaemrsync/server/SyncFHIRRecordTest.java b/api/src/test/java/org/openmrs/module/ugandaemrsync/server/SyncFHIRRecordTest.java
index e0fa2a71..6fa191bf 100644
--- a/api/src/test/java/org/openmrs/module/ugandaemrsync/server/SyncFHIRRecordTest.java
+++ b/api/src/test/java/org/openmrs/module/ugandaemrsync/server/SyncFHIRRecordTest.java
@@ -94,7 +94,8 @@ public void testValidateVLFHIRBundle_withAllRequiredCodes() {
bundle.addEntry().setResource(createObservation("202501021"));
String json = parser.encodeResourceToString(bundle);
- boolean result = ugandaEMRSyncService.validateVLFHIRBundle(json);
+ boolean result = ugandaEMRSyncService.validateTestFHIRBundle(json,"1eb05918-f50c-4cad-a827-3c78f296a10a");
+
Assert.assertTrue(result);
}
@@ -110,7 +111,8 @@ public void testValidateVLFHIRBundle_missingSomeCodes() {
// Missing "868642"
String json = parser.encodeResourceToString(bundle);
- boolean result = ugandaEMRSyncService.validateVLFHIRBundle(json);
+ boolean result = ugandaEMRSyncService.validateTestFHIRBundle(json,"1eb05918-f50c-4cad-a827-3c78f296a10a");
+
Assert.assertFalse("Payload Missing some data", result);
}
@@ -135,7 +137,7 @@ public void testGetMissingVLFHIRCodesAsString_withOutMissingCodes() {
String json = parser.encodeResourceToString(bundle);
- String result = service.getMissingVLFHIRCodesAsString(json);
+ String result = service.getMissingVLFHIRCodesAsString(json,"1eb05918-f50c-4cad-a827-3c78f296a10a");
Assert.assertEquals("", result);
}
@@ -159,7 +161,7 @@ public void testGetMissingVLFHIRCodesAsString_withTwoMissingCodes() {
String missingConceptName1 = service.getVLMissingCconcept("202501020").getName().getName();
String missingConceptName2 = service.getVLMissingCconcept("202501021").getName().getName();
- String result = service.getMissingVLFHIRCodesAsString(json);
+ String result = service.getMissingVLFHIRCodesAsString(json,"1eb05918-f50c-4cad-a827-3c78f296a10a");
Assert.assertEquals(String.format("%s,%s", missingConceptName1, missingConceptName2), result);
}
diff --git a/api/src/test/resources/org/openmrs/module/ugandaemrsync/include/globalPropertiesDataSet.xml b/api/src/test/resources/org/openmrs/module/ugandaemrsync/include/globalPropertiesDataSet.xml
index 62478ddb..dddda03e 100644
--- a/api/src/test/resources/org/openmrs/module/ugandaemrsync/include/globalPropertiesDataSet.xml
+++ b/api/src/test/resources/org/openmrs/module/ugandaemrsync/include/globalPropertiesDataSet.xml
@@ -5,5 +5,6 @@
+
diff --git a/omod/pom.xml b/omod/pom.xml
index a58f8ba5..e389d3a1 100644
--- a/omod/pom.xml
+++ b/omod/pom.xml
@@ -3,7 +3,7 @@
org.openmrs.module
ugandaemrsync
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
ugandaemrsync-omod
diff --git a/omod/src/main/java/org/openmrs/module/ugandaemrsync/web/resource/ReferralOrderResource.java b/omod/src/main/java/org/openmrs/module/ugandaemrsync/web/resource/ReferralOrderResource.java
index cc512261..86773e69 100644
--- a/omod/src/main/java/org/openmrs/module/ugandaemrsync/web/resource/ReferralOrderResource.java
+++ b/omod/src/main/java/org/openmrs/module/ugandaemrsync/web/resource/ReferralOrderResource.java
@@ -4,11 +4,15 @@
import io.swagger.models.ModelImpl;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.openmrs.*;
import org.openmrs.api.ConceptService;
import org.openmrs.api.OrderService;
import org.openmrs.api.context.Context;
import org.openmrs.module.ugandaemrsync.api.UgandaEMRSyncService;
+import org.openmrs.module.ugandaemrsync.api.impl.UgandaEMRSyncServiceImpl;
import org.openmrs.module.ugandaemrsync.model.SyncTask;
import org.openmrs.module.ugandaemrsync.model.SyncTaskType;
import org.openmrs.module.ugandaemrsync.web.resource.DTO.ReferralOrder;
@@ -36,6 +40,7 @@
@Resource(name = RestConstants.VERSION_1 + "/referredorders", supportedClass = ReferralOrder.class, supportedOpenmrsVersions = {"1.9.* - 9.*"})
public class ReferralOrderResource extends DelegatingCrudResource {
+
@Override
public ReferralOrder newDelegate() {
throw new ResourceDoesNotSupportOperationException("Operation not supported");
@@ -66,6 +71,8 @@ public ReferralOrder getByUniqueId(String uniqueId) {
@Override
public NeedsPaging doGetAll(RequestContext context) throws ResponseException {
+
+ List concepts = getConceptsFromSyncTaskType();
OrderService orderService = Context.getOrderService();
CareSetting careSetting = orderService.getCareSettingByUuid(CARE_SETTING_UUID_OPD);
@@ -74,7 +81,7 @@ public NeedsPaging doGetAll(RequestContext context) throws Respon
OrderSearchCriteria orderSearchCriteria = new OrderSearchCriteria(
null,
careSetting,
- Collections.singletonList(Context.getConceptService().getConcept(165412)),
+ concepts,
Collections.singletonList(orderType),
null,
null,
@@ -279,4 +286,58 @@ private Order.FulfillerStatus parseFulfillerStatus(String status) {
return Order.FulfillerStatus.IN_PROGRESS;
}
}
+
+ /**
+ * Builds a list of Concepts from the SyncTaskType configured for Viral Load sync.
+ * The SyncTaskType.getDataType() must contain a comma-separated list of Concept IDs, UUIDs, or Names.
+ *
+ * @return List of Concepts resolved from the SyncTaskType dataType.
+ */
+ public static List getConceptsFromSyncTaskType() {
+
+ UgandaEMRSyncService syncService = Context.getService(UgandaEMRSyncService.class);
+ SyncTaskType syncTaskType = syncService.getSyncTaskTypeByUUID(VIRAL_LOAD_SYNC_TYPE_UUID);
+
+ List concepts = new ArrayList<>();
+
+ // Early exit if syncTaskType or dataType is missing
+ if (syncTaskType == null) {
+ //log.warning("SyncTaskType not found for UUID: " + VIRAL_LOAD_SYNC_TYPE_UUID);
+ return concepts;
+ }
+
+ String dataType = syncTaskType.getDataType();
+ if (StringUtils.isBlank(dataType)) {
+ //log.warning("SyncTaskType dataType is blank for UUID: " + VIRAL_LOAD_SYNC_TYPE_UUID);
+ return concepts;
+ }
+
+ // Parse and resolve each token
+ for (String token : dataType.split(",")) {
+ token = token.trim();
+ if (token.isEmpty()) {
+ continue;
+ }
+
+ Concept concept = null;
+ if (StringUtils.isNumeric(token)) {
+ // Concept ID
+ concept = Context.getConceptService().getConcept(Integer.parseInt(token));
+ } else {
+ // Try UUID, then Name
+ concept = Context.getConceptService().getConceptByUuid(token);
+ if (concept == null) {
+ concept = Context.getConceptService().getConceptByName(token);
+ }
+ }
+
+ if (concept != null) {
+ concepts.add(concept);
+ } else {
+ //log.warning("No concept found for token: " + token);
+ }
+ }
+
+ return concepts;
+ }
}
diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml
index 3cc3a10e..6e43c22d 100644
--- a/omod/src/main/resources/config.xml
+++ b/omod/src/main/resources/config.xml
@@ -425,6 +425,14 @@
The Concept ID for allowable referral orders to be synced to CPHL
+
+
+ ugandaemrsync.testReferralValidators
+ {"validatableTest":["1eb05918-f50c-4cad-a827-3c78f296a10a","163610AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","dc8d4af2-30ab-102d-86b0-7a5022ba4115"],"testValidators":{"1eb05918-f50c-4cad-a827-3c78f296a10a":"413946009,385354005,202501002,LL5723-3,202501009,202501016,202501020,33882-2","163610AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA":"413946009,385354005,202501002,LL5723-3,202501009,202501016,202501020,33882-2","dc8d4af2-30ab-102d-86b0-7a5022ba4115":""}}
+
+ The allowable test order to be referred and their data requirements.
+
+
diff --git a/pom.xml b/pom.xml
index 00bf0bd2..0047b2bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
org.openmrs.module
ugandaemrsync
- 2.0.1-SNAPSHOT
+ 2.0.2-SNAPSHOT
pom
UgandaemrSync
Provides data sharing capabilities from the facility level installation with other systems