diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProvider.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProvider.java index 1c73395a2..417d78491 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProvider.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProvider.java @@ -28,16 +28,8 @@ public void transform(HealthData resource, Map args) { return; } - // Extract or create the OBR-16 extension from the ServiceRequest Extension obrExtension = HapiHelper.ensureExtensionExists(serviceRequest, HapiHelper.EXTENSION_OBR_URL); - - // Extract or create the OBR-16 data type extension - Extension obr16Extension = - HapiHelper.ensureSubExtensionExists( - obrExtension, HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()); - - // Set the ORC-12 Practitioner in the OBR-16 extension - HapiHelper.setOBR16WithPractitioner(obr16Extension, practitionerRole); + HapiHelper.setOBR16WithPractitioner(obrExtension, practitionerRole); } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifiers.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifiers.java index 524665d26..111a5a523 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifiers.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifiers.java @@ -15,7 +15,8 @@ public class RemovePatientIdentifiers implements CustomFhirTransformation { @Override public void transform(HealthData resource, Map args) { Bundle bundle = (Bundle) resource.getUnderlyingData(); - HapiHelper.setPID3_4Value(bundle, ""); // remove PID.3-4 - HapiHelper.setPID3_5Value(bundle, ""); // remove PID.3-5 + + HapiHelper.setPID3_4Value(bundle, null); + HapiHelper.removePID3_5Value(bundle); } } diff --git a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCode.java b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCode.java index 5cf7d4ce2..a7244ba6d 100644 --- a/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCode.java +++ b/etor/src/main/java/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCode.java @@ -12,8 +12,6 @@ public class RemovePatientNameTypeCode implements CustomFhirTransformation { @Override public void transform(final HealthData resource, final Map args) { Bundle bundle = (Bundle) resource.getUnderlyingData(); - // Need to set the value for extension to empty instead of removing the extension, - // otherwise RS will set its own value in its place - HapiHelper.setPID5_7ExtensionValue(bundle, null); + HapiHelper.removePID5_7Value(bundle); } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProviderTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProviderTest.groovy index eb74ed5b6..a7db7112d 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProviderTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProviderTest.groovy @@ -7,8 +7,6 @@ import gov.hhs.cdc.trustedintermediary.external.hapi.HapiHelper import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.DiagnosticReport -import org.hl7.fhir.r4.model.Practitioner -import org.hl7.fhir.r4.model.Reference import org.hl7.fhir.r4.model.ServiceRequest import spock.lang.Specification @@ -119,7 +117,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ evaluateOrc12Values(bundle, EXPECTED_NPI, EXPECTED_FIRST_NAME, EXPECTED_LAST_NAME, EXPECTED_NAME_TYPE_CODE, EXPECTED_IDENTIFIER_TYPE_CODE) // OBR16 should not exist initially - def obr16Practitioner = getObr16ExtensionPractitioner(serviceRequest) + def obr16Practitioner = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) obr16Practitioner == null when: @@ -191,7 +189,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ } void evaluateOrc12IsNull(Bundle bundle) { - assert getOrc12ExtensionPractitioner(bundle) == null + assert HapiHelper.getOrc12ExtensionPractitioner(bundle) == null } void evaluateOrc12Values( @@ -201,7 +199,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ String expectedLastName, String expectedNameTypeCode, String expectedIdentifierTypeCode) { - def practitioner = getOrc12ExtensionPractitioner(bundle) + def practitioner = HapiHelper.getOrc12ExtensionPractitioner(bundle) def xcnExtension = practitioner.getExtensionByUrl(PRACTITIONER_EXTENSION_URL) assert practitioner.identifier[0]?.value == expectedNpi @@ -214,7 +212,8 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ } void evaluateObr16IsNull(ServiceRequest serviceRequest) { - assert getObr16ExtensionPractitioner(serviceRequest) == null + assert HapiHelper.getObr16Extension(serviceRequest) == null + assert HapiHelper.getObr16ExtensionPractitioner(serviceRequest) == null } void evaluateObr16Values( @@ -224,7 +223,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ String expectedLastName, String expectedNameTypeCode, String expectedIdentifierTypeCode) { - def practitioner = getObr16ExtensionPractitioner(serviceRequest) + def practitioner = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) def xcnExtension = practitioner.getExtensionByUrl(PRACTITIONER_EXTENSION_URL) assert practitioner.identifier[0]?.value == expectedNpi @@ -234,40 +233,4 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{ def codingSystem = practitioner.identifier[0]?.type?.coding assert codingSystem == null || codingSystem[0]?.code == expectedIdentifierTypeCode } - - Practitioner getObr16ExtensionPractitioner (serviceRequest) { - def resource - try { - def extensionByUrl1 = serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_OBR_URL) - def extensionByUrl2 = extensionByUrl1.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) - def value = extensionByUrl2.value - resource = value.getResource() - return resource - } catch(Exception ignored) { - resource = null - return resource - } - } - - Practitioner getOrc12ExtensionPractitioner(Bundle bundle) { - def diagnosticReport = HapiHelper.getDiagnosticReport(bundle) - def serviceRequest = HapiHelper.getServiceRequest(diagnosticReport) - - def orcExtension = serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_ORC_URL) - def orc12Extension = orcExtension.getExtensionByUrl(HapiHelper.EXTENSION_ORC12_URL) - - if (orc12Extension == null) { - return null - } - - def practitionerReference = (Reference) orc12Extension.getValue() - def practitionerUrl = practitionerReference.getReference() - - for (Bundle.BundleEntryComponent entry : bundle.getEntry()) { - if (Objects.equals(entry.getFullUrl(), practitionerUrl) && entry.getResource() instanceof Practitioner) - return (Practitioner) entry.getResource() - } - - return null - } } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifierTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifierTest.groovy index e1920f2c6..ef163ffbe 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifierTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientIdentifierTest.groovy @@ -33,10 +33,10 @@ class RemovePatientIdentifierTest extends Specification { when: transformClass.transform(fhirResource, null) - def actualPid3_4 = HapiFhirHelper.getPID3_4Value(bundle) - def actualPid3_5 = HapiFhirHelper.getPID3_5Value(bundle) then: + def actualPid3_4 = HapiFhirHelper.getPID3_4Value(bundle) + def actualPid3_5 = HapiFhirHelper.getPID3_5Value(bundle) actualPid3_4 == null || actualPid3_4.isEmpty() actualPid3_5 == null || actualPid3_5.isEmpty() } diff --git a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCodeTest.groovy b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCodeTest.groovy index 53927b19f..b5780983e 100644 --- a/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCodeTest.groovy +++ b/etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/RemovePatientNameTypeCodeTest.groovy @@ -22,18 +22,22 @@ class RemovePatientNameTypeCodeTest extends Specification { def "remove PID.5-7 from Bundle"() { given: - def fhirResource = ExamplesHelper.getExampleFhirResource("../CA/002_CA_ORU_R01_initial_translation.fhir") + def fhirResource = ExamplesHelper.getExampleFhirResource("../CA/007_CA_ORU_R01_CDPH_produced_UCSD2024-07-11-16-02-17-749_1_hl7_translation.fhir") def bundle = fhirResource.getUnderlyingData() as Bundle - def pid5_7 = HapiFhirHelper.getPID5_7Value(bundle) + def pid5Extension = HapiHelper.getPID5Extension(bundle) + def patientName = HapiHelper.getPIDPatient(bundle).getNameFirstRep() + def patientNameUse = patientName.getUse() expect: - pid5_7 != null + pid5Extension.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL) != null + patientNameUse.toString() == "OFFICIAL" when: transformClass.transform(fhirResource, null) then: - HapiFhirHelper.getPID5_7Value(bundle) == null + pid5Extension.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL) == null + !patientName.hasUse() } def "don't throw exception if patient resource not present"() { diff --git a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java index 8ff7cb02f..a35324c0a 100644 --- a/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java +++ b/shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java @@ -18,6 +18,7 @@ import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ServiceRequest; import org.hl7.fhir.r4.model.StringType; @@ -268,15 +269,27 @@ public static Identifier getPID3_4Identifier(Bundle bundle) { return null; } Organization organization = (Organization) identifier.getAssigner().getResource(); + if (organization == null) { + return null; + } return organization.getIdentifierFirstRep(); } public static void setPID3_4Value(Bundle bundle, String value) { - Identifier identifier = getPID3_4Identifier(bundle); - if (identifier == null) { + if (value == null) { + Identifier pid3Identifier = getPID3Identifier(bundle); + if (pid3Identifier == null) { + return; + } + pid3Identifier.setAssigner(null); return; } - identifier.setValue(value); + + Identifier pid3_4Identifier = getPID3_4Identifier(bundle); + if (pid3_4Identifier == null) { + return; + } + pid3_4Identifier.setValue(value); } // PID-3.5 - Identifier Type Code @@ -288,6 +301,29 @@ public static void setPID3_5Value(Bundle bundle, String value) { setCX5Value(identifier, value); } + public static void removePID3_5Value(Bundle bundle) { + Identifier patientIdentifier = getPID3Identifier(bundle); + if (patientIdentifier == null) { + return; + } + + patientIdentifier.setType(null); + + Extension cxExtension = patientIdentifier.getExtensionByUrl(EXTENSION_CX_IDENTIFIER_URL); + if (cxExtension == null) { + return; + } + + if (cxExtension.hasExtension(EXTENSION_CX5_URL)) { + cxExtension.removeExtension(EXTENSION_CX5_URL); + } + + // The cx-identifier extension can be removed if it has no more sub-extensions + if (cxExtension.getExtension().isEmpty()) { + patientIdentifier.removeExtension(EXTENSION_CX_IDENTIFIER_URL); + } + } + // PID-5 - Patient Name public static Extension getPID5Extension(Bundle bundle) { Patient patient = getPIDPatient(bundle); @@ -295,15 +331,31 @@ public static Extension getPID5Extension(Bundle bundle) { return null; } HumanName name = patient.getNameFirstRep(); - return name.getExtensionByUrl(HapiHelper.EXTENSION_XPN_HUMAN_NAME_URL); + return name.getExtensionByUrl(EXTENSION_XPN_HUMAN_NAME_URL); } public static void setPID5_7ExtensionValue(Bundle bundle, String value) { Extension extension = getPID5Extension(bundle); - if (extension != null && extension.hasExtension(HapiHelper.EXTENSION_XPN7_URL)) { - extension - .getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL) - .setValue(new StringType(value)); + if (extension != null && extension.hasExtension(EXTENSION_XPN7_URL)) { + extension.getExtensionByUrl(EXTENSION_XPN7_URL).setValue(new StringType(value)); + } + } + + public static void removePID5_7Value(Bundle bundle) { + Patient patient = getPIDPatient(bundle); + if (patient == null) { + return; + } + HumanName patientName = patient.getNameFirstRep(); + patientName.setUse(null); + + Extension pid5Extension = getPID5Extension(bundle); + if (pid5Extension == null) { + return; + } + Extension xpn7Extension = pid5Extension.getExtensionByUrl(EXTENSION_XPN7_URL); + if (xpn7Extension != null) { + pid5Extension.removeExtension(EXTENSION_XPN7_URL); } } @@ -499,17 +551,69 @@ public static String getOBR4_1Value(ServiceRequest serviceRequest) { return getCWE1Value(cc.getCoding().get(0)); } - // OBR16 - Ordering Provider - - // OBR16 - + // OBR-16 - Ordering Provider public static void setOBR16WithPractitioner( - Extension obr16Extension, PractitionerRole practitionerRole) { - if (practitionerRole == null) { + Extension obrExtension, PractitionerRole practitionerRole) { + if (practitionerRole == null || !practitionerRole.getPractitioner().hasReference()) { return; } + + Extension obr16Extension = + ensureSubExtensionExists(obrExtension, EXTENSION_OBR16_DATA_TYPE.toString()); + obr16Extension.setValue(practitionerRole.getPractitioner()); } + public static Extension getObr16Extension(ServiceRequest serviceRequest) { + Extension obrExtension = serviceRequest.getExtensionByUrl(EXTENSION_OBR_URL); + if (obrExtension == null) { + return null; + } + return obrExtension.getExtensionByUrl(EXTENSION_OBR16_DATA_TYPE.toString()); + } + + public static Practitioner getObr16ExtensionPractitioner(ServiceRequest serviceRequest) { + Extension obr16Extension = getObr16Extension(serviceRequest); + if (obr16Extension == null || obr16Extension.getValue() == null) { + return null; + } + + if (obr16Extension.getValue() instanceof Reference reference + && reference.getResource() instanceof Practitioner practitioner) { + return practitioner; + } + return null; + } + + // ORC-12 - Ordering Provider + public static Practitioner getOrc12ExtensionPractitioner(Bundle bundle) { + DiagnosticReport diagnosticReport = getDiagnosticReport(bundle); + if (diagnosticReport == null) return null; + + ServiceRequest serviceRequest = getServiceRequest(diagnosticReport); + if (serviceRequest == null) return null; + + Extension orcExtension = serviceRequest.getExtensionByUrl(EXTENSION_ORC_URL); + if (orcExtension == null) return null; + + Extension orc12Extension = orcExtension.getExtensionByUrl(EXTENSION_ORC12_URL); + if (orc12Extension == null) return null; + + Reference practitionerReference = (Reference) orc12Extension.getValue(); + if (practitionerReference == null) return null; + + String practitionerUrl = practitionerReference.getReference(); + if (practitionerUrl == null) return null; + + for (Bundle.BundleEntryComponent entry : bundle.getEntry()) { + if (Objects.equals(entry.getFullUrl(), practitionerUrl) + && entry.getResource() instanceof Practitioner practitioner) + return practitioner; + } + + return null; + } + /** * Ensures that the extension exists for a given serviceRequest. If the extension does not * exist, it will create it. @@ -678,9 +782,9 @@ public static void removeHl7FieldIdentifier(List identifiers, String public static String urlForCodeType(String code) { return switch (code) { - case HapiHelper.LOINC_CODE -> HapiHelper.LOINC_URL; - case HapiHelper.PLT_CODE -> null; - default -> HapiHelper.LOCAL_CODE_URL; + case LOINC_CODE -> LOINC_URL; + case PLT_CODE -> null; + default -> LOCAL_CODE_URL; }; } @@ -695,22 +799,19 @@ public static String urlForCodeType(String code) { */ public static boolean hasDefinedCoding( Coding coding, String codingExt, String codingSystemExt) { - var codingExtMatch = - hasMatchingCodingExtension(coding, HapiHelper.EXTENSION_CWE_CODING, codingExt); + var codingExtMatch = hasMatchingCodingExtension(coding, EXTENSION_CWE_CODING, codingExt); var codingSystemExtMatch = - hasMatchingCodingExtension( - coding, HapiHelper.EXTENSION_CODING_SYSTEM, codingSystemExt); + hasMatchingCodingExtension(coding, EXTENSION_CODING_SYSTEM, codingSystemExt); return codingExtMatch && codingSystemExtMatch; } private static boolean hasMatchingCodingExtension( Coding coding, String extensionUrl, String valueToMatch) { - if (!HapiHelper.hasCodingExtensionWithUrl(coding, extensionUrl)) { + if (!hasCodingExtensionWithUrl(coding, extensionUrl)) { return false; } - var extensionValue = - HapiHelper.getCodingExtensionByUrl(coding, extensionUrl).getValue().toString(); + var extensionValue = getCodingExtensionByUrl(coding, extensionUrl).getValue().toString(); return Objects.equals(valueToMatch, extensionValue); } diff --git a/shared/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelperTest.groovy b/shared/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelperTest.groovy index b8ff46c6b..54283fc92 100644 --- a/shared/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelperTest.groovy +++ b/shared/src/test/groovy/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelperTest.groovy @@ -2,6 +2,7 @@ package gov.hhs.cdc.trustedintermediary.external.hapi import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.Coding +import org.hl7.fhir.r4.model.DiagnosticReport import org.hl7.fhir.r4.model.Extension import org.hl7.fhir.r4.model.Identifier import org.hl7.fhir.r4.model.MessageHeader @@ -430,30 +431,58 @@ class HapiHelperTest extends Specification { } // PID-3.4 - Assigning Authority - def "patient assigning authority methods work as expected"() { + def "getPID3_4Identifier returns null when bundle is empty"() { given: - def pid3_4 = "pid3_4" - - when: def bundle = new Bundle() - then: + expect: HapiHelper.getPID3_4Identifier(bundle) == null + } + + def "setPID3_4Value does not modify bundle without PID-3 identifier"() { + given: + def pid3_4Value = "pid3_4" + def bundle = new Bundle() when: - HapiHelper.setPID3_4Value(bundle, pid3_4) + HapiHelper.setPID3_4Value(bundle, pid3_4Value) then: HapiFhirHelper.getPID3_4Value(bundle) == null + } - when: + def "setPID3_4Value updates correctly when patient has a PID-3 identifier"() { + given: + def pid3_4Value = "pid3_4" + def bundle = new Bundle() HapiFhirHelper.createPIDPatient(bundle) HapiFhirHelper.setPID3Identifier(bundle, new Identifier()) HapiFhirHelper.setPID3_4Identifier(bundle, new Identifier()) - HapiHelper.setPID3_4Value(bundle, pid3_4) + + when: + HapiHelper.setPID3_4Value(bundle, pid3_4Value) then: - HapiFhirHelper.getPID3_4Value(bundle) == pid3_4 + HapiFhirHelper.getPID3_4Value(bundle) == pid3_4Value + } + + def "setPID3_4Value updates correctly when patient has a PID-3 identifier and the new value is null"() { + given: + def bundle = new Bundle() + HapiFhirHelper.createPIDPatient(bundle) + + def pid3Identifier = new Identifier() + HapiFhirHelper.setPID3Identifier(bundle, pid3Identifier) + + def pid3_4Value = "pid3_4" + HapiFhirHelper.setPID3_4Identifier(bundle, new Identifier()) + HapiHelper.setPID3_4Value(bundle, pid3_4Value) + + when: + HapiHelper.setPID3_4Value(bundle, null) + + then: + !pid3Identifier.hasAssigner() } // PID-3.5 - Assigning Identifier Type Code @@ -477,6 +506,75 @@ class HapiHelperTest extends Specification { HapiFhirHelper.getPID3_5Value(bundle) == pid3_5 } + // PID-3.5 - Removing Identifier Type Code + def "Bundle with no patient identifier does not change"() { + given: + Bundle bundle = new Bundle() + + when: + HapiHelper.removePID3_5Value(bundle) + + then: + !bundle.hasEntry() + } + + def "patientIdentifier with no extensions leaves extensions as-is"() { + given: + Bundle bundle = new Bundle() + Identifier patientIdentifier = new Identifier() + HapiFhirHelper.setPID3Identifier(bundle, patientIdentifier) + + expect: + !patientIdentifier.hasExtension() + + when: + HapiHelper.removePID3_5Value(bundle) + + then: + !patientIdentifier.hasExtension() + } + + def "removing of the patient assigning identifier clears extensions and type coding"() { + given: + def pid3_5 = "pid3_5" + def bundle = new Bundle() + def patientIdentifier = new Identifier() + + HapiFhirHelper.createPIDPatient(bundle) + HapiFhirHelper.setPID3Identifier(bundle, patientIdentifier) + HapiHelper.setPID3_5Value(bundle, pid3_5) + + patientIdentifier.type.addCoding(new Coding(code: pid3_5)) + + when: + HapiHelper.removePID3_5Value(bundle) + + then: + patientIdentifier.extension.isEmpty() + patientIdentifier.type.isEmpty() + } + + def "removing patient identifier with non-cx5 url extension does not clear extensions"() { + given: + def bundle = new Bundle() + def patientIdentifier = new Identifier() + + HapiFhirHelper.createPIDPatient(bundle) + HapiFhirHelper.setPID3Identifier(bundle, patientIdentifier) + patientIdentifier.addExtension().setUrl(HapiHelper.EXTENSION_CX_IDENTIFIER_URL) + patientIdentifier + .getExtensionByUrl(HapiHelper.EXTENSION_CX_IDENTIFIER_URL) + .addExtension() + .setUrl(HapiHelper.EXTENSION_XON10_URL) + + when: + HapiHelper.removePID3_5Value(bundle) + + then: + patientIdentifier.hasExtension() + } + + // PID-5 - Patient Name def "patient name methods work as expected"() { given: @@ -531,6 +629,45 @@ class HapiHelperTest extends Specification { HapiFhirHelper.getPID5_7Value(bundle) == null } + // PID-5.7 - Removing Name Type Code + def "bundle without patient remains empty"() { + given: + def bundle = new Bundle() + + when: + HapiHelper.removePID5_7Value(bundle) + + then: + bundle.getEntry().size() == 0 + } + + def "bundle with patient but no extensions remains empty"() { + given: + def bundle = new Bundle() + HapiFhirHelper.createPIDPatient(bundle) + + when: + HapiHelper.removePID5_7Value(bundle) + + then: + HapiHelper.getPID5Extension(bundle) == null + } + + def "bundle with patient and pid5 extensions but no xpn7 extension remains empty"() { + given: + def bundle = new Bundle() + HapiFhirHelper.createPIDPatient(bundle) + HapiFhirHelper.setPID5Extension(bundle) + + when: + HapiHelper.removePID5_7Value(bundle) + + then: + Extension pid5Extension = HapiHelper.getPID5Extension(bundle) + !pid5Extension.hasExtension() + } + + // ORC-2 - Placer Order Number def "orc-2.1 methods work as expected"() { given: @@ -703,6 +840,220 @@ class HapiHelperTest extends Specification { HapiHelper.getOBR4_1Value(sr) == null } + // OBR-16 - Ordering Provider + def "getObr16Extension returns the extension if present"() { + given: + def serviceRequest = new ServiceRequest() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + def obr16Extension = new Extension(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obrExtension.addExtension(obr16Extension) + serviceRequest.addExtension(obrExtension) + + when: + def result = HapiHelper.getObr16Extension(serviceRequest) + + then: + result == obr16Extension + } + + def "getObr16Extension returns null when no OBR extension is present"() { + given: + def serviceRequest = new ServiceRequest() + + when: + def result = HapiHelper.getObr16Extension(serviceRequest) + + then: + result == null + } + + def "getObr16Extension returns null when OBR extension does not contain OBR-16"() { + given: + def serviceRequest = new ServiceRequest() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + serviceRequest.addExtension(obrExtension) + + when: + def result = HapiHelper.getObr16Extension(serviceRequest) + + then: + result == null + } + + def "getObr16ExtensionPractitioner should return null when ServiceRequest has no OBR-16 extension"() { + given: + def serviceRequest = new ServiceRequest() + + when: + def result = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) + + then: + result == null + } + + def "getObr16ExtensionPractitioner should return null when OBR-16 extension value is null"() { + given: + def serviceRequest = new ServiceRequest() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + def obr16Extension = new Extension(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obrExtension.addExtension(obr16Extension) + serviceRequest.addExtension(obrExtension) + + when: + def result = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) + + then: + result == null + } + + def "getObr16ExtensionPractitioner should return null when OBR16 extension value is not a Reference"() { + given: + def serviceRequest = new ServiceRequest() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + def obr16Extension = new Extension(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obr16Extension.setValue(new StringType("Not a Reference")) + obrExtension.addExtension(obr16Extension) + serviceRequest.addExtension(obrExtension) + + when: + def result = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) + + then: + result == null + } + + def "getObr16ExtensionPractitioner should return null when Reference does not contain Practitioner"() { + given: + def serviceRequest = new ServiceRequest() + def reference = new Reference() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + def obr16Extension = new Extension(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obr16Extension.setValue(reference) + obrExtension.addExtension(obr16Extension) + serviceRequest.addExtension(obrExtension) + + when: + def result = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) + + then: + result == null + } + + def "getObr16ExtensionPractitioner should return Practitioner when Reference contains Practitioner"() { + given: + def serviceRequest = new ServiceRequest() + def obrExtension = new Extension(HapiHelper.EXTENSION_OBR_URL) + def obr16Extension = new Extension(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obrExtension.addExtension(obr16Extension) + serviceRequest.addExtension(obrExtension) + + def practitioner = new Practitioner() + def practitionerRole = new PractitionerRole() + practitionerRole.setPractitioner(new Reference("Practitioner/123").setResource(practitioner) as Reference) + + HapiHelper.setOBR16WithPractitioner(obrExtension, practitionerRole) + + when: + def result = HapiHelper.getObr16ExtensionPractitioner(serviceRequest) + + then: + result == practitioner + } + + // ORC-12 - Ordering Provider + def "getOrc12ExtensionPractitioner should return null when bundle has no DiagnosticReport"() { + given: + def bundle = new Bundle() + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == null + } + + def "getOrc12ExtensionPractitioner should return null when DiagnosticReport has no ServiceRequest"() { + given: + def bundle = new Bundle() + HapiFhirHelper.createDiagnosticReport(bundle) + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == null + } + + def "getOrc12ExtensionPractitioner should return null when ServiceRequest has no ORC extension"() { + given: + def bundle = new Bundle() + def diagnosticReport = HapiFhirHelper.createDiagnosticReport(bundle) + HapiFhirHelper.createBasedOnServiceRequest(diagnosticReport) + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == null + } + + def "getOrc12ExtensionPractitioner should return null when ORC extension has no ORC-12 extension"() { + given: + def bundle = new Bundle() + def diagnosticReport = HapiFhirHelper.createDiagnosticReport(bundle) + def serviceRequest = HapiFhirHelper.createBasedOnServiceRequest(diagnosticReport) + serviceRequest.addExtension(new Extension().setUrl(HapiHelper.EXTENSION_ORC_URL)) + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == null + } + + def "should return null when ORC12 extension has no Practitioner reference"() { + given: + def bundle = new Bundle() + def diagnosticReport = HapiFhirHelper.createDiagnosticReport(bundle) + def serviceRequest = HapiFhirHelper.createBasedOnServiceRequest(diagnosticReport) + + def orcExtension = new Extension().setUrl(HapiHelper.EXTENSION_ORC_URL) + def orc12Extension = new Extension().setUrl(HapiHelper.EXTENSION_ORC12_URL) + orcExtension.addExtension(orc12Extension) + serviceRequest.addExtension(orcExtension) + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == null + } + + def "should return Practitioner when all conditions are met"() { + given: + def bundle = new Bundle() + def diagnosticReport = HapiFhirHelper.createDiagnosticReport(bundle) + def serviceRequest = HapiFhirHelper.createBasedOnServiceRequest(diagnosticReport) + + def orcExtension = new Extension().setUrl(HapiHelper.EXTENSION_ORC_URL) + def orc12Extension = new Extension().setUrl(HapiHelper.EXTENSION_ORC12_URL) + + def practitioner = new Practitioner() + def practitionerId = "Practitioner/123" + def practitionerReference = new Reference().setReference(practitionerId) + + orc12Extension.setValue(practitionerReference) + orcExtension.addExtension(orc12Extension) + serviceRequest.addExtension(orcExtension) + bundle.addEntry(new Bundle.BundleEntryComponent().setFullUrl(practitionerId).setResource(practitioner)) + + when: + def result = HapiHelper.getOrc12ExtensionPractitioner(bundle) + + then: + result == practitioner + } + def "ensureExtensionExists returns extension if it exists"() { given: def serviceRequest = new ServiceRequest() @@ -863,21 +1214,19 @@ class HapiHelperTest extends Specification { def "setOBR16WithPractitioner sets the expected value on an extension"() { given: - def ext = new Extension() + Extension obrExtension = new Extension() def role = new PractitionerRole() def practitioner = new Practitioner() practitioner.setId("test123") def ref = new Reference(practitioner.getId()) role.setPractitioner(ref) - expect: - ext.getValue() == null - when: - HapiHelper.setOBR16WithPractitioner(ext, role) + HapiHelper.setOBR16WithPractitioner(obrExtension, role) then: - ext.getValue().getReference() == "test123" + def obr16Extension = obrExtension.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obr16Extension.getValue().getReference() == "test123" } def "setOBR16WithPractitioner does nothing if the provided PractitionerRole is null"() { @@ -892,7 +1241,8 @@ class HapiHelperTest extends Specification { HapiHelper.setOBR16WithPractitioner(ext, role) then: - ext.getValue() == null + def obr16Extension = ext.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString()) + obr16Extension == null } def "urlForCodeType should return expected values"() {