From 8149615745ebfd45832671e6ea2fb750e53ce190 Mon Sep 17 00:00:00 2001 From: Patrick LaRocque Date: Tue, 20 Sep 2022 16:28:10 -0400 Subject: [PATCH] Merge the upstream coverage-rules changes to make use of the coverage in a CRD rule. --- .../services/crd/r4/FhirBundleProcessor.java | 187 +++++++++--------- .../services/crd/r4/OrderSignService.java | 2 +- 2 files changed, 94 insertions(+), 95 deletions(-) diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java index 470bc4aee..3b0554a8c 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java @@ -133,136 +133,135 @@ public boolean verifyDeidentifiedResources(Bundle bundle) { public void processDeviceRequests(Bundle deviceRequestBundle, Bundle coverageBundle) { List deviceRequestList = Utilities.getResourcesOfTypeFromBundle(DeviceRequest.class, deviceRequestBundle); + if (deviceRequestList.isEmpty()) return; List patients = Utilities.getResourcesOfTypeFromBundle(Patient.class, deviceRequestBundle); logger.info("r4/FhirBundleProcessor::processDeviceRequests: Found " + patients.size() + " patients."); - List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); // TODO - do something with the coverage. - if (deviceRequestList.isEmpty()) return; - + List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); + List coverageList = Utilities.getResourcesOfTypeFromBundle(Coverage.class, coverageBundle); + logger.info("r4/FhirBundleProcessor::processDeviceRequests: " + deviceRequestList.size() + " DeviceRequest(s) found"); verifyDeidentifiedResources(deviceRequestBundle); verifyDeidentifiedResources(coverageBundle); for (DeviceRequest deviceRequest : deviceRequestList) { - if (idInSelectionsList(deviceRequest.getId())) { - List criteriaList = createCriteriaList(deviceRequest.getCodeCodeableConcept(), deviceRequest.getInsurance(), payorList); - - String patientReference = deviceRequest.getSubject().getReference(); - List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); - if (referencedPrefetechedPatients.size() < 1) { - logger.warn("r4/FhirBundleProcessor::processDeviceRequests: WARNING - Device Request '" - + deviceRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" - + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); - buildExecutionContexts(criteriaList, null, "device_request", deviceRequest); - - } else { - Patient patientToUse = referencedPrefetechedPatients.get(0); - buildExecutionContexts(criteriaList, patientToUse, "device_request", deviceRequest); - } - + if (!idInSelectionsList(deviceRequest.getId())) continue; + + List criteriaList = createCriteriaList(deviceRequest.getCodeCodeableConcept(), deviceRequest.getInsurance(), payorList); + + String patientReference = deviceRequest.getSubject().getReference(); + List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); + if (referencedPrefetechedPatients.size() < 1) { + logger.warn("r4/FhirBundleProcessor::processDeviceRequests: WARNING - Device Request '" + + deviceRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" + + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); + buildExecutionContexts(criteriaList, null, coverageList, "device_request", deviceRequest); + } else { + Patient patientToUse = referencedPrefetechedPatients.get(0); + buildExecutionContexts(criteriaList, patientToUse, coverageList, "device_request", deviceRequest); } } } public void processMedicationRequests(Bundle medicationRequestBundle, Bundle coverageBundle) { List medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle); + if (medicationRequestList.isEmpty()) return; List patients = Utilities.getResourcesOfTypeFromBundle(Patient.class, medicationRequestBundle); List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); - if (medicationRequestList.isEmpty()) return; + List coverageList = Utilities.getResourcesOfTypeFromBundle(Coverage.class, coverageBundle); logger.info("r4/FhirBundleProcessor::processMedicationRequests: MedicationRequest(s) found"); verifyDeidentifiedResources(medicationRequestBundle); verifyDeidentifiedResources(coverageBundle); for (MedicationRequest medicationRequest : medicationRequestList) { - if (idInSelectionsList(medicationRequest.getId())) { - String patientReference = medicationRequest.getSubject().getReference(); + if (!idInSelectionsList(medicationRequest.getId())) continue; - List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); - List criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), payorList); - if (referencedPrefetechedPatients.size() < 1) { - logger.warn("r4/FhirBundleProcessor::processMedicationRequests: WARNING - Medication Request '" - + medicationRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" - + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); - buildExecutionContexts(criteriaList, null, "medication_request", medicationRequest); - } else { - Patient patientToUse = referencedPrefetechedPatients.get(0); - buildExecutionContexts(criteriaList, patientToUse, "medication_request", medicationRequest); - } + String patientReference = medicationRequest.getSubject().getReference(); + + List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); + List criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), payorList); + if (referencedPrefetechedPatients.size() < 1) { + logger.warn("r4/FhirBundleProcessor::processMedicationRequests: WARNING - Medication Request '" + + medicationRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" + + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); + buildExecutionContexts(criteriaList, null, coverageList, "medication_request", medicationRequest); + } else { + Patient patientToUse = referencedPrefetechedPatients.get(0); + buildExecutionContexts(criteriaList, patientToUse, coverageList, "medication_request", medicationRequest); } } } public void processMedicationDispenses(Bundle medicationDispenseBundle, Bundle coverageBundle) { List medicationDispenseList = Utilities.getResourcesOfTypeFromBundle(MedicationDispense.class, medicationDispenseBundle); + if (medicationDispenseList.isEmpty()) return; List patients = Utilities.getResourcesOfTypeFromBundle(Patient.class, medicationDispenseBundle); List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); + List coverageList = Utilities.getResourcesOfTypeFromBundle(Coverage.class, coverageBundle); List medicationPayorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, medicationDispenseBundle); payorList.addAll(medicationPayorList); - if (medicationDispenseList.isEmpty()) return; logger.info("r4/FhirBundleProcessor::processMedicationDispenses: MedicationDispense(s) found"); verifyDeidentifiedResources(medicationDispenseBundle); verifyDeidentifiedResources(coverageBundle); for (MedicationDispense medicationDispense : medicationDispenseList) { - if (idInSelectionsList(medicationDispense.getId())) { - String patientReference = medicationDispense.getSubject().getReference(); - List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); - List criteriaList = createCriteriaList(medicationDispense.getMedicationCodeableConcept(), null, payorList); - if (referencedPrefetechedPatients.size() < 1) { - logger.warn("r4/FhirBundleProcessor::processMedicationDispenses: WARNING - Medication Dispense '" - + medicationDispense.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" - + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); - buildExecutionContexts(criteriaList,null, "medication_dispense", medicationDispense); - } else { - Patient patientToUse = referencedPrefetechedPatients.get(0); - buildExecutionContexts(criteriaList,patientToUse, "medication_dispense", medicationDispense); - } - + if (!idInSelectionsList(medicationDispense.getId())) continue; + + String patientReference = medicationDispense.getSubject().getReference(); + List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); + List criteriaList = createCriteriaList(medicationDispense.getMedicationCodeableConcept(), null, payorList); + if (referencedPrefetechedPatients.size() < 1) { + logger.warn("r4/FhirBundleProcessor::processMedicationDispenses: WARNING - Medication Dispense '" + + medicationDispense.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" + + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); + buildExecutionContexts(criteriaList,null, coverageList, "medication_dispense", medicationDispense); + } else { + Patient patientToUse = referencedPrefetechedPatients.get(0); + buildExecutionContexts(criteriaList,patientToUse, coverageList, "medication_dispense", medicationDispense); } } } public void processServiceRequests(Bundle serviceRequestBundle, Bundle coverageBundle) { - List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); List serviceRequestList = Utilities.getResourcesOfTypeFromBundle(ServiceRequest.class, serviceRequestBundle); - List patients = Utilities.getResourcesOfTypeFromBundle(Patient.class, serviceRequestBundle); if (serviceRequestList.isEmpty()) return; + List patients = Utilities.getResourcesOfTypeFromBundle(Patient.class, serviceRequestBundle); + List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); + List coverageList = Utilities.getResourcesOfTypeFromBundle(Coverage.class, coverageBundle); + logger.info("r4/FhirBundleProcessor::getAndProcessServiceRequests: ServiceRequest(s) found"); verifyDeidentifiedResources(serviceRequestBundle); verifyDeidentifiedResources(coverageBundle); for (ServiceRequest serviceRequest : serviceRequestList) { - if (idInSelectionsList(serviceRequest.getId())) { - String patientReference = serviceRequest.getSubject().getReference(); - List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); - List criteriaList = createCriteriaList(serviceRequest.getCode(), serviceRequest.getInsurance(), payorList); - if (referencedPrefetechedPatients.size() < 1) { - logger.warn("r4/FhirBundleProcessor::processServiceRequests: WARNING - Service Request '" - + serviceRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" - + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); - buildExecutionContexts(criteriaList, null, "service_request", serviceRequest); - } else { - Patient patientToUse = referencedPrefetechedPatients.iterator().next(); - logger.info("r4/FhirBundleProcessor::processMedicationDispenses: Found Patient '" + patientToUse + "'."); - buildExecutionContexts(criteriaList, patientToUse, "service_request", serviceRequest); - } - + if (!idInSelectionsList(serviceRequest.getId())) continue; + + String patientReference = serviceRequest.getSubject().getReference(); + List referencedPrefetechedPatients = extractReferencedResources(patients, patientReference); + List criteriaList = createCriteriaList(serviceRequest.getCode(), serviceRequest.getInsurance(), payorList); + if (referencedPrefetechedPatients.size() < 1) { + logger.warn("r4/FhirBundleProcessor::processServiceRequests: WARNING - Service Request '" + + serviceRequest.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" + + patientReference + "' and prefetch contains patients " + patients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); + buildExecutionContexts(criteriaList, null, coverageList, "service_request", serviceRequest); + } else { + Patient patientToUse = referencedPrefetechedPatients.iterator().next(); + logger.info("r4/FhirBundleProcessor::processMedicationDispenses: Found Patient '" + patientToUse + "'."); + buildExecutionContexts(criteriaList, patientToUse, coverageList, "service_request", serviceRequest); } } } public void processOrderSelectMedicationStatements(Bundle medicationRequestBundle, Bundle medicationStatementBundle, Bundle coverageBundle) { List medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle); + if (medicationRequestList.isEmpty()) return; List medicationStatementList = Utilities.getResourcesOfTypeFromBundle(MedicationStatement.class, medicationStatementBundle); - List medStatementPatients = Utilities.getResourcesOfTypeFromBundle(Patient.class, medicationStatementBundle); List payorList = Utilities.getResourcesOfTypeFromBundle(Organization.class, coverageBundle); - if (medicationRequestList.isEmpty()) return; - logger.info("r4/FhirBundleProcessor::processOrderSelectMedicationStatements: MedicationRequests(s) found"); verifyDeidentifiedResources(medicationRequestBundle); verifyDeidentifiedResources(medicationStatementBundle); @@ -270,32 +269,28 @@ public void processOrderSelectMedicationStatements(Bundle medicationRequestBundl // process each of the MedicationRequests for (MedicationRequest medicationRequest : medicationRequestList) { - if (idInSelectionsList(medicationRequest.getId())) { - - // run on each of the MedicationStatements - for (MedicationStatement medicationStatement : medicationStatementList) { - logger.info("r4/FhirBundleProcessor::processOrderSelectMedicationStatements: MedicationStatement found: " + medicationStatement.getId()); - String patientReference = medicationStatement.getSubject().getReference(); - List referencedPrefetechedPatients = extractReferencedResources(medStatementPatients, patientReference); - List criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), payorList); - if (referencedPrefetechedPatients.size() < 1) { - logger.warn("r4/FhirBundleProcessor::processMedicationStatements: WARNING - Medication Statement '" - + medicationStatement.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" - + patientReference + "' and prefetch contains patients " + medStatementPatients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); - HashMap cqlParams = new HashMap<>(); - cqlParams.put("Patient", null); - cqlParams.put("medication_request", medicationRequest); - cqlParams.put("medication_statement", medicationStatement); - buildExecutionContexts(criteriaList, cqlParams); - } else { - Patient patientToUse = referencedPrefetechedPatients.get(0); - HashMap cqlParams = new HashMap<>(); - cqlParams.put("Patient", (Patient) patientToUse); - cqlParams.put("medication_request", medicationRequest); - cqlParams.put("medication_statement", medicationStatement); - buildExecutionContexts(criteriaList, cqlParams); - } + if (!idInSelectionsList(medicationRequest.getId())) continue; + + // run on each of the MedicationStatements + for (MedicationStatement medicationStatement : medicationStatementList) { + logger.info("r4/FhirBundleProcessor::processOrderSelectMedicationStatements: MedicationStatement found: " + medicationStatement.getId()); + String patientReference = medicationStatement.getSubject().getReference(); + List referencedPrefetechedPatients = extractReferencedResources(medStatementPatients, patientReference); + List criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), payorList); + HashMap cqlParams = new HashMap<>(); + if (referencedPrefetechedPatients.size() < 1) { + logger.warn("r4/FhirBundleProcessor::processMedicationStatements: WARNING - Medication Statement '" + + medicationStatement.getId() + "' does not contain a reference to any prefetched patients. Resource contains patient reference '" + + patientReference + "' and prefetch contains patients " + medStatementPatients.stream().map(patient -> patient.getId()).collect(Collectors.toSet()) + "."); + cqlParams.put("Patient", null); + } else { + Patient patientToUse = referencedPrefetechedPatients.get(0); + cqlParams.put("Patient", (Patient) patientToUse); } + + cqlParams.put("medication_request", medicationRequest); + cqlParams.put("medication_statement", medicationStatement); + buildExecutionContexts(criteriaList, cqlParams); } } } @@ -347,10 +342,14 @@ private List createCriteriaList(CodeableConcept } } - private void buildExecutionContexts(List criteriaList, Patient patient, String requestType, DomainResource request) { + private void buildExecutionContexts(List criteriaList, Patient patient, List coverages, String requestType, DomainResource request) { System.out.println("buildExecutionContexts::PATIENT: " + patient); HashMap cqlParams = new HashMap<>(); cqlParams.put("Patient", patient); + if(coverages.size() > 0) { + // In this case, we're just using the first coverage. But in a payer implementation, it should find and use the correct relevant coverage(s). + cqlParams.put("Coverage", coverages.get(0)); + } cqlParams.put(requestType, request); buildExecutionContexts(criteriaList, cqlParams); diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java index 509eebab2..507af5648 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSignService.java @@ -65,7 +65,7 @@ public class OrderSignService extends CdsService { public List createCqlExecutionContexts(OrderSignRequest orderSignRequest, FileStore fileStore, String baseUrl) { FhirBundleProcessor fhirBundleProcessor = new FhirBundleProcessor(fileStore, baseUrl); CrdPrefetch prefetch = orderSignRequest.getPrefetch(); - Bundle coverageBundle = prefetch.getCoverageBundle(); // TODO - do something with coverage. + Bundle coverageBundle = prefetch.getCoverageBundle(); fhirBundleProcessor.processDeviceRequests(prefetch.getDeviceRequestBundle(), coverageBundle); fhirBundleProcessor.processMedicationRequests(prefetch.getMedicationRequestBundle(), coverageBundle); fhirBundleProcessor.processServiceRequests(prefetch.getServiceRequestBundle(), coverageBundle);