Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eliminate warnings for missing fields #1656

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
19227c0
WIP - remove cx.5 patient identifier warnings
jbiskie Dec 5, 2024
6d45952
Move PID-3.5 removal to HapiHelper
jbiskie Dec 5, 2024
3caa95d
Change parameter from bundle to patient indentifer
jbiskie Dec 5, 2024
f2847d8
Add tests for PID-3.5 removal
jbiskie Dec 6, 2024
cc3aa10
Move creation of OBR-16 extension into HapiHelper method, method para…
jbiskie Dec 6, 2024
fda6397
Unit Test for removal of PID-5.7
tjohnson7021 Dec 12, 2024
c8f5801
Added method for full removal of PID5.7 and name use
tjohnson7021 Dec 12, 2024
717e1e1
Remove old unit test, update input file for PID-5.7 test
jbiskie Dec 12, 2024
b6748a0
Merge branch 'main' into bug/940-eliminate-warnings-for-missing-fields
jbiskie Dec 12, 2024
8faf0f4
Improve readability and null checks in removePID3_5Value and add null…
jbiskie Dec 12, 2024
f074b67
Fix possible null value for getPIDPatient
jbiskie Dec 12, 2024
279d566
Add unit tests for removePID5_7Value Co-authored-by: jeremyir
jbiskie Dec 12, 2024
f37495e
add additional test coverage for removePID3_5Value method
Dec 13, 2024
a37b7be
Using VS Code TOC generation to generate a table of contents for the …
saquino0827 Dec 5, 2024
d9712ee
Update env template and readme for TI scripts
saquino0827 Dec 6, 2024
fb08b0b
Update setup rs script to use correct Flexion Org RS SFTP transport
saquino0827 Dec 6, 2024
982a50b
Update the README for scripts
saquino0827 Dec 9, 2024
48248c6
Updates for the scripts/README.md
saquino0827 Dec 11, 2024
4ad09d2
Update setup script to remove code duplication and update variables only
saquino0827 Dec 11, 2024
6ea8d86
Update rs scripts with some notes to attempt to fix this otherwise we…
saquino0827 Dec 11, 2024
aafe5eb
Last attempt to automate rs configuration depending on environment setup
saquino0827 Dec 12, 2024
8a85d61
Update to the script setup
saquino0827 Dec 13, 2024
28d5ee9
Use inject for non singleton class (#1617)
jorg3lopez Dec 13, 2024
5174441
Fix linting error
Dec 13, 2024
d6bbf8f
Remove obvious comments; clean up test
jbiskie Dec 13, 2024
0710b70
Refactor the clearing of patient identifier assigner into setPID3_4Va…
jbiskie Dec 16, 2024
f2c0f59
Refactor getObr16Extension to HapiHelper, add unit tests
jbiskie Dec 17, 2024
6be3152
Update Terraform azurerm to v4.14.0 (#1659)
renovate[bot] Dec 16, 2024
e626b0e
Refactor getObr16ExtensionPractitioner into HapiHelper, add unit tests
jbiskie Dec 17, 2024
cc2b9d6
Refactor getOrc12ExtensionPractitioner to HapiHelper, add unit tests
jbiskie Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,11 @@ public void transform(HealthData<?> resource, Map<String, Object> args) {
return;
}

// Extract or create the OBR-16 extension from the ServiceRequest
// Extract or create the OBR extension from the ServiceRequest
Extension obrExtension =
HapiHelper.ensureExtensionExists(serviceRequest, HapiHelper.EXTENSION_OBR_URL);

// Extract or create the OBR-16 data type extension
Extension obr16Extension =
basiliskus marked this conversation as resolved.
Show resolved Hide resolved
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import gov.hhs.cdc.trustedintermediary.wrappers.HealthData;
import java.util.Map;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Identifier;

/**
* Removes Assigning Authority (PID-3.4) and Identifier Type Code (PID-3.5) from Patient Identifier
Expand All @@ -15,7 +16,12 @@ public class RemovePatientIdentifiers implements CustomFhirTransformation {
@Override
public void transform(HealthData<?> resource, Map<String, Object> args) {
Bundle bundle = (Bundle) resource.getUnderlyingData();
HapiHelper.setPID3_4Value(bundle, ""); // remove PID.3-4
HapiHelper.setPID3_5Value(bundle, ""); // remove PID.3-5

Identifier patientIdentifier = HapiHelper.getPID3Identifier(bundle);
Copy link
Contributor

@basiliskus basiliskus Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can lines 20 to 24 be extracted to HapiHelper.setPID3_4Value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored.

if (patientIdentifier == null) {
return;
}
patientIdentifier.setAssigner(null);
HapiHelper.removePID3_5Value(patientIdentifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ public class RemovePatientNameTypeCode implements CustomFhirTransformation {
@Override
public void transform(final HealthData<?> resource, final Map<String, Object> 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just want to confirm that RS is not adding a value in PID-5.7 if we completely remove it instead of setting it to null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. We noted the same behavior as the old comments indicated initially. We also need to null patient name use so ReportStream doesn't do a secondary mapping. I went ahead and added a link in the PR description to some comments in the task.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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.Extension
import org.hl7.fhir.r4.model.Practitioner
import org.hl7.fhir.r4.model.Reference
import org.hl7.fhir.r4.model.ServiceRequest
Expand Down Expand Up @@ -214,6 +215,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
}

void evaluateObr16IsNull(ServiceRequest serviceRequest) {
assert getObr16Extension(serviceRequest) == null
assert getObr16ExtensionPractitioner(serviceRequest) == null
}

Expand All @@ -235,18 +237,18 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
assert codingSystem == null || codingSystem[0]?.code == expectedIdentifierTypeCode
}

Extension getObr16Extension(serviceRequest) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be useful to have getObr16Extension and some of the functions in this test in HapiHelper to be reused?

Copy link
Contributor Author

@jbiskie jbiskie Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the OBR-16 and ORC-12 methods into HapiHelper

def obrExtension = serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_OBR_URL)
def obr16Extension = obrExtension.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString())
return obr16Extension
}

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
def obr16Extension = getObr16Extension(serviceRequest)
if (obr16Extension == null) {
return null
}
return obr16Extension.value.getResource()
}

Practitioner getOrc12ExtensionPractitioner(Bundle bundle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,26 @@ 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 pid_5_initial = HapiHelper.getPID5Extension(bundle)
def xpn_7_initial = pid_5_initial.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL)
def patientName = HapiHelper.getPIDPatient(bundle).getNameFirstRep()
def patientNameUse = patientName.getUse()

expect:
pid5_7 != null
xpn_7_initial != null
patientNameUse.toString() == "OFFICIAL"

when:
transformClass.transform(fhirResource, null)

then:
HapiFhirHelper.getPID5_7Value(bundle) == null
def pid_5_transformed = HapiHelper.getPID5Extension(bundle)
def xpn_7_transformed = pid_5_transformed.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL)
xpn_7_transformed == null

!patientName.hasUse()
}

def "don't throw exception if patient resource not present"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ public static Identifier getPID3_4Identifier(Bundle bundle) {
return null;
}
Organization organization = (Organization) identifier.getAssigner().getResource();
if (organization == null) {
return null;
}
return organization.getIdentifierFirstRep();
}

Expand All @@ -288,6 +291,29 @@ public static void setPID3_5Value(Bundle bundle, String value) {
setCX5Value(identifier, value);
}

public static void removePID3_5Value(Identifier patientIdentifier) {
if (patientIdentifier == null) {
return;
}

patientIdentifier.setType(null);

Extension cxExtension =
patientIdentifier.getExtensionByUrl(HapiHelper.EXTENSION_CX_IDENTIFIER_URL);
if (cxExtension == null) {
return;
}

if (cxExtension.hasExtension(HapiHelper.EXTENSION_CX5_URL)) {
cxExtension.removeExtension(HapiHelper.EXTENSION_CX5_URL);
}

// The cx-identifier extension can be removed if it has no more sub-extensions
if (cxExtension.getExtension().isEmpty()) {
patientIdentifier.removeExtension(HapiHelper.EXTENSION_CX_IDENTIFIER_URL);
}
}

// PID-5 - Patient Name
public static Extension getPID5Extension(Bundle bundle) {
Patient patient = getPIDPatient(bundle);
Expand All @@ -307,6 +333,24 @@ public static void setPID5_7ExtensionValue(Bundle bundle, String value) {
}
}

public static void removePID5_7Value(Bundle bundle) {
Patient patient = HapiHelper.getPIDPatient(bundle);
if (patient == null) {
return;
}
HumanName patientName = patient.getNameFirstRep();
patientName.setUse(null);

Extension pid5Extension = HapiHelper.getPID5Extension(bundle);
if (pid5Extension == null) {
return;
}
Extension xpn7Extension = pid5Extension.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL);
if (xpn7Extension != null) {
pid5Extension.removeExtension(HapiHelper.EXTENSION_XPN7_URL);
}
}

// ORC - Common Order

// Diagnostic Report
Expand Down Expand Up @@ -500,13 +544,16 @@ public static String getOBR4_1Value(ServiceRequest serviceRequest) {
}

// OBR16 - Ordering Provider

// OBR16 -
public static void setOBR16WithPractitioner(
Extension obr16Extension, PractitionerRole practitionerRole) {
if (practitionerRole == null) {
Extension obrExtension, PractitionerRole practitionerRole) {
if (practitionerRole == null || !practitionerRole.getPractitioner().hasReference()) {
return;
}

Extension obr16Extension =
HapiHelper.ensureSubExtensionExists(
obrExtension, HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString());

obr16Extension.setValue(practitionerRole.getPractitioner());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,52 @@ class HapiHelperTest extends Specification {
HapiFhirHelper.getPID3_5Value(bundle) == pid3_5
}

// PID-3.5 - Removing Identifier Type Code
def "null patientIdentifier remains null"() {
given:
Identifier patientIdentifier = null

when:
HapiHelper.removePID3_5Value(patientIdentifier)

then:
patientIdentifier == null
}

def "patientIdentifier with no extensions leaves extensions as-is"() {
given:
Identifier patientIdentifier = new Identifier()

expect:
!patientIdentifier.hasExtension()

when:
HapiHelper.removePID3_5Value(patientIdentifier)

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(patientIdentifier)

then:
patientIdentifier.extension.isEmpty()
patientIdentifier.type.isEmpty()
}

// PID-5 - Patient Name
def "patient name methods work as expected"() {
given:
Expand Down Expand Up @@ -531,6 +577,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:
Expand Down Expand Up @@ -863,21 +948,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"() {
Expand All @@ -892,7 +975,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"() {
Expand Down
Loading