From e5d7a5a9a2ff64b00c67c88669d32223b9febccf Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Tue, 3 Dec 2024 14:49:37 -0500 Subject: [PATCH 01/17] [16143] Checking in WIP. --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 61 ++++++++-- .../fhirengine/utils/FHIRBundleHelpers.kt | 21 ++++ .../common/UniversalPipelineTestUtils.kt | 13 +++ .../azure/FHIRConverterIntegrationTests.kt | 14 +-- .../fhirengine/engine/FhirConverterTests.kt | 108 ++++++++++++++++++ .../utils/FHIRBundleHelpersTests.kt | 67 +++++++++++ 6 files changed, 265 insertions(+), 19 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index e5cd8908412..134ceca7e29 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -44,6 +44,7 @@ import gov.cdc.prime.router.azure.observability.event.AzureEventServiceImpl import gov.cdc.prime.router.azure.observability.event.IReportStreamEventService import gov.cdc.prime.router.azure.observability.event.ReportStreamEventName import gov.cdc.prime.router.azure.observability.event.ReportStreamEventProperties +import gov.cdc.prime.router.common.BaseEngine import gov.cdc.prime.router.fhirengine.translation.HL7toFhirTranslator import gov.cdc.prime.router.fhirengine.translation.hl7.FhirTransformer import gov.cdc.prime.router.fhirengine.translation.hl7.utils.CustomContext @@ -52,6 +53,7 @@ import gov.cdc.prime.router.fhirengine.utils.FhirTranscoder import gov.cdc.prime.router.fhirengine.utils.HL7Reader import gov.cdc.prime.router.fhirengine.utils.HL7Reader.Companion.parseHL7Message import gov.cdc.prime.router.fhirengine.utils.getObservations +import gov.cdc.prime.router.fhirengine.utils.isElr import gov.cdc.prime.router.logging.LogMeasuredTime import gov.cdc.prime.router.report.ReportService import gov.cdc.prime.router.validation.IItemValidator @@ -508,21 +510,56 @@ class FHIRConverter( } // 'stamp' observations with their condition code if (item.bundle != null) { + val isElr = item.bundle!!.isElr() item.bundle!!.getObservations().forEach { observation -> - val result = stamper.stampObservation(observation) - if (!result.success) { - val logger = actionLogger.getItemLogger(item.index + 1, observation.id) - if (result.failures.isEmpty()) { - logger.warn(UnmappableConditionMessage()) - } else { - logger.warn( - result.failures.map { - UnmappableConditionMessage( - it.failures.map { it.code }, - it.source + // Only do this if it is an ELR item. + if (isElr) { + val result = stamper.stampObservation(observation) + if (!result.success) { + val logger = actionLogger.getItemLogger(item.index + 1, observation.id) + if (result.failures.isEmpty()) { + logger.warn(UnmappableConditionMessage()) + } else { + logger.warn( + result.failures.map { + UnmappableConditionMessage( + it.failures.map { it.code }, + it.source + ) + } ) } - ) +// } else { +// // TODO Generate an ITEM_TRANSFORMED Azure Event. +// val bundleDigestExtractor = BundleDigestExtractor( +// FhirPathBundleDigestLabResultExtractorStrategy( +// CustomContext( +// item.bundle!!, +// item.bundle!!, +// mutableMapOf(), +// CustomFhirPathFunctions() +// ) +// ) +// ) +// reportEventService.sendItemEvent( +// eventName = ReportStreamEventName.ITEM_TRANSFORMED, +// childReport = report, +// pipelineStepName = TaskAction.convert +// ) { +// parentReportId(message.reportId) +// params( +// mapOf( +// ReportStreamEventProperties.RECEIVER_NAME to receiver.fullName, +// ReportStreamEventProperties.BUNDLE_DIGEST +// to bundleDigestExtractor.generateDigest(item.bundle!!), +// ReportStreamEventProperties.ORIGINAL_FORMAT to format.name, +// ReportStreamEventProperties.TARGET_FORMAT to MimeFormat.FHIR.name, +// ReportStreamEventProperties.ENRICHMENTS to +// listOf(receiver.translation.schemaName) +// ) +// ) +// trackingId(item.bundle!!) +// } } } } diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index 564d0d5e0e7..3835c5d5eb9 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -20,6 +20,7 @@ import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.DateTimeType import org.hl7.fhir.r4.model.DiagnosticReport import org.hl7.fhir.r4.model.Extension +import org.hl7.fhir.r4.model.MessageHeader import org.hl7.fhir.r4.model.Observation import org.hl7.fhir.r4.model.Patient import org.hl7.fhir.r4.model.Property @@ -116,6 +117,26 @@ fun Bundle.addProvenanceReference() { } } +/** + * Return true if Bundle contains an ELR in the MessageHeader. + * + * @return true if the MesssageHeader contains an R01, otherwise false. + */ +fun Bundle.isElr(): Boolean { + var isElr = false + if (this.type == Bundle.BundleType.MESSAGE && this.entry.isNotEmpty()) { + // By rule, the first entry must be a MessageHeader + val resource = this.entry[0].resource + if (resource is MessageHeader) { + val event = resource.event + if (event is Coding && event.code == "R01") { + isElr = true + } + } + } + return isElr +} + /** * Gets all properties for a [Base] resource recursively and filters only its references * diff --git a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt index 9a3aaf1c8b8..7380c6a2974 100644 --- a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt +++ b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt @@ -43,14 +43,27 @@ const val validFHIRRecord1 = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" const val validFHIRRecord1Identifier = "1234d1d1-95fe-462c-8ac6-46728dba581c" +@Suppress("ktlint:standard:max-line-length") +const val validFHIRRecord1a = + """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" +const val validFHIRRecord1aIdentifier = "1234d1d1-95fe-462c-8ac6-46728dba581c" + @Suppress("ktlint:standard:max-line-length") const val conditionCodedValidFHIRRecord1 = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/condition-code","valueCoding":{"system":"SNOMEDCT","code":"6142004","display":"Influenza (disorder)"}}],"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" +@Suppress("ktlint:standard:max-line-length") +const val conditionCodedValidFHIRRecord1a = + """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/condition-code","valueCoding":{"system":"SNOMEDCT","code":"6142004","display":"Influenza (disorder)"}}],"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" + @Suppress("ktlint:standard:max-line-length") const val validFHIRRecord2 = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c09876","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dbau8cd"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"41458-1"}],"text":"SARS "},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" +@Suppress("ktlint:standard:max-line-length") +const val validFHIRRecord2a = + """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c09876","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dbau8cd"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"41458-1"}],"text":"SARS "},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" + const val invalidEmptyFHIRRecord = "{}" const val invalidMalformedFHIRRecord = """{"resourceType":"Bund}""" diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt index e95fb3d5806..da04315bf38 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt @@ -53,7 +53,7 @@ import gov.cdc.prime.router.common.badEncodingHL7Record import gov.cdc.prime.router.common.cleanHL7Record import gov.cdc.prime.router.common.cleanHL7RecordConverted import gov.cdc.prime.router.common.cleanHL7RecordConvertedAndTransformed -import gov.cdc.prime.router.common.conditionCodedValidFHIRRecord1 +import gov.cdc.prime.router.common.conditionCodedValidFHIRRecord1a import gov.cdc.prime.router.common.garbledHL7Record import gov.cdc.prime.router.common.invalidEmptyFHIRRecord import gov.cdc.prime.router.common.invalidHL7Record @@ -62,8 +62,8 @@ import gov.cdc.prime.router.common.invalidHL7RecordConvertedAndTransformed import gov.cdc.prime.router.common.invalidMalformedFHIRRecord import gov.cdc.prime.router.common.invalidRadxMarsHL7Message import gov.cdc.prime.router.common.unparseableHL7Record -import gov.cdc.prime.router.common.validFHIRRecord1 -import gov.cdc.prime.router.common.validFHIRRecord2 +import gov.cdc.prime.router.common.validFHIRRecord1a +import gov.cdc.prime.router.common.validFHIRRecord2a import gov.cdc.prime.router.common.validRadxMarsHL7Message import gov.cdc.prime.router.common.validRadxMarsHL7MessageConverted import gov.cdc.prime.router.db.ReportStreamTestDatabaseContainer @@ -690,9 +690,9 @@ class FHIRConverterIntegrationTests { val receivedReportContents = listOf( - validFHIRRecord1, + validFHIRRecord1a, invalidEmptyFHIRRecord, - validFHIRRecord2, + validFHIRRecord2a, invalidMalformedFHIRRecord ).joinToString( "\n" @@ -748,7 +748,7 @@ class FHIRConverterIntegrationTests { } .map { Pair(it.first, it.second.toString(Charset.defaultCharset())) } assertThat(reportAndBundles).transform { pairs -> pairs.map { it.second } } - .containsOnly(conditionCodedValidFHIRRecord1, validFHIRRecord2) + .containsOnly(conditionCodedValidFHIRRecord1a, validFHIRRecord2a) val expectedQueueMessages = reportAndBundles.map { (report, fhirBundle) -> FhirDestinationFilterQueueMessage( report.reportId, @@ -835,7 +835,7 @@ class FHIRConverterIntegrationTests { patientState = emptyList(), orderingFacilityState = emptyList(), performerState = emptyList(), - eventType = "" + eventType = "ORU^R01^ORU_R01" ) ) ) diff --git a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt index 33731c0e5af..be85a4e54e0 100644 --- a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt @@ -344,6 +344,106 @@ class FhirConverterTests { @Test fun `test condition code stamping`() { + @Suppress("ktlint:standard:max-line-length") + val fhirRecord = + """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl" : "MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource" : {"resourceType" : "MessageHeader","id" : "0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension" : [ {"url" : "https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString" : "^~\\&#"}, {"url" : "https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString" : "UNICODE UTF-8"}, {"url" : "https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension" : [ {"url" : "MSH.7","valueString" : "20230501102531-0400"} ]} ],"eventCoding" : {"system" : "http://terminology.hl7.org/CodeSystem/v2-0003","code" : "R01","display" : "ORU^R01^ORU_R01"},"sender" : {"reference" : "Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" + + val conditionCodeExtensionURL = "https://reportstream.cdc.gov/fhir/StructureDefinition/condition-code" + mockkObject(BlobAccess) + mockkObject(Report) + metadata.lookupTableStore += mapOf( + "observation-mapping" to LookupTable( + "observation-mapping", + listOf( + listOf( + ObservationMappingConstants.TEST_CODE_KEY, + ObservationMappingConstants.CONDITION_CODE_KEY, + ObservationMappingConstants.CONDITION_CODE_SYSTEM_KEY, + ObservationMappingConstants.CONDITION_NAME_KEY + ), + listOf( + "80382-5", + "6142004", + "SNOMEDCT", + "Influenza (disorder)" + ), + listOf( + "260373001", + "Some Condition Code", + "Condition Code System", + "Condition Name" + ) + ) + ) + ) + + // set up + val actionHistory = mockk() + val actionLogger = mockk() + val transformer = mockk() + + val engine = spyk(makeFhirEngine(metadata, settings, TaskAction.process) as FHIRConverter) + val message = spyk( + FhirConvertQueueMessage( + UUID.randomUUID(), + BLOB_FHIR_URL, + "test", + BLOB_SUB_FOLDER_NAME, + Topic.FULL_ELR, + SCHEMA_NAME + ) + ) + + val bodyFormat = MimeFormat.FHIR + val bodyUrl = "https://anyblob.com" + + every { actionLogger.hasErrors() } returns false + every { actionLogger.getItemLogger(any(), any()) } returns actionLogger + every { actionLogger.warn(any>()) } just runs + every { actionLogger.setReportId(any()) } returns actionLogger + every { BlobAccess.downloadBlob(any(), any()) } returns (fhirRecord) + every { Report.getFormatFromBlobURL(message.blobURL) } returns MimeFormat.FHIR + every { BlobAccess.Companion.uploadBlob(any(), any()) } returns "test" + every { accessSpy.insertTask(any(), bodyFormat.toString(), bodyUrl, any()) }.returns(Unit) + every { actionHistory.trackCreatedReport(any(), any(), blobInfo = any()) }.returns(Unit) + every { actionHistory.trackExistingInputReport(any()) }.returns(Unit) + val action = Action() + action.actionName = TaskAction.convert + every { actionHistory.action } returns action + every { engine.getTransformerFromSchema(SCHEMA_NAME) }.returns(transformer) + every { transformer.process(any()) } returnsArgument (0) + + // act + accessSpy.transact { txn -> + engine.run(message, actionLogger, actionHistory, txn) + } + + val bundle = FhirContext.forR4().newJsonParser().parseResource(Bundle::class.java, fhirRecord) + bundle.entry.filter { it.resource is Observation }.forEach { + val observation = (it.resource as Observation) + observation.code.coding[0].addExtension( + conditionCodeExtensionURL, + Coding("SNOMEDCT", "6142004", "Influenza (disorder)") + ) + observation.valueCodeableConcept.coding[0].addExtension( + conditionCodeExtensionURL, + Coding("Condition Code System", "Some Condition Code", "Condition Name") + ) + } + + // assert + verify(exactly = 1) { + // TODO clean up assertions + // engine.getContentFromFHIR(any(), any()) + actionHistory.trackExistingInputReport(any()) + transformer.process(any()) + actionHistory.trackCreatedReport(any(), any(), blobInfo = any()) + BlobAccess.Companion.uploadBlob(any(), FhirTranscoder.encode(bundle).toByteArray(), any()) + } + } + + @Test + fun `test condition code stamping without message header`() { @Suppress("ktlint:standard:max-line-length") val fhirRecord = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" @@ -438,6 +538,8 @@ class FhirConverterTests { actionHistory.trackExistingInputReport(any()) transformer.process(any()) actionHistory.trackCreatedReport(any(), any(), blobInfo = any()) + } + verify(exactly = 0) { BlobAccess.Companion.uploadBlob(any(), FhirTranscoder.encode(bundle).toByteArray(), any()) } } @@ -544,6 +646,12 @@ class FhirConverterTests { } } +// @Test +// fun `test isElr when bundle is empty`() { +// val emptyBundle = Bundle() +// assertThat(BaseEngine.Companion.isElr(emptyBundle)).isFalse() +// } + @Nested inner class FhirConverterProcessTest { diff --git a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt index a9d4a282cf6..1b5968845ba 100644 --- a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt @@ -45,6 +45,7 @@ import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.DiagnosticReport import org.hl7.fhir.r4.model.Endpoint import org.hl7.fhir.r4.model.Extension +import org.hl7.fhir.r4.model.MessageHeader import org.hl7.fhir.r4.model.Observation import org.hl7.fhir.r4.model.Patient import org.hl7.fhir.r4.model.PractitionerRole @@ -195,6 +196,72 @@ class FHIRBundleHelpersTests { assertThat(diagnosticReport.getResourceProperties()).isNotEmpty() } + @Test + fun `Test if ELR when bundle is empty`() { + val fhirBundle = Bundle() + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle is not BundleType MESSAGE`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.DOCUMENT + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle has no entries`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.MESSAGE + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle has no MessageHeader`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.MESSAGE + val entry = Bundle.BundleEntryComponent() + fhirBundle.entry.add(0, entry) + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle has MessageHeader but no Coding event`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.MESSAGE + val entry = Bundle.BundleEntryComponent() + entry.resource = MessageHeader() + fhirBundle.entry.add(0, entry) + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle has MessageHeader but Coding event not R01`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.MESSAGE + val entry = Bundle.BundleEntryComponent() + val messageHeader = MessageHeader() + val event = Coding() + messageHeader.event = event + entry.resource = messageHeader + fhirBundle.entry.add(0, entry) + assertThat(fhirBundle.isElr()).isFalse() + } + + @Test + fun `Test if ELR when bundle is happy path`() { + val fhirBundle = Bundle() + fhirBundle.type = Bundle.BundleType.MESSAGE + val entry = Bundle.BundleEntryComponent() + val messageHeader = MessageHeader() + val event = Coding() + event.code = "R01" + messageHeader.event = event + entry.resource = messageHeader + fhirBundle.entry.add(0, entry) + assertThat(fhirBundle.isElr()).isTrue() + } + @Test fun `Test find Diagnostic report no observation`() { val actionLogger = ActionLogger() From 2891d0c9fe854c6d89dd993333c115f4dfd38d07 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Wed, 4 Dec 2024 09:20:50 -0500 Subject: [PATCH 02/17] [16143] Checking in WIP. --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 82 ++++++++++--------- .../fhirengine/engine/FhirConverterTests.kt | 46 ++++++----- 2 files changed, 69 insertions(+), 59 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index 134ceca7e29..6b950a7d49c 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -260,7 +260,7 @@ class FHIRConverter( // TODO: https://github.com/CDCgov/prime-reportstream/issues/14287 FhirPathUtils - val processedItems = process(format, input.blobURL, input.blobDigest, input.topic, actionLogger) + val processedItems = process(format, input, actionLogger) // processedItems can be empty in three scenarios: // - the blob had no contents, i.e. an empty file was submitted @@ -452,14 +452,12 @@ class FHIRConverter( */ internal fun process( format: MimeFormat, - blobURL: String, - blobDigest: String, - topic: Topic, + input: FHIRConvertInput, actionLogger: ActionLogger, routeReportWithInvalidItems: Boolean = true, ): List> { - val validator = topic.validator - val rawReport = BlobAccess.downloadBlob(blobURL, blobDigest) + val validator = input.topic.validator + val rawReport = BlobAccess.downloadBlob(input.blobURL, input.blobDigest) return if (rawReport.isBlank()) { actionLogger.error(InvalidReportMessage("Provided raw data is empty.")) emptyList() @@ -473,7 +471,7 @@ class FHIRConverter( "format" to format.name ) ) { - getBundlesFromRawHL7(rawReport, validator, topic.hl7ParseConfiguration) + getBundlesFromRawHL7(rawReport, validator, input.topic.hl7ParseConfiguration) } } catch (ex: ParseFailureError) { actionLogger.error( @@ -529,37 +527,45 @@ class FHIRConverter( } ) } -// } else { -// // TODO Generate an ITEM_TRANSFORMED Azure Event. -// val bundleDigestExtractor = BundleDigestExtractor( -// FhirPathBundleDigestLabResultExtractorStrategy( -// CustomContext( -// item.bundle!!, -// item.bundle!!, -// mutableMapOf(), -// CustomFhirPathFunctions() -// ) -// ) -// ) -// reportEventService.sendItemEvent( -// eventName = ReportStreamEventName.ITEM_TRANSFORMED, -// childReport = report, -// pipelineStepName = TaskAction.convert -// ) { -// parentReportId(message.reportId) -// params( -// mapOf( -// ReportStreamEventProperties.RECEIVER_NAME to receiver.fullName, -// ReportStreamEventProperties.BUNDLE_DIGEST -// to bundleDigestExtractor.generateDigest(item.bundle!!), -// ReportStreamEventProperties.ORIGINAL_FORMAT to format.name, -// ReportStreamEventProperties.TARGET_FORMAT to MimeFormat.FHIR.name, -// ReportStreamEventProperties.ENRICHMENTS to -// listOf(receiver.translation.schemaName) -// ) -// ) -// trackingId(item.bundle!!) -// } + } else { + // TODO Generate an ITEM_TRANSFORMED Azure Event. + val bundleDigestExtractor = BundleDigestExtractor( + FhirPathBundleDigestLabResultExtractorStrategy( + CustomContext( + item.bundle!!, + item.bundle!!, + mutableMapOf(), + CustomFhirPathFunctions() + ) + ) + ) + val report = Report( + MimeFormat.FHIR, + emptyList(), + parentItemLineageData = listOf( + Report.ParentItemLineageData(input.reportId, item.index.toInt() + 1) + ), + metadata = this.metadata, + topic = input.topic, + nextAction = TaskAction.none + ) + reportEventService.sendItemEvent( + eventName = ReportStreamEventName.ITEM_TRANSFORMED, + childReport = report, + pipelineStepName = TaskAction.convert + ) { + parentReportId(input.reportId) + params( + mapOf( + ReportStreamEventProperties.BUNDLE_DIGEST + to bundleDigestExtractor.generateDigest(item.bundle!!), + ReportStreamEventProperties.ORIGINAL_FORMAT to format.name, + ReportStreamEventProperties.TARGET_FORMAT to MimeFormat.FHIR.name, + ReportStreamEventProperties.ENRICHMENTS to listOf(input.schemaName) + ) + ) + trackingId(item.bundle!!) + } } } } diff --git a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt index be85a4e54e0..96015341e88 100644 --- a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt @@ -668,12 +668,11 @@ class FhirConverterTests { @Test fun `should log an error and return no bundles if the message is empty`() { mockkObject(BlobAccess) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") val engine = spyk(makeFhirEngine(metadata, settings, TaskAction.process) as FHIRConverter) val actionLogger = ActionLogger() every { BlobAccess.downloadBlob(any(), any()) } returns "" - val bundles = engine.process( - MimeFormat.FHIR, "", "", Topic.FULL_ELR, actionLogger - ) + val bundles = engine.process(MimeFormat.FHIR, input, actionLogger) assertThat(bundles).isEmpty() assertThat(actionLogger.errors.map { it.detail.message }).contains("Provided raw data is empty.") } @@ -695,9 +694,8 @@ class FhirConverterTests { every { mockMessage.topic } returns Topic.FULL_ELR every { mockMessage.reportId } returns UUID.randomUUID() every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 - val bundles = engine.process( - MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger - ) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val bundles = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(bundles).isEmpty() assertThat( actionLogger.errors.map { @@ -712,9 +710,8 @@ class FhirConverterTests { val engine = spyk(makeFhirEngine(metadata, settings, TaskAction.process) as FHIRConverter) val actionLogger = ActionLogger() every { BlobAccess.downloadBlob(any(), any()) } returns "test,1,2" - val bundles = engine.process( - MimeFormat.CSV, "", "", Topic.FULL_ELR, actionLogger - ) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val bundles = engine.process(MimeFormat.CSV, input, actionLogger) assertThat(bundles).isEmpty() assertThat(actionLogger.errors.map { it.detail.message }) .contains("Received unsupported report format: CSV") @@ -726,7 +723,8 @@ class FhirConverterTests { val engine = spyk(makeFhirEngine(metadata, settings, TaskAction.process) as FHIRConverter) val actionLogger = ActionLogger() every { BlobAccess.downloadBlob(any(), any()) } returns "{\"id\":}" - val processedItems = engine.process(MimeFormat.FHIR, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.FHIR, input, actionLogger) assertThat(processedItems).hasSize(1) assertThat(processedItems.first().bundle).isNull() assertThat(actionLogger.errors.map { it.detail.message }).contains( @@ -756,9 +754,8 @@ class FhirConverterTests { every { mockMessage.topic } returns Topic.FULL_ELR every { mockMessage.reportId } returns UUID.randomUUID() every { BlobAccess.downloadBlob(any(), any()) } returns "{\"id\":\"1\", \"resourceType\":\"Bundle\"}" - val processedItems = engine.process( - MimeFormat.FHIR, "", "", Topic.FULL_ELR, actionLogger - ) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.FHIR, input, actionLogger) assertThat(processedItems).hasSize(1) assertThat(processedItems.first().bundle).isNull() assertThat(actionLogger.errors.map { it.detail.message }).contains( @@ -777,7 +774,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns unparseableHL7 - val processedItems = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(processedItems).hasSize(1) assertThat(processedItems.first().bundle).isNull() assertThat( @@ -812,7 +810,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 - val processedItems = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(processedItems).hasSize(1) assertThat(processedItems.first().bundle).isNull() @Suppress("ktlint:standard:max-line-length") @@ -841,7 +840,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 - val processedItems = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(processedItems).hasSize(1) assertThat(processedItems.first().bundle).isNull() assertThat( @@ -867,14 +867,15 @@ class FhirConverterTests { } returns """{\"id\":} {"id":"1", "resourceType":"Bundle"} """.trimMargin() - val processedItems = engine.process(MimeFormat.FHIR, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val processedItems = engine.process(MimeFormat.FHIR, input, actionLogger) assertThat(processedItems).hasSize(2) assertThat(actionLogger.errors.map { it.detail.message }).contains( @Suppress("ktlint:standard:max-line-length") "Item 1 in the report was not parseable. Reason: exception while parsing FHIR: HAPI-1861: Failed to parse JSON encoded FHIR content: Unexpected character ('\\' (code 92)): was expecting double-quote to start field name\n at [line: 1, column: 2]" ) - val bundles2 = engine.process(MimeFormat.FHIR, "", "", Topic.FULL_ELR, actionLogger, false) + val bundles2 = engine.process(MimeFormat.FHIR, input, actionLogger, false) assertThat(bundles2).hasSize(0) assertThat(actionLogger.errors.map { it.detail.message }).contains( @Suppress("ktlint:standard:max-line-length") @@ -894,7 +895,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 - val bundles = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val bundles = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(bundles).hasSize(1) assertThat(actionLogger.errors).isEmpty() } @@ -914,7 +916,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 + "\n" + simpleHL7 + "\n" + simpleHL7 - val bundles = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val bundles = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(bundles).hasSize(3) assertThat(actionLogger.errors).isEmpty() @@ -945,7 +948,8 @@ class FhirConverterTests { every { BlobAccess.downloadBlob(any(), any()) } returns simpleHL7 - val bundles = engine.process(MimeFormat.HL7, "", "", Topic.FULL_ELR, actionLogger) + val input = FHIRConverter.FHIRConvertInput(UUID.randomUUID(), Topic.FULL_ELR, "", "", "", "") + val bundles = engine.process(MimeFormat.HL7, input, actionLogger) assertThat(bundles).hasSize(1) assertThat(actionLogger.errors).isEmpty() } From 12aaeb2a76c6883b914b923f5d4eba4891ef60a5 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Wed, 4 Dec 2024 13:45:37 -0500 Subject: [PATCH 03/17] [16143] Added new code to check for ELR.. --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 2 +- .../fhirengine/utils/FHIRBundleHelpers.kt | 4 +- .../utils/FHIRBundleHelpersTests.kt | 6 +- prime-router/tmp.txt | 1013 +++++++++++++++++ 4 files changed, 1021 insertions(+), 4 deletions(-) create mode 100644 prime-router/tmp.txt diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index 6b950a7d49c..b4f79187ee1 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -528,7 +528,7 @@ class FHIRConverter( ) } } else { - // TODO Generate an ITEM_TRANSFORMED Azure Event. + // Generate an ITEM_TRANSFORMED Azure Event. val bundleDigestExtractor = BundleDigestExtractor( FhirPathBundleDigestLabResultExtractorStrategy( CustomContext( diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index 3835c5d5eb9..0d9f71c49c6 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -120,7 +120,7 @@ fun Bundle.addProvenanceReference() { /** * Return true if Bundle contains an ELR in the MessageHeader. * - * @return true if the MesssageHeader contains an R01, otherwise false. + * @return true if has a MesssageHeader that contains an R01 or ORU_R01, otherwise false. */ fun Bundle.isElr(): Boolean { var isElr = false @@ -129,7 +129,7 @@ fun Bundle.isElr(): Boolean { val resource = this.entry[0].resource if (resource is MessageHeader) { val event = resource.event - if (event is Coding && event.code == "R01") { + if (event is Coding && ((event.code == "R01") || (event.code == "ORU_R01"))) { isElr = true } } diff --git a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt index 1b5968845ba..c22b45fc312 100644 --- a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt @@ -254,12 +254,16 @@ class FHIRBundleHelpersTests { fhirBundle.type = Bundle.BundleType.MESSAGE val entry = Bundle.BundleEntryComponent() val messageHeader = MessageHeader() - val event = Coding() + var event = Coding() event.code = "R01" messageHeader.event = event entry.resource = messageHeader fhirBundle.entry.add(0, entry) assertThat(fhirBundle.isElr()).isTrue() + event.code = "ORU_R01" + assertThat(fhirBundle.isElr()).isTrue() + event.code = "R21" + assertThat(fhirBundle.isElr()).isFalse() } @Test diff --git a/prime-router/tmp.txt b/prime-router/tmp.txt new file mode 100644 index 00000000000..13c28a4cb34 --- /dev/null +++ b/prime-router/tmp.txt @@ -0,0 +1,1013 @@ + 1 cd prime-router + 2 ./cleanslate.sh --verbose + 3 docker ps + 4 ./gradlew tasks + 5 gradle tasks + 6 docker compose down + 7 docker ps + 8 docker compose down + 9 docker-compose down + 10 docker-compose down d698f0920a37 + 11 docker-compose down prime-router-postgresql-1 + 12 docker-compose down prime-router-postgresql + 13 docker ps + 14 ./gradlew tasks + 15 ls + 16 ls prime + 17 gradle tasks + 18 docker ps + 19 git fetch -p + 20 git status + 21 git fetch -p + 22 cd .. + 23 grep -ir azurite * + 24 grep -ir azurite * | grep -v build | grep -v test + 25 find . -name "*.sh" + 26 cd prime-router + 27 less cleanslate.sh + 28 less docker-compose.yml + 29 grep -ir azurite * | grep -v '(build|test)' + 30 grep -ir azurite * | grep -v (build|test) + 31 grep -ir azurite * | grep -v build|test + 32 grep -ir azurite * | grep -v 'build|test' + 33 grep -ir azurite * | grep -v "build|test" + 34 grep -ir azurite * | grep -v "build\|test" + 35 ls + 36 ls -al + 37 less devenv-infrastructure.sh + 38 less docker-compose.yml + 39 ls + 40 ls .. + 41 less docker-compose.yml + 42 find . -name "Docker*" + 43 cd .. + 44 find . -name "Docker*" + 45 less ./.environment/docker/docker-compose/Dockerfile.azurite + 46 less ./.environment/docker/docker-compose/Dockerfile.azurite + 47 less docker-compose.yml + 48 cd prime-router + 49 less docker-compose.yml + 50 cd .. + 51 git branch + 52 git checkout main + 53 git fetch -p + 54 git pull + 55 cd .. + 56 history 1 | grep clone + 57 ls + 58 rm -rf prime-reportstream + 59 git clone https://github.com/CDCgov/prime-reportstream.git + 60 git checkout main + 61 cd prime-reportstream + 62 git checkout main + 63 git fetch -p + 64 ls + 65 cd prime-router + 66 git fetch -p + 67 cd .. + 68 git fetch -p + 69 cd prime-router + 70 ./cleanslate.sh --verbose + 71 docker ps + 72 ls + 73 gradle tasks + 74 cat /Users/bill/projects/report-stream/prime-reportstream/prime-router/.vault/env/.env.local + 75 docker compose -f docker-compose.build.yml up --detach + 76 docker ps + 77 docker compose up --detach vault 1>/dev/null 2>/dev/null + 78 docker ps + 79 ls + 80 gradle primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" + 81 gradle reloadTables + 82 docker ps + 83 gradle reloadTables + 84 docker ps + 85 gradle reloadTables + 86 grep -r 7071 * | grep -v 'test\|build' + 87 docker ps + 88 gradle run + 89 ../gradlew run + 90 docker ps + 91 ../gradlew reloadTables + 92 ../gradlew quickRun + 93 docker ps + 94 ../gradlew reloadTables + 95 ../gradlew run + 96 ../gradlew tasks + 97 ../gradlew clean build + 98 docker ps + 99 ../gradlew clean build -x test + 100 ../gradlew run -x test + 101 ls ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions + 102 ls ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions/prime-data-hub-router + 103 ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions/prime-data-hub-router + 104 ../gradlew reloadSettings + 105 docker ps + 106 ../gradlew quickRun + 107 docker ps + 108 ../gradlew composeDown + 109 ../gradlew composeDownForced + 110 docker ps + 111 docker ps + 112 docker ps + 113 ../gradlew run + 114 ls + 115 docker compose -f docker-compose.build.yml up --detach + 116 docker ps + 117 ../gradlew run + 118 docker ps + 119 ../gradlew quickRun + 120 ../gradlew run + 121 ../gradlew run --debug + 122 echo $JAVA_HOME + 123 java -version + 124 env + 125 cat ~/.zshrc + 126 export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH" + 127 export JAVA_HOME=$(/usr/libexec/java_home) + 128 env + 129 ../gradlew run --debug + 130 docker ps + 131 docker ps + 132 grep -r 5432 * + 133 grep -r 5432 * | grep -v 'build|test' + 134 grep -r 5432 * | grep -v "build\|test" + 135 docker ps + 136 ../gradlew composeDown + 137 docker ps + 138 ../gradlew composeDownForced + 139 exit + 140 cd + 141 ls -al + 142 less .gitconfig + 143 cat .stCommitMsg + 144 cat .gitconfig + 145 gpg --version + 146 gpg2 --version + 147 exit + 148 gpg2 --version + 149 gpg2 --full-generate-key + 150 ls -al + 151 ls .gnupg + 152 vi .gitconfig + 153 ls .gnupg + 154 vi .gitconfig + 155 gpg2 --armor --export real.name@organization.tld + 156 gpg2 --armor --export billcutshall@navapbc.com.tld + 157 gpg2 --armor --export Bill.Cutshall@navapbc.com.tld + 158 gpg2 --armor --export billcutshall@navapbc.com + 159 exit + 160 docker ps + 161 cd .. + 162 ./prime --help + 163 ls + 164 cd prime-router + 165 ls + 166 ./prime --help + 167 cat prime + 168 ../gradlew reloadTables + 169 ../gradlew reloadSettings + 170 curl --help + 171 curl http://localhost:7071/api/health + 172 curl -vvv http://localhost:7071/api/health + 173 ps + 174 netstat -vanp + 175 netstat -an + 176 lsof -i + 177 lsof -i tcp:7071 + 178 top + 179 docker ps + 180 lsof -i tcp:3000 + 181 ps aux + 182 ps aux | grep 7071 + 183 ps aux | grep 1113 + 184 curl -vvv http://localhost:7071/api/health + 185 curl -vvv http://localhost:7071/health + 186 curl -vvv http://localhost:7071/api/reports + 187 curl -vvv http://localhost:7071/prime-data-hub-router/health + 188 curl -vvv http://localhost:7071/prime-data-hub-router/api/health + 189 curl -vvv http://localhost:3001/prime-data-hub-router/api/health + 190 curl -vvv http://localhost:3001/api/health + 191 curl -vvv http://localhost:3001/health + 192 curl -vvv http://localhost:8080/health + 193 curl -vvv http://localhost:8081/health + 194 ps + 195 ps aux | grep 832 + 196 ps aux | grep java + 197 curl -vvv http://localhost:57179/health + 198 curl -vvv http://localhost:57179/api/health + 199 ../gradlew tasks + 200 ../gradlew properties + 201 curl -vvv http://localhost:57179/api/vi/health + 202 curl -vvv http://localhost:7071/api/vi/health + 203 curl -vvv http://localhost:3001/api/vi/health + 204 curl -vvv http://localhost:3001/api/health + 205 curl -vvv http://localhost:3001/health + 206 curl -vvv http://localhost:3001/actuator + 207 curl -vvv http://localhost:57179/actuator + 208 ps aux | grep java + 209 curl -vvv http://localhost:60811/actuator + 210 ../gradlew --help + 211 ../gradlew --status + 212 docker ps + 213 docker ps + 214 git status + 215 git checkout -- settings/organizations.yml + 216 ../gradlew reloadSettings + 217 ../gradlew reloadSettings + 218 ../gradlew status + 219 ../gradlew --status + 220 ../gradlew --help + 221 openssl --version + 222 grep -r "elr-fhir-translate" * | grep -v "(build\|test)" + 223 grep -r "elr-fhir-translate" * | grep -v "build\|test" + 224 find . -name "*elr-fhir-translate*" + 225 cd .. + 226 find . -name "*elr-fhir-translate*" + 227 grep -r "elr-fhir-translate" * | grep -v "build\|test" + 228 sftp --help + 229 grep -r FhirTranslateQueueMessage * | grep -v "build\|test" + 230 pwd + 231 cd .. + 232 grep -r FhirTranslateQueueMessage * | grep -v "build\|test" + 233 ls + 234 cd prime-reportstream + 235 ls + 236 find . name "*.tf" . + 237 find . name "*\.tf" . + 238 find . name "*tf" . + 239 find . name "*.tf" + 240 find . name "*\.tf" + 241 find . name "*tf + 242 find . name "*tf" + 243 find . -name "*.tf" + 244 cd operations + 245 ls + 246 ls app + 247 cd app + 248 ls functions + 249 ls terraform + 250 cd ../.. + 251 cd prime-router + 252 grep -r QueueTrigger * | grep -v "build\|test" + 253 history 1 | grep translate + 254 grep -r "elr-fhir-translate" * | grep -v "build\|test" + 255 cd .. + 256 grep -r "elr-fhir-translate" * | grep -v "build\|test" + 257 grep -r elrTranslationQueueName * | grep -v "build\|test" + 258 cd prime-router + 259 grep -ir azureevent * | grep -v "builld\|test" + 260 grep -ir azureevent * | grep -v "build\|test" + 261 grep -ir FhirTranslateQueueMessage * | grep -v "build\|test" + 262 grep -r digest * | grep -v "build\|test" + 263 git status + 264 git checkout -b 16144 origin/main + 265 git fetch -p + 266 git pull + 267 git fetch -p + 268 git pull + 269 git status + 270 grep -ir azureEventService * | grep -v "build\|test" + 271 grep -ir trackevent * | grep -v "build\|test" + 272 cd .. + 273 grep -ir azureEventService * | grep -v "build\|test" + 274 grep -ir trackevent * | grep -v "build\|test" + 275 cd .. + 276 ls + 277 cd prime-reportstream + 278 grep -ir ReportStreamItemEventBuilder * | grep -v "build\|test" + 279 grep -r ITEM_TRANSFORMED * + 280 grep -r ITEM_ * + 281 grep -r ReportStreamItemEvent * + 282 git status + 283 git diff prime-router/src/main/kotlin/fhirengine/engine/FHIRTranslator.kt + 284 git fetch -p + 285 git pull + 286 docker ps + 287 docker ps + 288 exit + 289 cd projects/report-stream/prime-reportstream + 290 ls + 291 cd prime-router + 292 env + 293 docker compose --file "docker-compose.build.yml" up --detach + 294 docker ps + 295 docker ps + 296 ../gradlew run + 297 docker ps + 298 ../gradlew composeDownForce + 299 docker ps + 300 git fetch -p + 301 git status + 302 git pull + 303 ../gradlew clean build + 304 ../gradlew run + 305 git status + 306 git fetch -p + 307 ../gradlew composeDownForce + 308 git pull + 309 ../gradlew clean build + 310 docker ps + 311 docker ps + 312 ../gradlew run + 313 ../gradlew run + 314 ../gradlew run + 315 ../gradlew run -x test + 316 ./gradlew clean build + 317 ../gradlew clean build + 318 ../gradlew clean build -x test + 319 ../gradlew run -x test --stacktrace + 320 ../gradlew clean build + 321 ../gradlew clean build + 322 ../gradlew clean build -x test + 323 ../gradlew run -x test --stacktrace + 324 ../gradlew composeDownForce + 325 git status + 326 git checkout -- . + 327 ../gradlew clean build + 328 ../gradlew run --stacktrace + 329 ../gradlew clean build + 330 ../gradlew clean build --stacktrace + 331 ../gradlew clean build --stacktrace + 332 ../gradlew clean build + 333 ../gradlew clean build + 334 ../gradlew clean build + 335 git fetch -p + 336 git pull + 337 git status + 338 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt + 339 docker ps + 340 ../gradlew clean build + 341 git fetch -p + 342 git pull + 343 ../gradlew clean build + 344 ../gradlew clean build + 345 ../gradlew clean build + 346 ../gradlew clean build + 347 ../gradlew clean build + 348 docker ps + 349 ../gradlew clean build + 350 ../gradlew clean build + 351 ../gradlew clean build + 352 git status + 353 git status + 354 git fetch =p + 355 git fetch -p + 356 git pull + 357 git status + 358 git add . + 359 git status + 360 git commit -m "[16144] Modifications for user story 16144 - Implement Translate Step Updates" + 361 git status + 362 git push origin 16144:platform/bill/16144 + 363 cd .git + 364 ls -al + 365 exit + 366 cd projects/report-stream/prime-reportstream + 367 git status + 368 git push origin 16144:platform/bill/16144 + 369 ls + 370 cd .. + 371 mv prime-reportstream prime-reportstream-SAV + 372 ls -al ~/.ssh + 373 ssh-keygen -t ed25519 -C "billcutshall@navapbc.com" + 374 cd + 375 ls -al ~/.ssh + 376 eval "$(ssh-agent -s)" + 377 touch ~/.ssh/config + 378 vi ~/.ssh/config + 379 ssh-add --apple-use-keychain ~/.ssh/id_ed25519 + 380 pbcopy < ~/.ssh/id_ed25519.pub + 381 vi .gitconfig + 382 git clone git@github.com:CDCgov/prime-reportstream.git + 383 ls + 384 rm -rf prime-reportstream + 385 cd projects + 386 ls + 387 cd report-stream + 388 git clone git@github.com:CDCgov/prime-reportstream.git + 389 ls + 390 ls + 391 ls prime-reportstream + 392 rm -rf prime-reportstream + 393 exit + 394 cd projects/report-stream/ + 395 ls + 396 git clone git@github.com:CDCgov/prime-reportstream.git + 397 cd prime-reportstream + 398 cd prime-router + 399 ../gradlew clean build + 400 env + 401 ls + 402 ../gradlew clean build + 403 git fetch -p + 404 git pull + 405 git status + 406 ../gradlew clean + 407 ./cleanslate.sh + 408 cd ../.. + 409 rm -rf prime-reportstream + 410 ./cleanslate.sh + 411 git clone git@github.com:CDCgov/prime-reportstream.git + 412 rm -rf prime-reportstream + 413 git clone git@github.com:CDCgov/prime-reportstream.git + 414 cd prime-reportstream/prime-router + 415 ./cleanslate.sh + 416 docker ps + 417 docker ps + 418 docker compose -f docker-compose.build.yml up --detach + 419 docker ps + 420 docker compose up --detach vault 1>/dev/null 2>/dev/null + 421 docker ps + 422 ../gradlew composeDown + 423 docker ps + 424 ./gradlew clean build + 425 ../gradlew clean build + 426 git status + 427 git fetch -p + 428 git pull + 429 pwd + 430 ../gradlew clean build + 431 cd .. + 432 ../gradlew clean build + 433 ./gradlew clean build + 434 cd prime-router + 435 ./gradlew build + 436 ../gradlew build + 437 cd ../.. + 438 ls + 439 exit + 440 cd projects/report-stream + 441 ls + 442 git clone git@github.com:CDCgov/prime-reportstream.git + 443 cd prime-reportstream + 444 cd prime-router + 445 ./cleanslate.sh --verbose + 446 docker ps + 447 docker compose -f docker-compose.build.yml up --detach + 448 docker ps + 449 docker compose up --detach vault 1>/dev/null 2>/dev/null + 450 docker ps + 451 docker compose --file "docker-compose.build.yml" up --detach + 452 docker ps + 453 ../gradlew clean build + 454 ls -al + 455 ../gradlew clean build --stacktrace + 456 cd ../.gradle + 457 ls + 458 cd vcs-1 + 459 ls + 460 cat vcs-1.lock + 461 cat hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c + 462 ls hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c + 463 ls hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c/hl7v2-fhir-converter + 464 rm -rf hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c + 465 cd ../ + 466 cd ../prime-router + 467 ../gradlew clean build --stacktrace + 468 ../gradlew run + 469 docker ps + 470 history 1 | grep checkout + 471 git checkout -b 16144 origin/main + 472 git status + 473 git fetch -p + 474 git pull + 475 git status + 476 ../gradlew clean build + 477 git status + 478 ../gradlew clean build -x test + 479 git status + 480 git add . + 481 history 1 | grep commit + 482 git commit -m "[16144] Modifications for user story 16144 - Implement Translate Step Updates" + 483 git status + 484 history 1 | grep push + 485 git push origin 16144:platform/bill/16144 + 486 ../gradlew clean build + 487 ../gradlew clean build + 488 ../gradlew clean build + 489 ../gradlew clean build + 490 ../gradlew clean build + 491 git status + 492 git add . + 493 history 1 | grep commit + 494 git commit -m "[16144] Change to attempt fix for existing unit and integration tests." + 495 history 1 | grep push + 496 git push origin 16144:platform/bill/16144 + 497 grep -r reportServiceMock.getRootReport * + 498 ../gradlew clean build + 499 ../gradlew clean build -x test + 500 ../gradlew clean build -x test + 501 ../gradlew clean build -x test + 502 ../gradlew clean build -x test + 503 ../gradlew clean build + 504 git status + 505 git add . + 506 git commit -m "[16144] Fixed unit tests in FHIRTranslatorTests." + 507 git push origin 16144:platform/bill/16144 + 508 docker ps + 509 docker ps + 510 docker ps + 511 docker ps + 512 docker ps + 513 docker ps + 514 docker ps + 515 docker ps + 516 docker ps + 517 history 1 | grep docker + 518 docker compose --file "docker-compose.build.yml" up --detach + 519 docker ps + 520 docker ps + 521 docker ps + 522 docker ps + 523 docker ps + 524 docker ps + 525 docker ps + 526 docker ps + 527 docker ps + 528 docker ps + 529 git status + 530 git status + 531 git checkout -- src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt + 532 git status + 533 git add . + 534 git commit -m "[16144] Fixed integration tests by modifying FHIRTranslator." + 535 git push origin 16144:platform/bill/16144 + 536 ../gradlew clean build + 537 ../gradlew run + 538 ../gradlew composeDownForce + 539 docker ps + 540 git status + 541 git checkout -- src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt + 542 grep -r "not supported" * + 543 grep -r "not supported" * | grep -v "build\|test" + 544 git status + 545 ../gradlew clean build + 546 ../gradlew clean build + 547 git status + 548 git fetch -p + 549 git pull + 550 docker ps + 551 ../gradlew clean build + 552 ../gradlew clean build + 553 ../gradlew clean build + 554 git status + 555 ../gradlew clean build + 556 ../gradlew clean build + 557 ../gradlew clean build + 558 docker ps + 559 ../gradlew clean build + 560 git status + 561 git add . + 562 history 1 | grep commit + 563 git commit -m "[16144] Added code for tests." + 564 history 1 | grep push + 565 git push origin 16144:platform/bill/16144 + 566 ../gradlew run + 567 ../gradlew run --trace + 568 ../gradlew run + 569 ../gradlew testSmoke + 570 grep -r setBlobDigest * + 571 ../gradlew clean build + 572 ../gradlew clean build + 573 ../gradlew clean build + 574 ../gradlew clean build + 575 grep -r ".blobDigest =" * + 576 grep -r ".digest =" * + 577 ../gradlew clean build + 578 cd .. + 579 grep -r setBlobDigest * + 580 grep -r setBlobDigest * | grep -v "build\|test" + 581 grep -r ".blobDigest =" * | grep -v "build\|test" + 582 docker ps + 583 pwd + 584 grep -r setBlobDigest * | grep -v "\build\|test" + 585 grep -r setBlobDigest * | grep -v "build\|test" + 586 less prime-router/build/generated-src/jooq/src/main/java/gov/cdc/prime/router/azure/db/tables/records/ReportFileRecord.java + 587 grep -r ReportFileRecord * | grep -v "build\|test" + 588 docker ps + 589 ../gradlew clean build + 590 cd prime-router + 591 ../gradlew clean build + 592 git status + 593 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt + 594 git diff src/test/kotlin/common/UniversalPipelineTestUtils.kt + 595 git diff src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt + 596 git checkout -- src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt + 597 git diff src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt + 598 ../gradlew clean build + 599 git status + 600 git add . + 601 history 1 | grep commit + 602 git commit -m "[16144] Added code to account for blob digest properly." + 603 history 1 | grep push + 604 git push origin 16144:platform/bill/16144 + 605 git status + 606 git status + 607 git checkout -b 16144-a origin/platform/bill/16144 + 608 ../gradlew clean build + 609 git fetch -p + 610 git pull + 611 git status + 612 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt + 613 git checkout -- . + 614 git status + 615 git pull + 616 git fetch -p + 617 ../gradlew clean build + 618 ../gradlew clean build + 619 ../gradlew clean build + 620 ../gradlew clean build + 621 ../gradlew clean build + 622 ../gradlew clean build -x test + 623 ../gradlew clean build -x test + 624 ../gradlew clean build + 625 history 1 | grep vault. + 626 history 1 | grep vault. + 627 ../gradlew clean build + 628 docker ps + 629 history 1 | grep docker + 630 find . -name "TaskAction*" + 631 ls -al + 632 cd .vault + 633 ls + 634 cd env + 635 ls + 636 ls -al + 637 cat .env.local + 638 c d + 639 cd ../.. + 640 ../gradlew clean build -x test + 641 ../gradlew clean build + 642 env + 643 cat .zshrc + 644 cacat ~/.zshrc + 645 cat ~/.zshrc + 646 env | grep JAVA + 647 ../gradlew run + 648 ../gradlew composeDownForce + 649 cd .. + 650 ls + 651 ./gradlew tasks + 652 cd prime-router + 653 ../gradlew tasks + 654 ../gradlew package + 655 docker ps + 656 docker ps + 657 exit + 658 cd + 659 ls -al + 660 cd .gradle + 661 ls + 662 ls caches + 663 cd + 664 docker ps + 665 cd projects + 666 cd pr + 667 cd report-stream + 668 cd prime-reportstream-SAV + 669 git status + 670 cd ../prime-reportstream + 671 cd prime-router + 672 ../gradlew composeDown + 673 ../gradlew composeDownForce + 674 docker ps + 675 ../gradlew composeDownForced + 676 docker ps + 677 docker ps + 678 find . -name "FHIRTranslatorIntegrationTests*" + 679 git fetch -p + 680 docker ps + 681 docker ps + 682 git status + 683 grep -oE '^[a-zA-Z][a-zA-Z0-9]*$' "test translation happy path with file digest exception" + 684 echo -n "test translation happy path with file digest exception" | grep -oE '^[a-zA-Z][a-zA-Z0-9]*$' + 685 env + 686 docker ps + 687 docker ps + 688 docker ps + 689 cd .. + 690 cd prime-router + 691 less cleanslate.sh + 692 less cleanslate.sh + 693 docker ps + 694 less cleanslate.sh + 695 ls + 696 less prime + 697 ls + 698 less cleanslate.sh.log + 699 git status + 700 ls + 701 less cleanslate.sh + 702 exit + 703 env + 704 cat ~/.zshrc + 705 uname -a + 706 less cleanslate.sh + 707 uname -m + 708 uname -an + 709 cd .vault + 710 ls + 711 ls config + 712 cat config/local.json + 713 cat env/.env.local + 714 vault + 715 cd .. + 716 less cleanslate.sh + 717 exit + 718 docker ps + 719 docker ps + 720 git status + 721 git diff src/main/kotlin/fhirengine/engine/FHIREngine.kt + 722 git diff src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt + 723 cd .. + 724 grep -r testSmoke * + 725 cd prime-router + 726 ../gradlew testSmoke + 727 ls + 728 ./prime test + 729 git status + 730 git add . + 731 git status + 732 ../gradlew testSmoke + 733 git status + 734 ../gradlew clearDB + 735 ../gradlew reloadSettings + 736 ../gradlew reloadTables + 737 ../gradlew testSmoke + 738 ../gradlew clearDB + 739 ../gradlew reloadSettings + 740 ../gradlew reloadTables + 741 ../gradlew testEnd2EndUP + 742 cat /etc/hosts + 743 grep -r R01 * | grep -v "build\|test" + 744 grep -r CSTE * | grep -v "build\|test" + 745 git fetch -p + 746 git status + 747 git fetch -p + 748 history 1 | grep checkout + 749 git checkout -b 16143 origin/main + 750 ../gradlew clean build + 751 ../gradlew run + 752 ../gradlew clearDB + 753 ../gradlew reloadSettings + 754 ../gradlew reloadTables + 755 ../gradlew testEnd2EndUP + 756 ../gradlew clearDB + 757 ../gradlew reloadSettings + 758 ../gradlew reloadTables + 759 ../gradlew testEnd2EndUP + 760 grep -r "SFTP credentials" * + 761 less cleanslate.sh + 762 cd .vault + 763 ls -al + 764 ls + 765 ls -l + 766 cd config + 767 ls + 768 cat init.sh + 769 ls + 770 cat local.json + 771 cd ../env + 772 ls -al + 773 cat .env.local + 774 cat key + 775 cd ../.. + 776 grep -i sftp cleanslate.sh + 777 ../gradlew quickRun + 778 ../gradlew composeDownForce + 779 ../gradlew clearDB + 780 ../gradlew reloadSettings + 781 ../gradlew reloadTables + 782 ../gradlew testEnd2EndUP + 783 export CREDENTIAL_STORAGE_METHOD="HASHICORP_VAULT" + 784 less cleanslate.sh + 785 ../gradlew clearDB + 786 ../gradlew reloadSettings + 787 ../gradlew reloadTables + 788 ../gradlew testEnd2EndUP + 789 exit + 790 cd projects/report-stream/prime-reportstream/prime-router + 791 history 1 | grep docker + 792 docker compose --file "docker-compose.build.yml" up --detach + 793 docker ps + 794 ../gradlew clean build + 795 ../gradlew clean build + 796 grep -r "any(" * + 797 docker ps + 798 grep -r "no answer found for AzureEventService" * + 799 ../gradlew clean build + 800 docker ps + 801 ../gradlew clean build + 802 ../gradlew clean build + 803 git status + 804 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt + 805 git add . + 806 history 1 | grep commit + 807 git commit -m "[16144] Checking in WIP." + 808 history 1 | grep push + 809 git push origin 16144-a:platform/bill/16144 + 810 grep -r params * + 811 ../gradlew clean build + 812 grep -r bodyFormat * | grep -v "build\|test" + 813 ../gradlew clean build + 814 ../gradlew clean build + 815 ../gradlew clean build + 816 ../gradlew clean build + 817 ../gradlew clean build + 818 ../gradlew clean build + 819 ../gradlew clean build + 820 ../gradlew clean build + 821 ../gradlew clean build + 822 ../gradlew clean build + 823 docker ps + 824 git status + 825 ../gradlew clean build + 826 ../gradlew clean build + 827 ../gradlew clean build + 828 ../gradlew clean build + 829 grep -r IReportStreamEventService * + 830 grep -r IReportStreamEventService * | grep -v "build\|test" + 831 grep -r IReportStreamEventService * | grep -v build + 832 grep -r IReportStreamEventService * | grep -v build + 833 git status + 834 git add . + 835 history 1 | grep commit + 836 git commit -m "[16144] Checking in WIP." + 837 history 1 | grep push + 838 git push origin 16144-a:platform/bill/16144 + 839 ../gradlew clean build + 840 docker ps + 841 docker ps + 842 ../gradlew clean build + 843 ../gradlew clean build + 844 ../gradlew clean build + 845 ../gradlew clean build + 846 git status + 847 git add . + 848 git commit -m "[16144] Made change to FHIREngine to account for nullable reportEventService actually having a value in builder." + 849 git push origin 16144-a:platform/bill/16144 + 850 git fetch -p + 851 git pull + 852 ../gradlew clean build + 853 ../gradlew clean build + 854 ../gradlew clean build + 855 git status + 856 git add . + 857 git commit -m "[16144] Updates based on PR review." + 858 git push origin 16144-a:platform/bill/16144 + 859 ../gradlew clean build + 860 git fetch -p + 861 git pull + 862 git fetch -p + 863 ../gradlew clean build + 864 git status + 865 git add . + 866 git commit -m "[16144] Update based on PR review." + 867 git push origin 16144-a:platform/bill/16144 + 868 ../gradlew clean build + 869 ../gradlew clean build + 870 ../gradlew clean build + 871 ../gradlew clean build + 872 ../gradlew testSmoke + 873 history 1 | grep testSmoke + 874 docker ps + 875 git commit -m "[16144] Changed url and digest to use correct reportdocument." + 876 git push origin 16144-a:platform/bill/16144 + 877 ../gradlew run + 878 docker ps + 879 ../gradlew composeDownForce + 880 git status + 881 git status + 882 git add . + 883 git commit -m "[16144] Added additional checks to integration test." + 884 git fetch -p + 885 git pull + 886 ../gradlew clean build + 887 ../gradlew clean build + 888 git status + 889 git add src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt + 890 git commit -m "[16144] Added additional checks to integration test." + 891 git push origin 16144-a:platform/bill/16144 + 892 git fetch -p + 893 git pull + 894 git fetch -p + 895 git pull + 896 ../gradlew clean build + 897 ../gradlew clean build + 898 git status + 899 git add . + 900 git commit -m "[16144] Added additional check to integration tests." + 901 git push origin 16144-a:platform/bill/16144 + 902 ../gradlew run + 903 docker ps + 904 docker ps + 905 docker ps + 906 ../gradlew composeDownForce + 907 docker ps + 908 ../gradlew quickRun + 909 ../gradlew composeDownForce + 910 ../gradlew quickRun + 911 ../gradlew composeDownForce + 912 ../gradlew tasks + 913 grep -r credentials * + 914 grep -r credentials * | grep -v "build\|test" + 915 less cleanslate.sh + 916 ./prime create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass 1>>${LOG?} 2>&1 + 917 ls + 918 less cleanslate.sh.log + 919 less cleanslate.sh + 920 export LOG=fred.txt + 921 ./prime create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass 1>>${LOG?} 2>&1 + 922 cat fred.txt + 923 less cleanslate.sh + 924 ./prime multiple-settings set --silent --input settings/organizations.yml 1>>${LOG?} 2>&1 + 925 cat fred.txt + 926 ../gradlew quickRun + 927 ../gradlew composeDownForce + 928 export CREDENTIAL_STORAGE_METHOD="HASHICORP_VAULT" + 929 ../gradlew quickRun + 930 ../gradlew composeDownForce + 931 cd .. + 932 cd .. + 933 ls + 934 mv prime-reportstream prime-reportstream-SAV-1 + 935 exit + 936 cd + 937 cd .gradle + 938 \tls -al + 939 cd .. + 940 mv .gradle .gradle-SAV + 941 cd .gradle + 942 ls -al + 943 cd + 944 cd + 945 cd projects/report-stream/prime-reportstream/prime-router + 946 ../gradlew cleanDB + 947 ../gradlew clearDB + 948 ../gradlew reloadSettings + 949 ../gradlew reloadTables + 950 ../gradlew testEnd2EndUP + 951 ../gradlew clearDB + 952 ../gradlew reloadSettings + 953 ../gradlew reloadTables + 954 ../gradlew testSmoke + 955 less build.gradle.kts + 956 git status + 957 git branch + 958 git checkout -b 16143 origin/main + 959 git fetch -p + 960 git pull + 961 ../gradlew clean build + 962 git fetch -p + 963 git pull + 964 git fetch -p + 965 git pull + 966 docker ps + 967 git fetch -p + 968 exit + 969 env + 970 cd projects/report-stream + 971 ls + 972 history 1 | grep clone + 973 git clone git@github.com:CDCgov/prime-reportstream.git + 974 cd prime-reportstream + 975 cd prime-router + 976 ./cleanslate --verbose + 977 ls + 978 ./cleanslate.sh --verbose + 979 cd .. + 980 cd ./prime-router\n./cleanslate.sh + 981 cd ../.. + 982 rm -rf prime-reportstream + 983 git clone git@github.com:CDCgov/prime-reportstream.git + 984 cd prime-reportstream/prime-router + 985 ./cleanslate --verbose + 986 ./cleanslate.sh --verbose + 987 docker ps + 988 docker compose up --detach vault 1>/dev/null 2>/dev/null + 989 ./gradlew primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" + 990 ../gradlew primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" + 991 ../gradlew reloadTables + 992 ../gradlew composeDownForced + 993 ../gradlew quickRun + 994 ../gradlew composeDownForced + 995 ../gradlew quickRun + 996 ../gradlew quickRun + 997 ../gradlew clean build + 998 ../gradlew quickRun + 999 ../gradlew composeDownForced + 1000 exit + 1001 git fetch -p + 1002 git status + 1003 git fetch -p + 1004 history 1 | grep e2e + 1005 history 1 | grep gradlew | sort -U + 1006 history 1 | grep gradlew | sort -u + 1007 history 1 | grep nd + 1008 ../gradlew tasks + 1009 ./gradlew testEnd2EndUP + 1010 ../gradlew testEnd2EndUP + 1011 ../gradlew testSmoke + 1012 history 1 | grep clear + 1013 history 1 | grep reload From 48cf73bbf63335ad3edf6460827d9da1c6e5b528 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Wed, 4 Dec 2024 13:46:26 -0500 Subject: [PATCH 04/17] [16143] Removed tmp file. --- prime-router/tmp.txt | 1013 ------------------------------------------ 1 file changed, 1013 deletions(-) delete mode 100644 prime-router/tmp.txt diff --git a/prime-router/tmp.txt b/prime-router/tmp.txt deleted file mode 100644 index 13c28a4cb34..00000000000 --- a/prime-router/tmp.txt +++ /dev/null @@ -1,1013 +0,0 @@ - 1 cd prime-router - 2 ./cleanslate.sh --verbose - 3 docker ps - 4 ./gradlew tasks - 5 gradle tasks - 6 docker compose down - 7 docker ps - 8 docker compose down - 9 docker-compose down - 10 docker-compose down d698f0920a37 - 11 docker-compose down prime-router-postgresql-1 - 12 docker-compose down prime-router-postgresql - 13 docker ps - 14 ./gradlew tasks - 15 ls - 16 ls prime - 17 gradle tasks - 18 docker ps - 19 git fetch -p - 20 git status - 21 git fetch -p - 22 cd .. - 23 grep -ir azurite * - 24 grep -ir azurite * | grep -v build | grep -v test - 25 find . -name "*.sh" - 26 cd prime-router - 27 less cleanslate.sh - 28 less docker-compose.yml - 29 grep -ir azurite * | grep -v '(build|test)' - 30 grep -ir azurite * | grep -v (build|test) - 31 grep -ir azurite * | grep -v build|test - 32 grep -ir azurite * | grep -v 'build|test' - 33 grep -ir azurite * | grep -v "build|test" - 34 grep -ir azurite * | grep -v "build\|test" - 35 ls - 36 ls -al - 37 less devenv-infrastructure.sh - 38 less docker-compose.yml - 39 ls - 40 ls .. - 41 less docker-compose.yml - 42 find . -name "Docker*" - 43 cd .. - 44 find . -name "Docker*" - 45 less ./.environment/docker/docker-compose/Dockerfile.azurite - 46 less ./.environment/docker/docker-compose/Dockerfile.azurite - 47 less docker-compose.yml - 48 cd prime-router - 49 less docker-compose.yml - 50 cd .. - 51 git branch - 52 git checkout main - 53 git fetch -p - 54 git pull - 55 cd .. - 56 history 1 | grep clone - 57 ls - 58 rm -rf prime-reportstream - 59 git clone https://github.com/CDCgov/prime-reportstream.git - 60 git checkout main - 61 cd prime-reportstream - 62 git checkout main - 63 git fetch -p - 64 ls - 65 cd prime-router - 66 git fetch -p - 67 cd .. - 68 git fetch -p - 69 cd prime-router - 70 ./cleanslate.sh --verbose - 71 docker ps - 72 ls - 73 gradle tasks - 74 cat /Users/bill/projects/report-stream/prime-reportstream/prime-router/.vault/env/.env.local - 75 docker compose -f docker-compose.build.yml up --detach - 76 docker ps - 77 docker compose up --detach vault 1>/dev/null 2>/dev/null - 78 docker ps - 79 ls - 80 gradle primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" - 81 gradle reloadTables - 82 docker ps - 83 gradle reloadTables - 84 docker ps - 85 gradle reloadTables - 86 grep -r 7071 * | grep -v 'test\|build' - 87 docker ps - 88 gradle run - 89 ../gradlew run - 90 docker ps - 91 ../gradlew reloadTables - 92 ../gradlew quickRun - 93 docker ps - 94 ../gradlew reloadTables - 95 ../gradlew run - 96 ../gradlew tasks - 97 ../gradlew clean build - 98 docker ps - 99 ../gradlew clean build -x test - 100 ../gradlew run -x test - 101 ls ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions - 102 ls ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions/prime-data-hub-router - 103 ls /Users/bill/projects/report-stream/prime-reportstream/prime-router/build/azure-functions/prime-data-hub-router - 104 ../gradlew reloadSettings - 105 docker ps - 106 ../gradlew quickRun - 107 docker ps - 108 ../gradlew composeDown - 109 ../gradlew composeDownForced - 110 docker ps - 111 docker ps - 112 docker ps - 113 ../gradlew run - 114 ls - 115 docker compose -f docker-compose.build.yml up --detach - 116 docker ps - 117 ../gradlew run - 118 docker ps - 119 ../gradlew quickRun - 120 ../gradlew run - 121 ../gradlew run --debug - 122 echo $JAVA_HOME - 123 java -version - 124 env - 125 cat ~/.zshrc - 126 export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH" - 127 export JAVA_HOME=$(/usr/libexec/java_home) - 128 env - 129 ../gradlew run --debug - 130 docker ps - 131 docker ps - 132 grep -r 5432 * - 133 grep -r 5432 * | grep -v 'build|test' - 134 grep -r 5432 * | grep -v "build\|test" - 135 docker ps - 136 ../gradlew composeDown - 137 docker ps - 138 ../gradlew composeDownForced - 139 exit - 140 cd - 141 ls -al - 142 less .gitconfig - 143 cat .stCommitMsg - 144 cat .gitconfig - 145 gpg --version - 146 gpg2 --version - 147 exit - 148 gpg2 --version - 149 gpg2 --full-generate-key - 150 ls -al - 151 ls .gnupg - 152 vi .gitconfig - 153 ls .gnupg - 154 vi .gitconfig - 155 gpg2 --armor --export real.name@organization.tld - 156 gpg2 --armor --export billcutshall@navapbc.com.tld - 157 gpg2 --armor --export Bill.Cutshall@navapbc.com.tld - 158 gpg2 --armor --export billcutshall@navapbc.com - 159 exit - 160 docker ps - 161 cd .. - 162 ./prime --help - 163 ls - 164 cd prime-router - 165 ls - 166 ./prime --help - 167 cat prime - 168 ../gradlew reloadTables - 169 ../gradlew reloadSettings - 170 curl --help - 171 curl http://localhost:7071/api/health - 172 curl -vvv http://localhost:7071/api/health - 173 ps - 174 netstat -vanp - 175 netstat -an - 176 lsof -i - 177 lsof -i tcp:7071 - 178 top - 179 docker ps - 180 lsof -i tcp:3000 - 181 ps aux - 182 ps aux | grep 7071 - 183 ps aux | grep 1113 - 184 curl -vvv http://localhost:7071/api/health - 185 curl -vvv http://localhost:7071/health - 186 curl -vvv http://localhost:7071/api/reports - 187 curl -vvv http://localhost:7071/prime-data-hub-router/health - 188 curl -vvv http://localhost:7071/prime-data-hub-router/api/health - 189 curl -vvv http://localhost:3001/prime-data-hub-router/api/health - 190 curl -vvv http://localhost:3001/api/health - 191 curl -vvv http://localhost:3001/health - 192 curl -vvv http://localhost:8080/health - 193 curl -vvv http://localhost:8081/health - 194 ps - 195 ps aux | grep 832 - 196 ps aux | grep java - 197 curl -vvv http://localhost:57179/health - 198 curl -vvv http://localhost:57179/api/health - 199 ../gradlew tasks - 200 ../gradlew properties - 201 curl -vvv http://localhost:57179/api/vi/health - 202 curl -vvv http://localhost:7071/api/vi/health - 203 curl -vvv http://localhost:3001/api/vi/health - 204 curl -vvv http://localhost:3001/api/health - 205 curl -vvv http://localhost:3001/health - 206 curl -vvv http://localhost:3001/actuator - 207 curl -vvv http://localhost:57179/actuator - 208 ps aux | grep java - 209 curl -vvv http://localhost:60811/actuator - 210 ../gradlew --help - 211 ../gradlew --status - 212 docker ps - 213 docker ps - 214 git status - 215 git checkout -- settings/organizations.yml - 216 ../gradlew reloadSettings - 217 ../gradlew reloadSettings - 218 ../gradlew status - 219 ../gradlew --status - 220 ../gradlew --help - 221 openssl --version - 222 grep -r "elr-fhir-translate" * | grep -v "(build\|test)" - 223 grep -r "elr-fhir-translate" * | grep -v "build\|test" - 224 find . -name "*elr-fhir-translate*" - 225 cd .. - 226 find . -name "*elr-fhir-translate*" - 227 grep -r "elr-fhir-translate" * | grep -v "build\|test" - 228 sftp --help - 229 grep -r FhirTranslateQueueMessage * | grep -v "build\|test" - 230 pwd - 231 cd .. - 232 grep -r FhirTranslateQueueMessage * | grep -v "build\|test" - 233 ls - 234 cd prime-reportstream - 235 ls - 236 find . name "*.tf" . - 237 find . name "*\.tf" . - 238 find . name "*tf" . - 239 find . name "*.tf" - 240 find . name "*\.tf" - 241 find . name "*tf - 242 find . name "*tf" - 243 find . -name "*.tf" - 244 cd operations - 245 ls - 246 ls app - 247 cd app - 248 ls functions - 249 ls terraform - 250 cd ../.. - 251 cd prime-router - 252 grep -r QueueTrigger * | grep -v "build\|test" - 253 history 1 | grep translate - 254 grep -r "elr-fhir-translate" * | grep -v "build\|test" - 255 cd .. - 256 grep -r "elr-fhir-translate" * | grep -v "build\|test" - 257 grep -r elrTranslationQueueName * | grep -v "build\|test" - 258 cd prime-router - 259 grep -ir azureevent * | grep -v "builld\|test" - 260 grep -ir azureevent * | grep -v "build\|test" - 261 grep -ir FhirTranslateQueueMessage * | grep -v "build\|test" - 262 grep -r digest * | grep -v "build\|test" - 263 git status - 264 git checkout -b 16144 origin/main - 265 git fetch -p - 266 git pull - 267 git fetch -p - 268 git pull - 269 git status - 270 grep -ir azureEventService * | grep -v "build\|test" - 271 grep -ir trackevent * | grep -v "build\|test" - 272 cd .. - 273 grep -ir azureEventService * | grep -v "build\|test" - 274 grep -ir trackevent * | grep -v "build\|test" - 275 cd .. - 276 ls - 277 cd prime-reportstream - 278 grep -ir ReportStreamItemEventBuilder * | grep -v "build\|test" - 279 grep -r ITEM_TRANSFORMED * - 280 grep -r ITEM_ * - 281 grep -r ReportStreamItemEvent * - 282 git status - 283 git diff prime-router/src/main/kotlin/fhirengine/engine/FHIRTranslator.kt - 284 git fetch -p - 285 git pull - 286 docker ps - 287 docker ps - 288 exit - 289 cd projects/report-stream/prime-reportstream - 290 ls - 291 cd prime-router - 292 env - 293 docker compose --file "docker-compose.build.yml" up --detach - 294 docker ps - 295 docker ps - 296 ../gradlew run - 297 docker ps - 298 ../gradlew composeDownForce - 299 docker ps - 300 git fetch -p - 301 git status - 302 git pull - 303 ../gradlew clean build - 304 ../gradlew run - 305 git status - 306 git fetch -p - 307 ../gradlew composeDownForce - 308 git pull - 309 ../gradlew clean build - 310 docker ps - 311 docker ps - 312 ../gradlew run - 313 ../gradlew run - 314 ../gradlew run - 315 ../gradlew run -x test - 316 ./gradlew clean build - 317 ../gradlew clean build - 318 ../gradlew clean build -x test - 319 ../gradlew run -x test --stacktrace - 320 ../gradlew clean build - 321 ../gradlew clean build - 322 ../gradlew clean build -x test - 323 ../gradlew run -x test --stacktrace - 324 ../gradlew composeDownForce - 325 git status - 326 git checkout -- . - 327 ../gradlew clean build - 328 ../gradlew run --stacktrace - 329 ../gradlew clean build - 330 ../gradlew clean build --stacktrace - 331 ../gradlew clean build --stacktrace - 332 ../gradlew clean build - 333 ../gradlew clean build - 334 ../gradlew clean build - 335 git fetch -p - 336 git pull - 337 git status - 338 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt - 339 docker ps - 340 ../gradlew clean build - 341 git fetch -p - 342 git pull - 343 ../gradlew clean build - 344 ../gradlew clean build - 345 ../gradlew clean build - 346 ../gradlew clean build - 347 ../gradlew clean build - 348 docker ps - 349 ../gradlew clean build - 350 ../gradlew clean build - 351 ../gradlew clean build - 352 git status - 353 git status - 354 git fetch =p - 355 git fetch -p - 356 git pull - 357 git status - 358 git add . - 359 git status - 360 git commit -m "[16144] Modifications for user story 16144 - Implement Translate Step Updates" - 361 git status - 362 git push origin 16144:platform/bill/16144 - 363 cd .git - 364 ls -al - 365 exit - 366 cd projects/report-stream/prime-reportstream - 367 git status - 368 git push origin 16144:platform/bill/16144 - 369 ls - 370 cd .. - 371 mv prime-reportstream prime-reportstream-SAV - 372 ls -al ~/.ssh - 373 ssh-keygen -t ed25519 -C "billcutshall@navapbc.com" - 374 cd - 375 ls -al ~/.ssh - 376 eval "$(ssh-agent -s)" - 377 touch ~/.ssh/config - 378 vi ~/.ssh/config - 379 ssh-add --apple-use-keychain ~/.ssh/id_ed25519 - 380 pbcopy < ~/.ssh/id_ed25519.pub - 381 vi .gitconfig - 382 git clone git@github.com:CDCgov/prime-reportstream.git - 383 ls - 384 rm -rf prime-reportstream - 385 cd projects - 386 ls - 387 cd report-stream - 388 git clone git@github.com:CDCgov/prime-reportstream.git - 389 ls - 390 ls - 391 ls prime-reportstream - 392 rm -rf prime-reportstream - 393 exit - 394 cd projects/report-stream/ - 395 ls - 396 git clone git@github.com:CDCgov/prime-reportstream.git - 397 cd prime-reportstream - 398 cd prime-router - 399 ../gradlew clean build - 400 env - 401 ls - 402 ../gradlew clean build - 403 git fetch -p - 404 git pull - 405 git status - 406 ../gradlew clean - 407 ./cleanslate.sh - 408 cd ../.. - 409 rm -rf prime-reportstream - 410 ./cleanslate.sh - 411 git clone git@github.com:CDCgov/prime-reportstream.git - 412 rm -rf prime-reportstream - 413 git clone git@github.com:CDCgov/prime-reportstream.git - 414 cd prime-reportstream/prime-router - 415 ./cleanslate.sh - 416 docker ps - 417 docker ps - 418 docker compose -f docker-compose.build.yml up --detach - 419 docker ps - 420 docker compose up --detach vault 1>/dev/null 2>/dev/null - 421 docker ps - 422 ../gradlew composeDown - 423 docker ps - 424 ./gradlew clean build - 425 ../gradlew clean build - 426 git status - 427 git fetch -p - 428 git pull - 429 pwd - 430 ../gradlew clean build - 431 cd .. - 432 ../gradlew clean build - 433 ./gradlew clean build - 434 cd prime-router - 435 ./gradlew build - 436 ../gradlew build - 437 cd ../.. - 438 ls - 439 exit - 440 cd projects/report-stream - 441 ls - 442 git clone git@github.com:CDCgov/prime-reportstream.git - 443 cd prime-reportstream - 444 cd prime-router - 445 ./cleanslate.sh --verbose - 446 docker ps - 447 docker compose -f docker-compose.build.yml up --detach - 448 docker ps - 449 docker compose up --detach vault 1>/dev/null 2>/dev/null - 450 docker ps - 451 docker compose --file "docker-compose.build.yml" up --detach - 452 docker ps - 453 ../gradlew clean build - 454 ls -al - 455 ../gradlew clean build --stacktrace - 456 cd ../.gradle - 457 ls - 458 cd vcs-1 - 459 ls - 460 cat vcs-1.lock - 461 cat hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c - 462 ls hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c - 463 ls hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c/hl7v2-fhir-converter - 464 rm -rf hl7v2-fhir_ceb5eyxyfvflmdloyy6lk5d5c - 465 cd ../ - 466 cd ../prime-router - 467 ../gradlew clean build --stacktrace - 468 ../gradlew run - 469 docker ps - 470 history 1 | grep checkout - 471 git checkout -b 16144 origin/main - 472 git status - 473 git fetch -p - 474 git pull - 475 git status - 476 ../gradlew clean build - 477 git status - 478 ../gradlew clean build -x test - 479 git status - 480 git add . - 481 history 1 | grep commit - 482 git commit -m "[16144] Modifications for user story 16144 - Implement Translate Step Updates" - 483 git status - 484 history 1 | grep push - 485 git push origin 16144:platform/bill/16144 - 486 ../gradlew clean build - 487 ../gradlew clean build - 488 ../gradlew clean build - 489 ../gradlew clean build - 490 ../gradlew clean build - 491 git status - 492 git add . - 493 history 1 | grep commit - 494 git commit -m "[16144] Change to attempt fix for existing unit and integration tests." - 495 history 1 | grep push - 496 git push origin 16144:platform/bill/16144 - 497 grep -r reportServiceMock.getRootReport * - 498 ../gradlew clean build - 499 ../gradlew clean build -x test - 500 ../gradlew clean build -x test - 501 ../gradlew clean build -x test - 502 ../gradlew clean build -x test - 503 ../gradlew clean build - 504 git status - 505 git add . - 506 git commit -m "[16144] Fixed unit tests in FHIRTranslatorTests." - 507 git push origin 16144:platform/bill/16144 - 508 docker ps - 509 docker ps - 510 docker ps - 511 docker ps - 512 docker ps - 513 docker ps - 514 docker ps - 515 docker ps - 516 docker ps - 517 history 1 | grep docker - 518 docker compose --file "docker-compose.build.yml" up --detach - 519 docker ps - 520 docker ps - 521 docker ps - 522 docker ps - 523 docker ps - 524 docker ps - 525 docker ps - 526 docker ps - 527 docker ps - 528 docker ps - 529 git status - 530 git status - 531 git checkout -- src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt - 532 git status - 533 git add . - 534 git commit -m "[16144] Fixed integration tests by modifying FHIRTranslator." - 535 git push origin 16144:platform/bill/16144 - 536 ../gradlew clean build - 537 ../gradlew run - 538 ../gradlew composeDownForce - 539 docker ps - 540 git status - 541 git checkout -- src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt - 542 grep -r "not supported" * - 543 grep -r "not supported" * | grep -v "build\|test" - 544 git status - 545 ../gradlew clean build - 546 ../gradlew clean build - 547 git status - 548 git fetch -p - 549 git pull - 550 docker ps - 551 ../gradlew clean build - 552 ../gradlew clean build - 553 ../gradlew clean build - 554 git status - 555 ../gradlew clean build - 556 ../gradlew clean build - 557 ../gradlew clean build - 558 docker ps - 559 ../gradlew clean build - 560 git status - 561 git add . - 562 history 1 | grep commit - 563 git commit -m "[16144] Added code for tests." - 564 history 1 | grep push - 565 git push origin 16144:platform/bill/16144 - 566 ../gradlew run - 567 ../gradlew run --trace - 568 ../gradlew run - 569 ../gradlew testSmoke - 570 grep -r setBlobDigest * - 571 ../gradlew clean build - 572 ../gradlew clean build - 573 ../gradlew clean build - 574 ../gradlew clean build - 575 grep -r ".blobDigest =" * - 576 grep -r ".digest =" * - 577 ../gradlew clean build - 578 cd .. - 579 grep -r setBlobDigest * - 580 grep -r setBlobDigest * | grep -v "build\|test" - 581 grep -r ".blobDigest =" * | grep -v "build\|test" - 582 docker ps - 583 pwd - 584 grep -r setBlobDigest * | grep -v "\build\|test" - 585 grep -r setBlobDigest * | grep -v "build\|test" - 586 less prime-router/build/generated-src/jooq/src/main/java/gov/cdc/prime/router/azure/db/tables/records/ReportFileRecord.java - 587 grep -r ReportFileRecord * | grep -v "build\|test" - 588 docker ps - 589 ../gradlew clean build - 590 cd prime-router - 591 ../gradlew clean build - 592 git status - 593 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt - 594 git diff src/test/kotlin/common/UniversalPipelineTestUtils.kt - 595 git diff src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt - 596 git checkout -- src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt - 597 git diff src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt - 598 ../gradlew clean build - 599 git status - 600 git add . - 601 history 1 | grep commit - 602 git commit -m "[16144] Added code to account for blob digest properly." - 603 history 1 | grep push - 604 git push origin 16144:platform/bill/16144 - 605 git status - 606 git status - 607 git checkout -b 16144-a origin/platform/bill/16144 - 608 ../gradlew clean build - 609 git fetch -p - 610 git pull - 611 git status - 612 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt - 613 git checkout -- . - 614 git status - 615 git pull - 616 git fetch -p - 617 ../gradlew clean build - 618 ../gradlew clean build - 619 ../gradlew clean build - 620 ../gradlew clean build - 621 ../gradlew clean build - 622 ../gradlew clean build -x test - 623 ../gradlew clean build -x test - 624 ../gradlew clean build - 625 history 1 | grep vault. - 626 history 1 | grep vault. - 627 ../gradlew clean build - 628 docker ps - 629 history 1 | grep docker - 630 find . -name "TaskAction*" - 631 ls -al - 632 cd .vault - 633 ls - 634 cd env - 635 ls - 636 ls -al - 637 cat .env.local - 638 c d - 639 cd ../.. - 640 ../gradlew clean build -x test - 641 ../gradlew clean build - 642 env - 643 cat .zshrc - 644 cacat ~/.zshrc - 645 cat ~/.zshrc - 646 env | grep JAVA - 647 ../gradlew run - 648 ../gradlew composeDownForce - 649 cd .. - 650 ls - 651 ./gradlew tasks - 652 cd prime-router - 653 ../gradlew tasks - 654 ../gradlew package - 655 docker ps - 656 docker ps - 657 exit - 658 cd - 659 ls -al - 660 cd .gradle - 661 ls - 662 ls caches - 663 cd - 664 docker ps - 665 cd projects - 666 cd pr - 667 cd report-stream - 668 cd prime-reportstream-SAV - 669 git status - 670 cd ../prime-reportstream - 671 cd prime-router - 672 ../gradlew composeDown - 673 ../gradlew composeDownForce - 674 docker ps - 675 ../gradlew composeDownForced - 676 docker ps - 677 docker ps - 678 find . -name "FHIRTranslatorIntegrationTests*" - 679 git fetch -p - 680 docker ps - 681 docker ps - 682 git status - 683 grep -oE '^[a-zA-Z][a-zA-Z0-9]*$' "test translation happy path with file digest exception" - 684 echo -n "test translation happy path with file digest exception" | grep -oE '^[a-zA-Z][a-zA-Z0-9]*$' - 685 env - 686 docker ps - 687 docker ps - 688 docker ps - 689 cd .. - 690 cd prime-router - 691 less cleanslate.sh - 692 less cleanslate.sh - 693 docker ps - 694 less cleanslate.sh - 695 ls - 696 less prime - 697 ls - 698 less cleanslate.sh.log - 699 git status - 700 ls - 701 less cleanslate.sh - 702 exit - 703 env - 704 cat ~/.zshrc - 705 uname -a - 706 less cleanslate.sh - 707 uname -m - 708 uname -an - 709 cd .vault - 710 ls - 711 ls config - 712 cat config/local.json - 713 cat env/.env.local - 714 vault - 715 cd .. - 716 less cleanslate.sh - 717 exit - 718 docker ps - 719 docker ps - 720 git status - 721 git diff src/main/kotlin/fhirengine/engine/FHIREngine.kt - 722 git diff src/test/kotlin/fhirengine/engine/FhirTranslatorTests.kt - 723 cd .. - 724 grep -r testSmoke * - 725 cd prime-router - 726 ../gradlew testSmoke - 727 ls - 728 ./prime test - 729 git status - 730 git add . - 731 git status - 732 ../gradlew testSmoke - 733 git status - 734 ../gradlew clearDB - 735 ../gradlew reloadSettings - 736 ../gradlew reloadTables - 737 ../gradlew testSmoke - 738 ../gradlew clearDB - 739 ../gradlew reloadSettings - 740 ../gradlew reloadTables - 741 ../gradlew testEnd2EndUP - 742 cat /etc/hosts - 743 grep -r R01 * | grep -v "build\|test" - 744 grep -r CSTE * | grep -v "build\|test" - 745 git fetch -p - 746 git status - 747 git fetch -p - 748 history 1 | grep checkout - 749 git checkout -b 16143 origin/main - 750 ../gradlew clean build - 751 ../gradlew run - 752 ../gradlew clearDB - 753 ../gradlew reloadSettings - 754 ../gradlew reloadTables - 755 ../gradlew testEnd2EndUP - 756 ../gradlew clearDB - 757 ../gradlew reloadSettings - 758 ../gradlew reloadTables - 759 ../gradlew testEnd2EndUP - 760 grep -r "SFTP credentials" * - 761 less cleanslate.sh - 762 cd .vault - 763 ls -al - 764 ls - 765 ls -l - 766 cd config - 767 ls - 768 cat init.sh - 769 ls - 770 cat local.json - 771 cd ../env - 772 ls -al - 773 cat .env.local - 774 cat key - 775 cd ../.. - 776 grep -i sftp cleanslate.sh - 777 ../gradlew quickRun - 778 ../gradlew composeDownForce - 779 ../gradlew clearDB - 780 ../gradlew reloadSettings - 781 ../gradlew reloadTables - 782 ../gradlew testEnd2EndUP - 783 export CREDENTIAL_STORAGE_METHOD="HASHICORP_VAULT" - 784 less cleanslate.sh - 785 ../gradlew clearDB - 786 ../gradlew reloadSettings - 787 ../gradlew reloadTables - 788 ../gradlew testEnd2EndUP - 789 exit - 790 cd projects/report-stream/prime-reportstream/prime-router - 791 history 1 | grep docker - 792 docker compose --file "docker-compose.build.yml" up --detach - 793 docker ps - 794 ../gradlew clean build - 795 ../gradlew clean build - 796 grep -r "any(" * - 797 docker ps - 798 grep -r "no answer found for AzureEventService" * - 799 ../gradlew clean build - 800 docker ps - 801 ../gradlew clean build - 802 ../gradlew clean build - 803 git status - 804 git diff src/main/kotlin/fhirengine/engine/FHIRTranslator.kt - 805 git add . - 806 history 1 | grep commit - 807 git commit -m "[16144] Checking in WIP." - 808 history 1 | grep push - 809 git push origin 16144-a:platform/bill/16144 - 810 grep -r params * - 811 ../gradlew clean build - 812 grep -r bodyFormat * | grep -v "build\|test" - 813 ../gradlew clean build - 814 ../gradlew clean build - 815 ../gradlew clean build - 816 ../gradlew clean build - 817 ../gradlew clean build - 818 ../gradlew clean build - 819 ../gradlew clean build - 820 ../gradlew clean build - 821 ../gradlew clean build - 822 ../gradlew clean build - 823 docker ps - 824 git status - 825 ../gradlew clean build - 826 ../gradlew clean build - 827 ../gradlew clean build - 828 ../gradlew clean build - 829 grep -r IReportStreamEventService * - 830 grep -r IReportStreamEventService * | grep -v "build\|test" - 831 grep -r IReportStreamEventService * | grep -v build - 832 grep -r IReportStreamEventService * | grep -v build - 833 git status - 834 git add . - 835 history 1 | grep commit - 836 git commit -m "[16144] Checking in WIP." - 837 history 1 | grep push - 838 git push origin 16144-a:platform/bill/16144 - 839 ../gradlew clean build - 840 docker ps - 841 docker ps - 842 ../gradlew clean build - 843 ../gradlew clean build - 844 ../gradlew clean build - 845 ../gradlew clean build - 846 git status - 847 git add . - 848 git commit -m "[16144] Made change to FHIREngine to account for nullable reportEventService actually having a value in builder." - 849 git push origin 16144-a:platform/bill/16144 - 850 git fetch -p - 851 git pull - 852 ../gradlew clean build - 853 ../gradlew clean build - 854 ../gradlew clean build - 855 git status - 856 git add . - 857 git commit -m "[16144] Updates based on PR review." - 858 git push origin 16144-a:platform/bill/16144 - 859 ../gradlew clean build - 860 git fetch -p - 861 git pull - 862 git fetch -p - 863 ../gradlew clean build - 864 git status - 865 git add . - 866 git commit -m "[16144] Update based on PR review." - 867 git push origin 16144-a:platform/bill/16144 - 868 ../gradlew clean build - 869 ../gradlew clean build - 870 ../gradlew clean build - 871 ../gradlew clean build - 872 ../gradlew testSmoke - 873 history 1 | grep testSmoke - 874 docker ps - 875 git commit -m "[16144] Changed url and digest to use correct reportdocument." - 876 git push origin 16144-a:platform/bill/16144 - 877 ../gradlew run - 878 docker ps - 879 ../gradlew composeDownForce - 880 git status - 881 git status - 882 git add . - 883 git commit -m "[16144] Added additional checks to integration test." - 884 git fetch -p - 885 git pull - 886 ../gradlew clean build - 887 ../gradlew clean build - 888 git status - 889 git add src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt - 890 git commit -m "[16144] Added additional checks to integration test." - 891 git push origin 16144-a:platform/bill/16144 - 892 git fetch -p - 893 git pull - 894 git fetch -p - 895 git pull - 896 ../gradlew clean build - 897 ../gradlew clean build - 898 git status - 899 git add . - 900 git commit -m "[16144] Added additional check to integration tests." - 901 git push origin 16144-a:platform/bill/16144 - 902 ../gradlew run - 903 docker ps - 904 docker ps - 905 docker ps - 906 ../gradlew composeDownForce - 907 docker ps - 908 ../gradlew quickRun - 909 ../gradlew composeDownForce - 910 ../gradlew quickRun - 911 ../gradlew composeDownForce - 912 ../gradlew tasks - 913 grep -r credentials * - 914 grep -r credentials * | grep -v "build\|test" - 915 less cleanslate.sh - 916 ./prime create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass 1>>${LOG?} 2>&1 - 917 ls - 918 less cleanslate.sh.log - 919 less cleanslate.sh - 920 export LOG=fred.txt - 921 ./prime create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass 1>>${LOG?} 2>&1 - 922 cat fred.txt - 923 less cleanslate.sh - 924 ./prime multiple-settings set --silent --input settings/organizations.yml 1>>${LOG?} 2>&1 - 925 cat fred.txt - 926 ../gradlew quickRun - 927 ../gradlew composeDownForce - 928 export CREDENTIAL_STORAGE_METHOD="HASHICORP_VAULT" - 929 ../gradlew quickRun - 930 ../gradlew composeDownForce - 931 cd .. - 932 cd .. - 933 ls - 934 mv prime-reportstream prime-reportstream-SAV-1 - 935 exit - 936 cd - 937 cd .gradle - 938 \tls -al - 939 cd .. - 940 mv .gradle .gradle-SAV - 941 cd .gradle - 942 ls -al - 943 cd - 944 cd - 945 cd projects/report-stream/prime-reportstream/prime-router - 946 ../gradlew cleanDB - 947 ../gradlew clearDB - 948 ../gradlew reloadSettings - 949 ../gradlew reloadTables - 950 ../gradlew testEnd2EndUP - 951 ../gradlew clearDB - 952 ../gradlew reloadSettings - 953 ../gradlew reloadTables - 954 ../gradlew testSmoke - 955 less build.gradle.kts - 956 git status - 957 git branch - 958 git checkout -b 16143 origin/main - 959 git fetch -p - 960 git pull - 961 ../gradlew clean build - 962 git fetch -p - 963 git pull - 964 git fetch -p - 965 git pull - 966 docker ps - 967 git fetch -p - 968 exit - 969 env - 970 cd projects/report-stream - 971 ls - 972 history 1 | grep clone - 973 git clone git@github.com:CDCgov/prime-reportstream.git - 974 cd prime-reportstream - 975 cd prime-router - 976 ./cleanslate --verbose - 977 ls - 978 ./cleanslate.sh --verbose - 979 cd .. - 980 cd ./prime-router\n./cleanslate.sh - 981 cd ../.. - 982 rm -rf prime-reportstream - 983 git clone git@github.com:CDCgov/prime-reportstream.git - 984 cd prime-reportstream/prime-router - 985 ./cleanslate --verbose - 986 ./cleanslate.sh --verbose - 987 docker ps - 988 docker compose up --detach vault 1>/dev/null 2>/dev/null - 989 ./gradlew primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" - 990 ../gradlew primeCLI --args "create-credential --type=UserPass --persist=DEFAULT-SFTP --user foo --pass pass" - 991 ../gradlew reloadTables - 992 ../gradlew composeDownForced - 993 ../gradlew quickRun - 994 ../gradlew composeDownForced - 995 ../gradlew quickRun - 996 ../gradlew quickRun - 997 ../gradlew clean build - 998 ../gradlew quickRun - 999 ../gradlew composeDownForced - 1000 exit - 1001 git fetch -p - 1002 git status - 1003 git fetch -p - 1004 history 1 | grep e2e - 1005 history 1 | grep gradlew | sort -U - 1006 history 1 | grep gradlew | sort -u - 1007 history 1 | grep nd - 1008 ../gradlew tasks - 1009 ./gradlew testEnd2EndUP - 1010 ../gradlew testEnd2EndUP - 1011 ../gradlew testSmoke - 1012 history 1 | grep clear - 1013 history 1 | grep reload From 63d36499ec856ebb6714ec76aa3bd95fff3e30e7 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Thu, 5 Dec 2024 09:48:28 -0500 Subject: [PATCH 05/17] [16143] Added additional testing to integration test. --- .../fhirengine/azure/FHIRConverterIntegrationTests.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt index da04315bf38..174bb86c4ee 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt @@ -798,7 +798,7 @@ class FHIRConverterIntegrationTests { ) assertThat(azureEventService.reportStreamEvents[ReportStreamEventName.ITEM_ACCEPTED]!!).hasSize(2) - val event = azureEventService + var event = azureEventService .reportStreamEvents[ReportStreamEventName.ITEM_ACCEPTED]!!.last() as ReportStreamItemEvent assertThat(event.reportEventData).isEqualToIgnoringGivenProperties( ReportEventData( @@ -839,6 +839,15 @@ class FHIRConverterIntegrationTests { ) ) ) + assertThat(azureEventService.reportStreamEvents[ReportStreamEventName.ITEM_TRANSFORMED]!!).hasSize(1) + event = azureEventService + .reportStreamEvents[ReportStreamEventName.ITEM_TRANSFORMED]!!.first() as ReportStreamItemEvent + assertThat(event.reportEventData.parentReportId).isEqualTo(receiveReport.id) + assertThat(event.reportEventData.topic).isEqualTo(Topic.FULL_ELR) + assertThat(event.reportEventData.pipelineStepName).isEqualTo(TaskAction.convert) + assertThat(event.params).hasSize(4) + assertThat(event.params[ReportStreamEventProperties.ORIGINAL_FORMAT]).isEqualTo("FHIR") + assertThat(event.params[ReportStreamEventProperties.TARGET_FORMAT]).isEqualTo("FHIR") } } From 87e3c7a37c056faae00e6f68fcc61f069d6accc4 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Fri, 6 Dec 2024 16:06:01 -0500 Subject: [PATCH 06/17] [16143] Cleanup based on PR review. --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 50 ++++--------------- .../azure/FHIRConverterIntegrationTests.kt | 18 +++---- 2 files changed, 16 insertions(+), 52 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index b4f79187ee1..5b01e8fa6c2 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -325,6 +325,10 @@ class FHIRConverter( // We know from the null check above that this cannot be null val bundle = processedItem.bundle!! transformer?.process(bundle) + logger.info( + "Applied transform - parentReportId=[${input.reportId}]" + + ", childReportId=[], schemaName=[${input.schemaName}]" + ) // make a 'report' val report = Report( @@ -384,7 +388,8 @@ class FHIRConverter( mapOf( ReportStreamEventProperties.BUNDLE_DIGEST to bundleDigestExtractor.generateDigest(processedItem.bundle!!), - ReportStreamEventProperties.ITEM_FORMAT to format + ReportStreamEventProperties.ITEM_FORMAT to format, + ReportStreamEventProperties.ENRICHMENTS to input.schemaName ) ) } @@ -527,48 +532,13 @@ class FHIRConverter( } ) } - } else { - // Generate an ITEM_TRANSFORMED Azure Event. - val bundleDigestExtractor = BundleDigestExtractor( - FhirPathBundleDigestLabResultExtractorStrategy( - CustomContext( - item.bundle!!, - item.bundle!!, - mutableMapOf(), - CustomFhirPathFunctions() - ) - ) - ) - val report = Report( - MimeFormat.FHIR, - emptyList(), - parentItemLineageData = listOf( - Report.ParentItemLineageData(input.reportId, item.index.toInt() + 1) - ), - metadata = this.metadata, - topic = input.topic, - nextAction = TaskAction.none - ) - reportEventService.sendItemEvent( - eventName = ReportStreamEventName.ITEM_TRANSFORMED, - childReport = report, - pipelineStepName = TaskAction.convert - ) { - parentReportId(input.reportId) - params( - mapOf( - ReportStreamEventProperties.BUNDLE_DIGEST - to bundleDigestExtractor.generateDigest(item.bundle!!), - ReportStreamEventProperties.ORIGINAL_FORMAT to format.name, - ReportStreamEventProperties.TARGET_FORMAT to MimeFormat.FHIR.name, - ReportStreamEventProperties.ENRICHMENTS to listOf(input.schemaName) - ) - ) - trackingId(item.bundle!!) - } } } } + logger.info( + "Applied transform - parentReportId=[${input.reportId}]" + + ", childReportId=[], schemaName=[${input.schemaName}]" + ) } item } diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt index 174bb86c4ee..b58057ec07d 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt @@ -508,7 +508,8 @@ class FHIRConverterIntegrationTests { orderingFacilityState = listOf("FL"), performerState = emptyList(), eventType = "ORU^R01^ORU_R01" - ) + ), + ReportStreamEventProperties.ENRICHMENTS to "" ) ) } @@ -663,7 +664,8 @@ class FHIRConverterIntegrationTests { orderingFacilityState = listOf("FL"), performerState = emptyList(), eventType = "ORU^R01^ORU_R01" - ) + ), + ReportStreamEventProperties.ENRICHMENTS to "" ) ) } @@ -836,18 +838,10 @@ class FHIRConverterIntegrationTests { orderingFacilityState = emptyList(), performerState = emptyList(), eventType = "ORU^R01^ORU_R01" - ) + ), + ReportStreamEventProperties.ENRICHMENTS to "" ) ) - assertThat(azureEventService.reportStreamEvents[ReportStreamEventName.ITEM_TRANSFORMED]!!).hasSize(1) - event = azureEventService - .reportStreamEvents[ReportStreamEventName.ITEM_TRANSFORMED]!!.first() as ReportStreamItemEvent - assertThat(event.reportEventData.parentReportId).isEqualTo(receiveReport.id) - assertThat(event.reportEventData.topic).isEqualTo(Topic.FULL_ELR) - assertThat(event.reportEventData.pipelineStepName).isEqualTo(TaskAction.convert) - assertThat(event.params).hasSize(4) - assertThat(event.params[ReportStreamEventProperties.ORIGINAL_FORMAT]).isEqualTo("FHIR") - assertThat(event.params[ReportStreamEventProperties.TARGET_FORMAT]).isEqualTo("FHIR") } } From 466e4d78e78fcf0d4cb44a5f9e9ccefbad7fb30d Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Mon, 9 Dec 2024 14:57:43 -0500 Subject: [PATCH 07/17] [16143] Added code based on PR review. --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 3 ++- .../kotlin/fhirengine/engine/RSMessageType.kt | 11 +++++++++++ .../kotlin/fhirengine/utils/FHIRBundleHelpers.kt | 13 +++++++++++++ .../fhirengine/utils/FHIRBundleHelpersTests.kt | 16 ++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 prime-router/src/main/kotlin/fhirengine/engine/RSMessageType.kt diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index 5b01e8fa6c2..9416be40ad1 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -53,6 +53,7 @@ import gov.cdc.prime.router.fhirengine.utils.FhirTranscoder import gov.cdc.prime.router.fhirengine.utils.HL7Reader import gov.cdc.prime.router.fhirengine.utils.HL7Reader.Companion.parseHL7Message import gov.cdc.prime.router.fhirengine.utils.getObservations +import gov.cdc.prime.router.fhirengine.utils.getRSMessageType import gov.cdc.prime.router.fhirengine.utils.isElr import gov.cdc.prime.router.logging.LogMeasuredTime import gov.cdc.prime.router.report.ReportService @@ -513,7 +514,7 @@ class FHIRConverter( } // 'stamp' observations with their condition code if (item.bundle != null) { - val isElr = item.bundle!!.isElr() + val isElr = if (item.bundle!!.getRSMessageType() == RSMessageType.LAB_RESULT) true else false item.bundle!!.getObservations().forEach { observation -> // Only do this if it is an ELR item. if (isElr) { diff --git a/prime-router/src/main/kotlin/fhirengine/engine/RSMessageType.kt b/prime-router/src/main/kotlin/fhirengine/engine/RSMessageType.kt new file mode 100644 index 00000000000..d1db9dd9d12 --- /dev/null +++ b/prime-router/src/main/kotlin/fhirengine/engine/RSMessageType.kt @@ -0,0 +1,11 @@ +package gov.cdc.prime.router.fhirengine.engine + +/** + * This class represents a way to group message types from an RS perspective. As we add additional logical + * groupings, FHIRBundleHelpers.getRSMessageType will need to be updated. + * + */ +enum class RSMessageType { + LAB_RESULT, + UNKNOWN, +} \ No newline at end of file diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index 0d9f71c49c6..0ab1ac76400 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -9,6 +9,7 @@ import gov.cdc.prime.router.azure.ConditionStamper.Companion.BUNDLE_CODE_IDENTIF import gov.cdc.prime.router.azure.ConditionStamper.Companion.BUNDLE_VALUE_IDENTIFIER import gov.cdc.prime.router.azure.ConditionStamper.Companion.conditionCodeExtensionURL import gov.cdc.prime.router.codes +import gov.cdc.prime.router.fhirengine.engine.RSMessageType import gov.cdc.prime.router.fhirengine.translation.hl7.utils.CustomContext import gov.cdc.prime.router.fhirengine.translation.hl7.utils.FhirPathUtils import gov.cdc.prime.router.fhirengine.utils.FHIRBundleHelpers.Companion.getChildProperties @@ -137,6 +138,18 @@ fun Bundle.isElr(): Boolean { return isElr } +/** + * Return RSMessageType based on grouping logic. + * + * @return RSMessageType of this Bundle. + */ +fun Bundle.getRSMessageType(): RSMessageType { + when { + isElr() -> return RSMessageType.LAB_RESULT + else -> return RSMessageType.UNKNOWN + } +} + /** * Gets all properties for a [Base] resource recursively and filters only its references * diff --git a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt index c22b45fc312..5abc630dc42 100644 --- a/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/utils/FHIRBundleHelpersTests.kt @@ -31,6 +31,7 @@ import gov.cdc.prime.router.azure.ConditionStamper.Companion.conditionCodeExtens import gov.cdc.prime.router.azure.DatabaseAccess import gov.cdc.prime.router.azure.LookupTableConditionMapper import gov.cdc.prime.router.azure.QueueAccess +import gov.cdc.prime.router.fhirengine.engine.RSMessageType import gov.cdc.prime.router.fhirengine.translation.hl7.utils.CustomContext import gov.cdc.prime.router.fhirengine.translation.hl7.utils.FhirPathUtils import gov.cdc.prime.router.metadata.LookupTable @@ -266,6 +267,21 @@ class FHIRBundleHelpersTests { assertThat(fhirBundle.isElr()).isFalse() } + @Test + fun `Test current values for rs message type`() { + val fhirBundle = Bundle() + assertThat(fhirBundle.getRSMessageType()).isEqualTo(RSMessageType.UNKNOWN) + fhirBundle.type = Bundle.BundleType.MESSAGE + val entry = Bundle.BundleEntryComponent() + val messageHeader = MessageHeader() + val event = Coding() + event.code = "R01" + messageHeader.event = event + entry.resource = messageHeader + fhirBundle.entry.add(0, entry) + assertThat(fhirBundle.getRSMessageType()).isEqualTo(RSMessageType.LAB_RESULT) + } + @Test fun `Test find Diagnostic report no observation`() { val actionLogger = ActionLogger() From 270faefd2ead52c8f7f52adc5e2a67a02e04ddd3 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Wed, 11 Dec 2024 08:42:34 -0500 Subject: [PATCH 08/17] [16143] Cleanup from PR review. --- .../main/kotlin/fhirengine/engine/FHIRConverter.kt | 13 +++++++------ .../kotlin/fhirengine/engine/FhirConverterTests.kt | 6 ------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index 9416be40ad1..a3a7121700e 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -326,10 +326,6 @@ class FHIRConverter( // We know from the null check above that this cannot be null val bundle = processedItem.bundle!! transformer?.process(bundle) - logger.info( - "Applied transform - parentReportId=[${input.reportId}]" + - ", childReportId=[], schemaName=[${input.schemaName}]" - ) // make a 'report' val report = Report( @@ -343,6 +339,12 @@ class FHIRConverter( nextAction = TaskAction.destination_filter ) + logger.info( + "Applied transform - parentReportId=[${input.reportId}]" + + ", childReportId=[${report.id}], schemaName=[${input.schemaName}]" + + ", trackingId=[${processedItem.getTrackingId()}]" + ) + // create route event val routeEvent = ProcessEvent( Event.EventAction.DESTINATION_FILTER, @@ -514,9 +516,8 @@ class FHIRConverter( } // 'stamp' observations with their condition code if (item.bundle != null) { - val isElr = if (item.bundle!!.getRSMessageType() == RSMessageType.LAB_RESULT) true else false + val isElr = item.bundle!!.getRSMessageType() == RSMessageType.LAB_RESULT item.bundle!!.getObservations().forEach { observation -> - // Only do this if it is an ELR item. if (isElr) { val result = stamper.stampObservation(observation) if (!result.success) { diff --git a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt index 96015341e88..e23ef1b6e35 100644 --- a/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/engine/FhirConverterTests.kt @@ -646,12 +646,6 @@ class FhirConverterTests { } } -// @Test -// fun `test isElr when bundle is empty`() { -// val emptyBundle = Bundle() -// assertThat(BaseEngine.Companion.isElr(emptyBundle)).isFalse() -// } - @Nested inner class FhirConverterProcessTest { From d8a5314cdbd1147f71e59c9913c5ae64cf414193 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Thu, 12 Dec 2024 14:10:13 -0500 Subject: [PATCH 09/17] [16143] Modification based on review. --- .../src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index 0ab1ac76400..d243a85e593 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -144,9 +144,9 @@ fun Bundle.isElr(): Boolean { * @return RSMessageType of this Bundle. */ fun Bundle.getRSMessageType(): RSMessageType { - when { - isElr() -> return RSMessageType.LAB_RESULT - else -> return RSMessageType.UNKNOWN + return when { + isElr() -> RSMessageType.LAB_RESULT + else -> RSMessageType.UNKNOWN } } From 44d4b603a9134b553050a7371c2da6fd4ac9ab9c Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Thu, 12 Dec 2024 14:35:04 -0500 Subject: [PATCH 10/17] [16143] Modification based on review. --- .../src/main/kotlin/fhirengine/engine/FHIRConverter.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index a3a7121700e..53a4242dfc4 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -537,10 +537,6 @@ class FHIRConverter( } } } - logger.info( - "Applied transform - parentReportId=[${input.reportId}]" + - ", childReportId=[], schemaName=[${input.schemaName}]" - ) } item } From f4b43863e9cf2aada827181d98432d08a34a7ea0 Mon Sep 17 00:00:00 2001 From: Josh Fisk Date: Fri, 13 Dec 2024 09:35:52 -0800 Subject: [PATCH 11/17] Add CP to Extension mappings (#16767) * CPExtension mappings * CPExtension Integration Tests * MOCExtension name change to fit existing patterns --- .../design/design/RS-Extention-Registry.yml | 93 +++++ .../hl7/codesystem/ExtensionUrlMapping.yml | 4 + .../catchall/hl7/datatypes/CP/CPExtension.yml | 103 ++++++ .../MOC/{Extension.yml => MOCExtension.yml} | 0 .../catchall/hl7/segments/IN1/Coverage.yml | 34 +- .../hl7/segments/ORC/OBRExtension.yml | 2 +- .../hl7_mapping/OML_O21/OML_O21-base.yml | 2 +- .../hl7_mapping/OML_O21/OML_O21-test.yml | 2 +- .../hl7_mapping/datatypes/extensionCP/CP.yml | 33 ++ .../hl7_mapping/resources/Coverage/IN1.yml | 28 +- .../mappinginventory/catchall/cp/CPTests.kt | 16 + .../catchall/cp/cp-to-extension.fhir | 195 +++++++++++ .../catchall/cp/cp-to-extension.hl7 | 3 + .../catchall/in1/IN1-to-Coverage.fhir | 323 +++++++++++++++++- .../catchall/in1/IN1-to-Coverage.hl7 | 2 +- .../catchall/omlo21/oml_o21-full.fhir | 216 ++++++++++++ .../catchall/omlo21/oml_o21-full.hl7 | 2 +- 17 files changed, 1042 insertions(+), 16 deletions(-) create mode 100644 prime-router/metadata/HL7/catchall/hl7/datatypes/CP/CPExtension.yml rename prime-router/metadata/HL7/catchall/hl7/datatypes/MOC/{Extension.yml => MOCExtension.yml} (100%) create mode 100644 prime-router/src/main/resources/metadata/hl7_mapping/datatypes/extensionCP/CP.yml create mode 100644 prime-router/src/testIntegration/kotlin/datatests/mappinginventory/catchall/cp/CPTests.kt create mode 100644 prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.fhir create mode 100644 prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.hl7 diff --git a/prime-router/docs/design/design/RS-Extention-Registry.yml b/prime-router/docs/design/design/RS-Extention-Registry.yml index 8b3bb667f28..247103ae682 100644 --- a/prime-router/docs/design/design/RS-Extention-Registry.yml +++ b/prime-router/docs/design/design/RS-Extention-Registry.yml @@ -3418,6 +3418,99 @@ valueType: String hl7Use: XTN.12 +- Resource: Any + FHIR-Type: Extension + HL7-Type: + CP: + Example: + { + "fullUrl": "Coverage/1733795578717198000.8888487d-55f4-4d1d-963d-f8692fc77e9c", + "resource": { + "resourceType": "Coverage", + "id": "1733795578717198000.8888487d-55f4-4d1d-963d-f8692fc77e9c", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.40" + }, + { + "url": "CP.1.1", + "valueDecimal": 33.33 + }, + { + "url": "CP.1.2", + "valueString": "MXN" + }, + { + "url": "CP.2", + "valueString": "P3" + }, + { + "url": "CP.3", + "valueDecimal": 3.003 + }, + { + "url": "CP.4", + "valueDecimal": -3 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + # CWE to CodeableConcept + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] + } + ] + } + } + Extension: + - id: composite-price + url: "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price" + valueType: Extension + hl7Use: NA + extension: + - id: hl7v2Field + url: "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field" + valueType: String + hl7Use: NA + description: Identifies the HL7 field of the data. + - id: cp-price-quantity + url: "CP.1.1" + valueType: Decimal + hl7use: CP.1.1 + - id: cp-price-denomination + url: "CP.1.2" + valueType: String + hl7use: CP.1.2 + - id: cp-price-type + url: "CP.2" + valueType: String + hl7use: CP.2 + - id: cp-from-value + url: "CP.3" + valueType: Decimal + hl7use: CP.3 + - id: cp-to-value + url: "CP.4" + valueType: Decimal + hl7use: CP.4 + - id: cp-range-units + url: "CP.5" + valueType: CodeableConcept + hl7use: CP.5 + - id: cp-range-type + url: "CP.6" + valueType: String + hl7use: CP.6 + - Resource: Any FHIR-Type: MessageHeader.destination HL7-Type: diff --git a/prime-router/metadata/HL7/catchall/hl7/codesystem/ExtensionUrlMapping.yml b/prime-router/metadata/HL7/catchall/hl7/codesystem/ExtensionUrlMapping.yml index 2643e984fed..cc27f956220 100644 --- a/prime-router/metadata/HL7/catchall/hl7/codesystem/ExtensionUrlMapping.yml +++ b/prime-router/metadata/HL7/catchall/hl7/codesystem/ExtensionUrlMapping.yml @@ -65,6 +65,10 @@ - id: "xon-organization" url: "https://reportstream.cdc.gov/fhir/StructureDefinition/xon-organization" +# CP -> Extension +- id: "composite-price" + url: "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price" + # CX -> Identifier - id: "assigning-facility" url: "https://reportstream.cdc.gov/fhir/StructureDefinition/assigning-facility" diff --git a/prime-router/metadata/HL7/catchall/hl7/datatypes/CP/CPExtension.yml b/prime-router/metadata/HL7/catchall/hl7/datatypes/CP/CPExtension.yml new file mode 100644 index 00000000000..ad352c02b56 --- /dev/null +++ b/prime-router/metadata/HL7/catchall/hl7/datatypes/CP/CPExtension.yml @@ -0,0 +1,103 @@ +# $schema: ./../../../../../json_schema/fhir/hl7-to-fhir-mapping-resource-template.json + +url: + type: SYSTEM_URL + value: composite-price + +extension: + expressionType: nested + generateList: true + expressions: + - expressionType: nested + expressionsMap: + url: + type: SYSTEM_URL + value: hl7v2Field + valueString: + type: STRING + expressionType: HL7Spec + valueOf: $cpExtensionName + - expressionType: nested + vars: + cp11: STRING, CP.1 + condition: $cp11 NOT_NULL + expressionsMap: + url: + type: STRING + value: CP.1.1 + valueDecimal: + type: STRING + expressionType: HL7Spec + valueOf: CP.1.1 + - expressionType: nested + vars: + cp12: STRING, CP.1.2 + condition: $cp12 NOT_NULL + expressionsMap: + url: + type: STRING + value: CP.1.2 + valueString: + type: STRING + expressionType: HL7Spec + valueOf: CP.1.2 + - expressionType: nested + vars: + cp2: STRING, CP.2 + condition: $cp2 NOT_NULL + expressionsMap: + url: + type: STRING + valueOf: CP.2 + valueString: + type: STRING + expressionType: HL7Spec + valueOf: CP.2 + - expressionType: nested + vars: + cp3: STRING, CP.3 + condition: $cp3 NOT_NULL + expressionsMap: + url: + type: STRING + valueOf: CP.3 + valueDecimal: + type: STRING + expressionType: HL7Spec + valueOf: CP.3 + - expressionType: nested + vars: + cp4: STRING, CP.4 + condition: $cp4 NOT_NULL + expressionsMap: + url: + type: STRING + valueOf: CP.4 + valueDecimal: + type: STRING + expressionType: HL7Spec + valueOf: CP.4 + - expressionType: nested + vars: + cp5: STRING_ALL, CP.5 + condition: $cp5 NOT_NULL + expressionsMap: + url: + type: STRING + value: CP.5 + valueCodeableConcept: + valueOf: datatypes/CWE/CodeableConcept + specs: CP.5 + expressionType: resource + - expressionType: nested + vars: + cp6: STRING, CP.6 + condition: $cp6 NOT_NULL + expressionsMap: + url: + type: STRING + valueOf: CP.6 + valueString: + type: STRING + expressionType: HL7Spec + valueOf: CP.6 diff --git a/prime-router/metadata/HL7/catchall/hl7/datatypes/MOC/Extension.yml b/prime-router/metadata/HL7/catchall/hl7/datatypes/MOC/MOCExtension.yml similarity index 100% rename from prime-router/metadata/HL7/catchall/hl7/datatypes/MOC/Extension.yml rename to prime-router/metadata/HL7/catchall/hl7/datatypes/MOC/MOCExtension.yml diff --git a/prime-router/metadata/HL7/catchall/hl7/segments/IN1/Coverage.yml b/prime-router/metadata/HL7/catchall/hl7/segments/IN1/Coverage.yml index 8479f85f8bc..c4bfd5d0c1b 100644 --- a/prime-router/metadata/HL7/catchall/hl7/segments/IN1/Coverage.yml +++ b/prime-router/metadata/HL7/catchall/hl7/segments/IN1/Coverage.yml @@ -13,4 +13,36 @@ extension: expressions: - expressionType: resource valueOf: datatypes/AUI/AUIExtension - specs: IN1.14 \ No newline at end of file + specs: IN1.14 + - expressionType: resource + vars: + in137: STRING, IN1.37 + condition: $in137 NOT_NULL + valueOf: datatypes/CP/CPExtension + constants: + cpExtensionName: IN1.37 + specs: IN1.37 + - expressionType: resource + vars: + in138: STRING, IN1.38 + condition: $in138 NOT_NULL + valueOf: datatypes/CP/CPExtension + constants: + cpExtensionName: IN1.38 + specs: IN1.38 + - expressionType: resource + vars: + in140: STRING, IN1.40 + condition: $in140 NOT_NULL + valueOf: datatypes/CP/CPExtension + constants: + cpExtensionName: IN1.40 + specs: IN1.40 + - expressionType: resource + vars: + in141: STRING, IN1.41 + condition: $in141 NOT_NULL + valueOf: datatypes/CP/CPExtension + constants: + cpExtensionName: IN1.41 + specs: IN1.41 diff --git a/prime-router/metadata/HL7/catchall/hl7/segments/ORC/OBRExtension.yml b/prime-router/metadata/HL7/catchall/hl7/segments/ORC/OBRExtension.yml index c2509802ecf..78c9142b244 100644 --- a/prime-router/metadata/HL7/catchall/hl7/segments/ORC/OBRExtension.yml +++ b/prime-router/metadata/HL7/catchall/hl7/segments/ORC/OBRExtension.yml @@ -335,7 +335,7 @@ extension: expressionType: HL7Spec valueOf: OBR.22 - expressionType: resource - valueOf: datatypes/MOC/Extension + valueOf: datatypes/MOC/MOCExtension vars: obr23: STRING_ALL, OBR.23 condition: $obr23 NOT_NULL diff --git a/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-base.yml b/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-base.yml index 305e890b694..5038b8227fa 100644 --- a/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-base.yml +++ b/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-base.yml @@ -1,6 +1,6 @@ # $schema: ./../../../../../../metadata/json_schema/fhir/fhir-to-hl7-mapping.json -hl7Class: ca.uhn.hl7v2.model.v27.message.OML_O21 +hl7Class: fhirengine.translation.hl7.structures.fhirinventory.message.OML_O21 constants: # Prefix for RS custom extension URLs diff --git a/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-test.yml b/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-test.yml index d9c02000ec8..5dda094bd39 100644 --- a/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-test.yml +++ b/prime-router/src/main/resources/metadata/hl7_mapping/OML_O21/OML_O21-test.yml @@ -1,6 +1,6 @@ # $schema: ./../../../../../../metadata/json_schema/fhir/fhir-to-hl7-mapping.json -hl7Class: ca.uhn.hl7v2.model.v27.message.OML_O21 +hl7Class: fhirengine.translation.hl7.structures.fhirinventory.message.OML_O21 extends: classpath:/metadata/hl7_mapping/OML_O21/OML_O21-base.yml elements: diff --git a/prime-router/src/main/resources/metadata/hl7_mapping/datatypes/extensionCP/CP.yml b/prime-router/src/main/resources/metadata/hl7_mapping/datatypes/extensionCP/CP.yml new file mode 100644 index 00000000000..12df1c0bab0 --- /dev/null +++ b/prime-router/src/main/resources/metadata/hl7_mapping/datatypes/extensionCP/CP.yml @@ -0,0 +1,33 @@ +# $schema: ./../../../../../../../metadata/json_schema/fhir/fhir-to-hl7-mapping.json + +elements: + + - name: cp-price-quantity + value: [ '%resource.extension.where(url = "CP.1.1").value' ] + hl7Spec: [ '%{cpField}-1-1' ] + + - name: cp-price-denomination + value: [ '%resource.extension.where(url = "CP.1.2").value' ] + hl7Spec: [ '%{cpField}-1-2' ] + + - name: cp-price-type + value: [ '%resource.extension.where(url = "CP.2").value' ] + hl7Spec: [ '%{cpField}-2' ] + + - name: cp-from-value + value: [ '%resource.extension.where(url = "CP.3").value' ] + hl7Spec: [ '%{cpField}-3' ] + + - name: cp-to-value + value: [ '%resource.extension.where(url = "CP.4").value' ] + hl7Spec: [ '%{cpField}-4' ] + + - name: cp-range-units + resource: '%resource.extension.where(url = "CP.5").value' + schema: classpath:/metadata/hl7_mapping/datatypes/codeableConcept/CWE.yml + constants: + cweField: '%{cpField}-5' + + - name: cp-range-type + value: [ '%resource.extension.where(url = "CP.6").value' ] + hl7Spec: [ '%{cpField}-6' ] diff --git a/prime-router/src/main/resources/metadata/hl7_mapping/resources/Coverage/IN1.yml b/prime-router/src/main/resources/metadata/hl7_mapping/resources/Coverage/IN1.yml index fe437d13fce..b412907a538 100644 --- a/prime-router/src/main/resources/metadata/hl7_mapping/resources/Coverage/IN1.yml +++ b/prime-router/src/main/resources/metadata/hl7_mapping/resources/Coverage/IN1.yml @@ -5,8 +5,32 @@ constants: elements: - - name: aui-extension + - name: in1-authorization-information resource: '%resource.extension.where(url = "IN1.14")' schema: classpath:/metadata/hl7_mapping/datatypes/extensionAUI/AUI.yml constants: - auiField: '%{hl7IN1Field}-14' \ No newline at end of file + auiField: '%{hl7IN1Field}-14' + + - name: in1-policy-deductable + resource: '%resource.extension(%`rsext-composite-price`).where(extension(%`rsext-hl7v2Field`).value = "IN1.37")' + schema: classpath:/metadata/hl7_mapping/datatypes/extensionCP/CP.yml + constants: + cpField: '%{hl7IN1Field}-37' + + - name: in1-policy-limit-amount + resource: '%resource.extension(%`rsext-composite-price`).where(extension(%`rsext-hl7v2Field`).value = "IN1.38")' + schema: classpath:/metadata/hl7_mapping/datatypes/extensionCP/CP.yml + constants: + cpField: '%{hl7IN1Field}-38' + + - name: in1-room-rate-semi-private + resource: '%resource.extension(%`rsext-composite-price`).where(extension(%`rsext-hl7v2Field`).value = "IN1.40")' + schema: classpath:/metadata/hl7_mapping/datatypes/extensionCP/CP.yml + constants: + cpField: '%{hl7IN1Field}-40' + + - name: in1-room-rate-private + resource: '%resource.extension(%`rsext-composite-price`).where(extension(%`rsext-hl7v2Field`).value = "IN1.41")' + schema: classpath:/metadata/hl7_mapping/datatypes/extensionCP/CP.yml + constants: + cpField: '%{hl7IN1Field}-41' diff --git a/prime-router/src/testIntegration/kotlin/datatests/mappinginventory/catchall/cp/CPTests.kt b/prime-router/src/testIntegration/kotlin/datatests/mappinginventory/catchall/cp/CPTests.kt new file mode 100644 index 00000000000..6fa650b9945 --- /dev/null +++ b/prime-router/src/testIntegration/kotlin/datatests/mappinginventory/catchall/cp/CPTests.kt @@ -0,0 +1,16 @@ +package gov.cdc.prime.router.datatests.mappinginventory.cp + +import gov.cdc.prime.router.datatests.mappinginventory.verifyHL7ToFHIRToHL7Mapping +import org.junit.jupiter.api.Test + +class CPTests { + @Test + fun `test CP mapped to CPExtension`() { + assert( + verifyHL7ToFHIRToHL7Mapping( + "catchall/cp/cp-to-extension", + outputSchema = "classpath:/metadata/hl7_mapping/OML_O21/OML_O21-test.yml" + ).passed + ) + } +} \ No newline at end of file diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.fhir b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.fhir new file mode 100644 index 00000000000..86c2f6a5a65 --- /dev/null +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.fhir @@ -0,0 +1,195 @@ +{ + "resourceType": "Bundle", + "id": "1733797768446514000.f1548dec-5abc-4302-9b8d-59f755ec9b2f", + "meta": { + "lastUpdated": "2024-12-09T18:29:28.450-08:00" + }, + "identifier": { + "system": "https://reportstream.cdc.gov/prime-router", + "value": "MSG00001" + }, + "type": "message", + "entry": [ + { + "fullUrl": "MessageHeader/1733797768476500000.9c68bbf7-cd15-490d-a357-ac0d515575f8", + "resource": { + "resourceType": "MessageHeader", + "id": "1733797768476500000.9c68bbf7-cd15-490d-a357-ac0d515575f8", + "meta": { + "tag": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0103", + "code": "P" + } + ] + }, + "eventCoding": { + "system": "http://terminology.hl7.org/CodeSystem/v2-0003", + "code": "O21", + "display": "OML^O21^OML_O21" + } + } + }, + { + "fullUrl": "Provenance/1733797768760500000.23e4e2bd-4532-468d-89ec-e012d5702477", + "resource": { + "resourceType": "Provenance", + "id": "1733797768760500000.23e4e2bd-4532-468d-89ec-e012d5702477", + "activity": { + "coding": [ + { + "display": "OML^O21^OML_O21" + } + ] + } + } + }, + { + "fullUrl": "Provenance/1733797768767441000.19ac0704-100d-4d66-8cb9-3094fba92b95", + "resource": { + "resourceType": "Provenance", + "id": "1733797768767441000.19ac0704-100d-4d66-8cb9-3094fba92b95", + "recorded": "2024-12-09T18:29:28Z", + "policy": [ + "http://hl7.org/fhir/uv/v2mappings/message-oru-r01-to-bundle" + ], + "activity": { + "coding": [ + { + "code": "v2-FHIR transformation" + } + ] + }, + "agent": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/provenance-participant-type", + "code": "assembler" + } + ] + }, + "who": { + "reference": "Organization/1733797768766853000.2f23f653-749b-4b43-b159-d1d955375f3a" + } + } + ] + } + }, + { + "fullUrl": "Organization/1733797768766853000.2f23f653-749b-4b43-b159-d1d955375f3a", + "resource": { + "resourceType": "Organization", + "id": "1733797768766853000.2f23f653-749b-4b43-b159-d1d955375f3a", + "identifier": [ + { + "value": "CDC PRIME - Atlanta" + }, + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0301" + } + ] + }, + "system": "urn:ietf:rfc:3986", + "value": "2.16.840.1.114222.4.1.237821" + } + ] + } + }, + { + "fullUrl": "Patient/1733797768779870000.bb1ddb84-5fa1-484f-96a4-4616988212fc", + "resource": { + "resourceType": "Patient", + "id": "1733797768779870000.bb1ddb84-5fa1-484f-96a4-4616988212fc" + } + }, + { + "fullUrl": "Provenance/1733797768780413000.e0ff5861-fd54-4149-8ee0-415a1dcc9123", + "resource": { + "resourceType": "Provenance", + "id": "1733797768780413000.e0ff5861-fd54-4149-8ee0-415a1dcc9123", + "target": [ + { + "reference": "Patient/1733797768779870000.bb1ddb84-5fa1-484f-96a4-4616988212fc" + } + ], + "recorded": "2024-12-09T18:29:28Z", + "activity": { + "coding": [ + { + "system": "https://terminology.hl7.org/CodeSystem/v3-DataOperation", + "code": "UPDATE" + } + ] + } + } + }, + { + "fullUrl": "Coverage/1733797768783117000.2931a2e0-097c-481f-9adf-46e114f827b2", + "resource": { + "resourceType": "Coverage", + "id": "1733797768783117000.2931a2e0-097c-481f-9adf-46e114f827b2", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.40" + }, + { + "url": "CP.1.1", + "valueDecimal": 33.33 + }, + { + "url": "CP.1.2", + "valueString": "MXN" + }, + { + "url": "CP.2", + "valueString": "P3" + }, + { + "url": "CP.3", + "valueDecimal": 3.003 + }, + { + "url": "CP.4", + "valueDecimal": -3 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "OR", + "display": "Oven Range" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] + } + ] + } + } + ] +} \ No newline at end of file diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.hl7 b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.hl7 new file mode 100644 index 00000000000..be3735df492 --- /dev/null +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/cp/cp-to-extension.hl7 @@ -0,0 +1,3 @@ +MSH|^~\&|||||||OML^O21^OML_O21|MSG00001|P|2.5.1 +PID|1 +IN1||||||||||||||||||||||||||||||||||||||||33.33&MXN^P3^3.003^-3^OR&Oven Range&HL79999^P \ No newline at end of file diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.fhir b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.fhir index bac350c4bb3..c341f40f512 100644 --- a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.fhir +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.fhir @@ -1,8 +1,8 @@ { "resourceType": "Bundle", - "id": "1732324230716018000.38edba19-1d39-4040-85af-9f5f6248813c", + "id": "1733797806213402000.63933238-a67a-4568-8544-178612c57351", "meta": { - "lastUpdated": "2024-11-22T17:10:30.720-08:00" + "lastUpdated": "2024-12-09T18:30:06.217-08:00" }, "identifier": { "system": "https://reportstream.cdc.gov/prime-router", @@ -11,10 +11,10 @@ "type": "message", "entry": [ { - "fullUrl": "MessageHeader/1732324230752828000.fc7cea9d-d7ca-4378-91d4-ea97c86b4787", + "fullUrl": "MessageHeader/1733797806248346000.554ce0a6-e3fb-4b4e-b8e2-c111f8944cd5", "resource": { "resourceType": "MessageHeader", - "id": "1732324230752828000.fc7cea9d-d7ca-4378-91d4-ea97c86b4787", + "id": "1733797806248346000.554ce0a6-e3fb-4b4e-b8e2-c111f8944cd5", "meta": { "tag": [ { @@ -31,17 +31,108 @@ } }, { - "fullUrl": "Patient/1732324231018814000.533db9a5-5375-4746-be23-f7140d4a3280", + "fullUrl": "Provenance/1733797806498618000.239e218a-0960-4528-939e-5ee68bfbba1d", + "resource": { + "resourceType": "Provenance", + "id": "1733797806498618000.239e218a-0960-4528-939e-5ee68bfbba1d", + "activity": { + "coding": [ + { + "display": "OML^O21^OML_O21" + } + ] + } + } + }, + { + "fullUrl": "Provenance/1733797806506657000.35b16b0c-d80a-4017-8cad-868a79863b64", + "resource": { + "resourceType": "Provenance", + "id": "1733797806506657000.35b16b0c-d80a-4017-8cad-868a79863b64", + "recorded": "2024-12-09T18:30:06Z", + "policy": [ + "http://hl7.org/fhir/uv/v2mappings/message-oru-r01-to-bundle" + ], + "activity": { + "coding": [ + { + "code": "v2-FHIR transformation" + } + ] + }, + "agent": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/provenance-participant-type", + "code": "assembler" + } + ] + }, + "who": { + "reference": "Organization/1733797806506092000.a6f8b4f5-e971-4ee2-8891-8b67af7df93d" + } + } + ] + } + }, + { + "fullUrl": "Organization/1733797806506092000.a6f8b4f5-e971-4ee2-8891-8b67af7df93d", + "resource": { + "resourceType": "Organization", + "id": "1733797806506092000.a6f8b4f5-e971-4ee2-8891-8b67af7df93d", + "identifier": [ + { + "value": "CDC PRIME - Atlanta" + }, + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0301" + } + ] + }, + "system": "urn:ietf:rfc:3986", + "value": "2.16.840.1.114222.4.1.237821" + } + ] + } + }, + { + "fullUrl": "Patient/1733797806517233000.6ddc53a3-0587-4db5-8c73-5b6634eb1369", "resource": { "resourceType": "Patient", - "id": "1732324231018814000.533db9a5-5375-4746-be23-f7140d4a3280" + "id": "1733797806517233000.6ddc53a3-0587-4db5-8c73-5b6634eb1369" } }, { - "fullUrl": "Coverage/1732324231019741000.a36368bf-6c63-4970-8948-034a92248964", + "fullUrl": "Provenance/1733797806517793000.28f02504-824d-4c22-a6a1-e234b3affd5f", + "resource": { + "resourceType": "Provenance", + "id": "1733797806517793000.28f02504-824d-4c22-a6a1-e234b3affd5f", + "target": [ + { + "reference": "Patient/1733797806517233000.6ddc53a3-0587-4db5-8c73-5b6634eb1369" + } + ], + "recorded": "2024-12-09T18:30:06Z", + "activity": { + "coding": [ + { + "system": "https://terminology.hl7.org/CodeSystem/v3-DataOperation", + "code": "UPDATE" + } + ] + } + } + }, + { + "fullUrl": "Coverage/1733797806523309000.c5403041-1e4b-4f81-bc46-f16237041fec", "resource": { "resourceType": "Coverage", - "id": "1732324231019741000.a36368bf-6c63-4970-8948-034a92248964", + "id": "1733797806523309000.c5403041-1e4b-4f81-bc46-f16237041fec", "extension": [ { "url": "IN1.14", @@ -59,6 +150,222 @@ "valueString": "DR TEETH AND THE ELECTRIC MAYHEM" } ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.37" + }, + { + "url": "CP.1.1", + "valueDecimal": 11.11 + }, + { + "url": "CP.1.2", + "valueString": "USD" + }, + { + "url": "CP.2", + "valueString": "P1" + }, + { + "url": "CP.3", + "valueDecimal": 1.001 + }, + { + "url": "CP.4", + "valueDecimal": -1 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "R", + "display": "Range Units" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "F" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.38" + }, + { + "url": "CP.1.1", + "valueDecimal": 22.22 + }, + { + "url": "CP.1.2", + "valueString": "RUB" + }, + { + "url": "CP.2", + "valueString": "P2" + }, + { + "url": "CP.3", + "valueDecimal": 2.002 + }, + { + "url": "CP.4", + "valueDecimal": -2 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "RR", + "display": "Russian Rubble" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "F" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.40" + }, + { + "url": "CP.1.1", + "valueDecimal": 33.33 + }, + { + "url": "CP.1.2", + "valueString": "MXN" + }, + { + "url": "CP.2", + "valueString": "P3" + }, + { + "url": "CP.3", + "valueDecimal": 3.003 + }, + { + "url": "CP.4", + "valueDecimal": -3 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "OR", + "display": "Oven Range" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.41" + }, + { + "url": "CP.1.1", + "valueDecimal": 44.44 + }, + { + "url": "CP.1.2", + "valueString": "CAD" + }, + { + "url": "CP.2", + "valueString": "P4" + }, + { + "url": "CP.3", + "valueDecimal": 4.004 + }, + { + "url": "CP.4", + "valueDecimal": -4 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "HHR", + "display": "Home Home Range" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] } ] } diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.hl7 b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.hl7 index 6d424a80fa2..0279bf1db76 100644 --- a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.hl7 +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/in1/IN1-to-Coverage.hl7 @@ -1,3 +1,3 @@ MSH|^~\&|||||||OML^O21^OML_O21|MSG00001|P|2.5.1 PID|1 -IN1||||||||||||||1701^19700101^DR TEETH AND THE ELECTRIC MAYHEM \ No newline at end of file +IN1||||||||||||||1701^19700101^DR TEETH AND THE ELECTRIC MAYHEM|||||||||||||||||||||||11.11&USD^P1^1.001^-1^R&Range Units&HL79999^F|22.22&RUB^P2^2.002^-2^RR&Russian Rubble&HL79999^F||33.33&MXN^P3^3.003^-3^OR&Oven Range&HL79999^P|44.44&CAD^P4^4.004^-4^HHR&Home Home Range&HL79999^P \ No newline at end of file diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.fhir b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.fhir index 214a988f494..d24dfe4dad2 100644 --- a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.fhir +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.fhir @@ -13262,6 +13262,222 @@ "valueString": "DR TEETH AND THE ELECTRIC MAYHEM" } ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.37" + }, + { + "url": "CP.1.1", + "valueDecimal": 11.11 + }, + { + "url": "CP.1.2", + "valueString": "USD" + }, + { + "url": "CP.2", + "valueString": "P1" + }, + { + "url": "CP.3", + "valueDecimal": 1.001 + }, + { + "url": "CP.4", + "valueDecimal": -1 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "R", + "display": "Range Units" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "F" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.38" + }, + { + "url": "CP.1.1", + "valueDecimal": 22.22 + }, + { + "url": "CP.1.2", + "valueString": "RUB" + }, + { + "url": "CP.2", + "valueString": "P2" + }, + { + "url": "CP.3", + "valueDecimal": 2.002 + }, + { + "url": "CP.4", + "valueDecimal": -2 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "RR", + "display": "Russian Rubble" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "F" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.40" + }, + { + "url": "CP.1.1", + "valueDecimal": 33.33 + }, + { + "url": "CP.1.2", + "valueString": "MXN" + }, + { + "url": "CP.2", + "valueString": "P3" + }, + { + "url": "CP.3", + "valueDecimal": 3.003 + }, + { + "url": "CP.4", + "valueDecimal": -3 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "OR", + "display": "Oven Range" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/composite-price", + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/hl7v2Field", + "valueString": "IN1.41" + }, + { + "url": "CP.1.1", + "valueDecimal": 44.44 + }, + { + "url": "CP.1.2", + "valueString": "CAD" + }, + { + "url": "CP.2", + "valueString": "P4" + }, + { + "url": "CP.3", + "valueDecimal": 4.004 + }, + { + "url": "CP.4", + "valueDecimal": -4 + }, + { + "url": "CP.5", + "valueCodeableConcept": { + "coding": [ + { + "extension": [ + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding", + "valueString": "coding" + }, + { + "url": "https://reportstream.cdc.gov/fhir/StructureDefinition/cwe-coding-system", + "valueString": "HL79999" + } + ], + "code": "HHR", + "display": "Home Home Range" + } + ] + } + }, + { + "url": "CP.6", + "valueString": "P" + } + ] } ] } diff --git a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.hl7 b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.hl7 index 23863a51bb8..baa36fced05 100644 --- a/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.hl7 +++ b/prime-router/src/testIntegration/resources/datatests/mappinginventory/catchall/omlo21/oml_o21-full.hl7 @@ -8,7 +8,7 @@ NK1|1|SURYAN&Prefix&Own&SpousePrefix&Spouse^GENARO^GR^JR^Sir^Md^L^I^CON&Context NK1|2|SUPERMAN&Prefix&Own&SpousePrefix&Spouse^GENARO^GR^JR^Sir^Md^L^I^CON&Context the namee&HL70448^2000&2030^G^20000501102531^2030501102531^Dr|OTH^Other^HL70063^OT^OTHER RELATIONSHIP^L|4861 20TH AVE^^THUNDER MOUNTAIN^IG^99999^USA^H|^PRN^PH^example2@exmaple.com^1^720^5553954^2^any^^^+1 720 555 3955|^WPN^PH^^1^555^4672293^^^^^+1 555 467 2294|F^Federal Agency^HL70131|20220501102531-0400|20230501102531-0400|||052479^^^^^^20160822|HospitalsRUs^^112233^^^^^^^HRU||N^Not Applicable^HL70001|19860505||||E^English^HL70296|||||||||||^WPN^PH^^1^720^5553954^^^^^+1 720 555 3955|4861 20TH AVE^#B^AURORA^IG^99999^USA^H^World^King^12^8^2017&2025^2020^2021|052479^^^^^^^20210428|||||||^VHN^SAT^^1^314^5553131^^^^^+1 314 555 3132|^AWN^FX^^1^281^5558181^^^^^+1 281 555 8182 PV1|1|O|A&Point OF Care&C^1&Room&3^B&Bed&A^Hospital Assigned&2.4.4.4&ISO^^R^&Building^&Floor^Totally A Real Location^Comprehensive&&UID4This^AA&AssigningAUTH&ISO|R^Routine^HL70007|232323|^^^Hospital Prio&2.4.4.4&ISO^active^location type^^^Description^Entity ID&NAME&UNI&ISO^ASSIGNEE&222.1111.22222&UUID|1^BEETHOVEN^LUDWIG^B^2ND^DR^MD^^Namespace&AssigningSystem&UUID^B^^^DL^^^^^^^^MD~1^BEETHOVEN2^LUDWIG^B^2ND^DR^MD^^Namespace&AssigningSystem&UUID^B^^^DL^^^^^^^^MD|1^MOZART~1^MOZARTJR|1^CHOPIN~1^CHOPINSR|URO^Urology Service^HL70069|^^^^^^^^Its Temporary|P^Passed^HL70087|R^Re-admission^HL70092|RL^Real Life^HL70023||VIP^Very Interesting Person^HL70099|1^BACH~1^BACHtheSecond|H^Human Patient^HL70018|22|||||||||||20020101|C^Collectors^HL70021|1|0|Y^Yes^HL70111|20080101|H^Happy^HL70112|^202305061200|F^Fed^HL70114|H^A Hospital Of Course^HL70115||A^Active^HL70117|^^^^^^^^Pending Location|^^^^^^^^Prior Location|20240801102531-0400|20240801102531-0400|100|199|142|130|alternate visit|A^Account Level^HL70326||Service Description|episode identifier PV2|^^^Hospital PriorPending&2.4.4.4&ISO^active^location type^^^Description^Entity ID&NAME&UNI&ISO^ASSIGNEE&222.1111.22222&UUID||1^AD||||413^V~423^X|20230601102531-0400|20230701102531-0400|5|12|Description|1^BEETHOVEN&VAN&Referral Source Code1&VAL&ROGER^LUDWIG^B^2ND^DR^MD^SRC^&AssigningSystem&ISO^B^A^NPI^DL^^A^NameContext^^G^20220501102531-0400^20230501102531-0400^MD^AssignJ^AssignA~1^BEETHOVEN&VAN&Referral Source Code2&VAL&ROGER^LUDWIG^B^2ND^DR^MD^SRC^&AssigningSystem&ISO^B^A^NPI^DL^^A^NameContext^^G^20220501102531-0400^20230501102531-0400^MD^AssignJ^AssignA||EMP_ILL||||||100^PublicCode|SEC|Org1^1234-5&TestText&LN&1234-5&TestAltText&LN&1&2&OriginalText^123^Check Digit^C1^Assigning Authority&2.1.4.1&ISO^MD^Hospital A&2.16.840.1.113883.9.11&ISO~Org2^1234-5&TestText&LN&1234-5&TestAltText&LN&1&2&OriginalText^123^Check Digit^C1^Assigning Authority&2.1.4.1&ISO^MD^Hospital A&2.16.840.1.113883.9.11&ISO||3^Elective^HL70217|20230501102531-0400|||20220501102531-0400|||||||||444^MODE||123^CARELEVEL1 -IN1||||||||||||||1701^19700101^DR TEETH AND THE ELECTRIC MAYHEM +IN1||||||||||||||1701^19700101^DR TEETH AND THE ELECTRIC MAYHEM|||||||||||||||||||||||11.11&USD^P1^1.001^-1^R&Range Units&HL79999^F|22.22&RUB^P2^2.002^-2^RR&Russian Rubble&HL79999^F||33.33&MXN^P3^3.003^-3^OR&Oven Range&HL79999^P|44.44&CAD^P4^4.004^-4^HHR&Home Home Range&HL79999^P ORC|RE|Specimen123^SPHL-000048^2.16.840.1.114222.4.1.10765^ISO|Specimen12311^SPHL-000048^2.16.840.1.114222.4.1.10765^ISO|Specimen12322^SPHL-000048^2.16.840.1.114222.4.1.10765^ISO|CM|E||Specimen12333&SPHL-000048&2.16.840.1.114222.4.1.10765&ISO^Specimen12333454&SPHL-000048&2.16.840.1.114222.4.1.10765&ISO|20230725|71^^ORC.10Name~71^^ORC.10Name2|82^^ORC.11Name~82^^ORC.11Name2|93^^ORC.12Name~93^^ORC.12Name2|12.12.12&enter location id&L|123^^^+123~1234^^^+1234|202101021000||EO^entering org text^HL79999|ED^entering device text^HL79999|60^^ORC.19Name~60^^ORC.19Name2||CDPH, Viral and Rickettsial Disease Laboratory^^^^^STARLIMS.CDC.Stag&2.16.840.1.114222.4.3.3.2.1.2&ISO^XX^STARLINKS.CDC.Stag&2.16.840.1.114222.8.7.6.5.4.1&ISO^A^SPHL-000048~CDPH, Viral and Rickettsial Disease Laboratory part two^^^^^STARLIMS.CDC.Stag&2.16.840.1.114222.4.3.3.2.1.2&ISO|111 Street St^^Streetsville^ST~112 Street St^^Streetsville^ST|456^^^+456~4567^^^+4567|111 Road Rd^^Roadsville^RD~112 Road Rd^^Roadsville^RD|OS^order status^HL79999||20260404|EMP^Employee^HL70177|I^Inpatient Order^HL70482|EL^Electronic^HL70483|UMM^Universal Modifier^HL70000|20250403|33~332 OBR|1|Placer Identifier^Placer Identifier Namespace^Placer Universal ID^ISO|Filler Identifier^Filler Identifier Namespace^Filler Universal ID^ISO|123^Universal service identifier||202202021022||20240220|1771|1^Collector&VAN&Identifier&VAL&ROGER^LUDWIG^B^2ND^DR^MD^SRC^&AssigningSystem&ISO^B^A^NPI^DL^^A^NameContext~1^Collectorx2&VAN&Identifier&VAL&ROGER^LUDWIG^B^2ND^DR^MD^SRC^&AssigningSystem&ISO^B^A^NPI^DL^^A^NameContext|G|512^Danger code|R^relevent info^ISO|202102021000|ID^BOUIN&Bouin's solution&HL70371^Collection Method^LN&Left Naris&HL70163^^CMMC&Collection Method Modifer Code&HL7|1^Ordering&VAN&Provider&VAL&JollyROGER~2^Ordering&VAN&Provider&VAL&JollyROGER|^WPN^BP^^1^260^7595016^^^^^+1 260 759 5016~^WPN^Internet^order.callback@email.com~^WPN^BP^^1^260^7595016^^^^^+1 260 759 5016~^WPN^Internet^order.callback2@email.com|placer1|placer2|filler1|filler2||100&$^16&code|OTH|F|444&ParentId^888^ParentOBSdescriptor||1^result&VAN&copiesto&VAL&NotSoJollyROGER~2^results&VAN&copiesto&VAL&NotSoJollyROGER|adb4a5cc-50ec-4f1e-95d7-0c1f77cacee1&CSV&11D1111111&CLIA^f34b0f57-1601-4480-ae8a-d4006e50f38d&Other CSV&22D2222222&CLIA2||3216^ReasonForStudy~3216^ReasonForStudy2||123&Assistant&Results Interpreter&S&ESQ&DR&MD&&Assigning Authority&2.1.4.1&ISO^20230401102531-0400^20230501102531-0400^Point of Care^Room 101^Bed A^Hospital A&2.16.840.1.113883.9.11&ISO^active^^Building 123^Floor A~123&Assistant&Results Interpreter&S&ESQ&DR&MD&&Assigning Authority&2.1.4.1&ISO^20230401102531-0400^20230501102531-0400^Point of Care^Room 101^Bed A^Hospital A&2.16.840.1.113883.9.11&ISO^active^^Building 123^Floor A|||20230806123359-0500|||4438^Collectors Comment~4438^Collectors Comment2|||||5019^Procedure Code|887766^Procedure Code Modifier~887766^Procedure Code Modifier2|7461^Placer Supplemental~7461^Placer Supplemental2|8811^Fillter Supplemental~8811^Fillter Supplemental2|71435^Medically Necessary Duplicate Procedure|N|443331^Parent Universal Service Identifier|||Alt^Placer Order~Alt^Placer Order2|adb4a5cc-50ec-4f1e-95d7-0c1f77cacee1&CSV&11D1111111&CLIA^f34b0f57-1601-4480-ae8a-d4006e50f38d&Other CSV&22D2222222&CLIA2 NTE|1|L|Note about the observation request~second~third~fourth|||20230207|20230208|20230209|CC^Coded Request note From 426d4d66a12325c9962c8aa621ed42255441b3e0 Mon Sep 17 00:00:00 2001 From: Bill Cutshall Date: Fri, 13 Dec 2024 14:02:40 -0500 Subject: [PATCH 12/17] [16143] Changes from feedback in PR review. --- .../fhirengine/utils/FHIRBundleHelpers.kt | 22 ++++++++++--------- .../common/UniversalPipelineTestUtils.kt | 15 +------------ .../azure/FHIRConverterIntegrationTests.kt | 12 +++++----- .../FHIRReceiverFilterIntegrationTests.kt | 2 +- 4 files changed, 20 insertions(+), 31 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index d243a85e593..c6a7633740e 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -16,12 +16,12 @@ import gov.cdc.prime.router.fhirengine.utils.FHIRBundleHelpers.Companion.getChil import io.github.linuxforhealth.hl7.data.Hl7RelatedGeneralUtils import org.hl7.fhir.r4.model.Base import org.hl7.fhir.r4.model.Bundle +import org.hl7.fhir.r4.model.CodeType import org.hl7.fhir.r4.model.CodeableConcept import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.DateTimeType import org.hl7.fhir.r4.model.DiagnosticReport import org.hl7.fhir.r4.model.Extension -import org.hl7.fhir.r4.model.MessageHeader import org.hl7.fhir.r4.model.Observation import org.hl7.fhir.r4.model.Patient import org.hl7.fhir.r4.model.Property @@ -125,15 +125,17 @@ fun Bundle.addProvenanceReference() { */ fun Bundle.isElr(): Boolean { var isElr = false - if (this.type == Bundle.BundleType.MESSAGE && this.entry.isNotEmpty()) { - // By rule, the first entry must be a MessageHeader - val resource = this.entry[0].resource - if (resource is MessageHeader) { - val event = resource.event - if (event is Coding && ((event.code == "R01") || (event.code == "ORU_R01"))) { - isElr = true - } - } + val code = FhirPathUtils.evaluate( + null, + this, + this, + "Bundle.entry.resource.ofType(MessageHeader).event.code" + ) + .filterIsInstance() + .firstOrNull() + ?.code + if (code != null && ((code == "R01") || (code == "ORU_R01"))) { + isElr = true } return isElr } diff --git a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt index 7380c6a2974..a61f5b13d86 100644 --- a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt +++ b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt @@ -40,28 +40,15 @@ import java.time.OffsetDateTime @Suppress("ktlint:standard:max-line-length") const val validFHIRRecord1 = - """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" -const val validFHIRRecord1Identifier = "1234d1d1-95fe-462c-8ac6-46728dba581c" - -@Suppress("ktlint:standard:max-line-length") -const val validFHIRRecord1a = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" -const val validFHIRRecord1aIdentifier = "1234d1d1-95fe-462c-8ac6-46728dba581c" +const val validFHIRRecord1Identifier = "1234d1d1-95fe-462c-8ac6-46728dba581c" @Suppress("ktlint:standard:max-line-length") const val conditionCodedValidFHIRRecord1 = - """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/condition-code","valueCoding":{"system":"SNOMEDCT","code":"6142004","display":"Influenza (disorder)"}}],"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" - -@Suppress("ktlint:standard:max-line-length") -const val conditionCodedValidFHIRRecord1a = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c12347","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dba581c"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/condition-code","valueCoding":{"system":"SNOMEDCT","code":"6142004","display":"Influenza (disorder)"}}],"system":"http://loinc.org","code":"80382-5"}],"text":"Flu A"},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" @Suppress("ktlint:standard:max-line-length") const val validFHIRRecord2 = - """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c09876","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dbau8cd"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"41458-1"}],"text":"SARS "},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" - -@Suppress("ktlint:standard:max-line-length") -const val validFHIRRecord2a = """{"resourceType":"Bundle","id":"1667861767830636000.7db38d22-b713-49fc-abfa-2edba9c09876","meta":{"lastUpdated":"2022-11-07T22:56:07.832+00:00"},"identifier":{"value":"1234d1d1-95fe-462c-8ac6-46728dbau8cd"},"type":"message","timestamp":"2021-08-03T13:15:11.015+00:00","entry":[{"fullUrl":"MessageHeader/0993dd0b-6ce5-3caf-a177-0b81cc780c18","resource":{"resourceType":"MessageHeader","id":"0993dd0b-6ce5-3caf-a177-0b81cc780c18","extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/encoding-characters","valueString":"^~\\&#"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/character-set","valueString":"UNICODE UTF-8"},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/msh-message-header","extension":[{"url":"MSH.7","valueString":"20230501102531-0400"}]}],"eventCoding":{"system":"http://terminology.hl7.org/CodeSystem/v2-0003","code":"R01","display":"ORU^R01^ORU_R01"},"sender":{"reference":"Organization/1710886092467181000.213628f7-9569-4400-a95d-621c3bfbf121"}}},{"fullUrl":"Observation/d683b42a-bf50-45e8-9fce-6c0531994f09","resource":{"resourceType":"Observation","id":"d683b42a-bf50-45e8-9fce-6c0531994f09","status":"final","code":{"coding":[{"system":"http://loinc.org","code":"41458-1"}],"text":"SARS "},"subject":{"reference":"Patient/9473889b-b2b9-45ac-a8d8-191f27132912"},"performer":[{"reference":"Organization/1a0139b9-fc23-450b-9b6c-cd081e5cea9d"}],"valueCodeableConcept":{"coding":[{"system":"http://snomed.info/sct","code":"260373001","display":"Detected"}]},"interpretation":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0078","code":"A","display":"Abnormal"}]}],"method":{"extension":[{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/testkit-name-id","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}},{"url":"https://reportstream.cdc.gov/fhir/StructureDefinition/equipment-uid","valueCoding":{"code":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B_Becton, Dickinson and Company (BD)"}}],"coding":[{"display":"BD Veritor System for Rapid Detection of SARS-CoV-2 & Flu A+B*"}]},"specimen":{"reference":"Specimen/52a582e4-d389-42d0-b738-bee51cf5244d"},"device":{"reference":"Device/78dc4d98-2958-43a3-a445-76ceef8c0698"}}}]}""" const val invalidEmptyFHIRRecord = "{}" diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt index b58057ec07d..b534f994a12 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRConverterIntegrationTests.kt @@ -53,7 +53,7 @@ import gov.cdc.prime.router.common.badEncodingHL7Record import gov.cdc.prime.router.common.cleanHL7Record import gov.cdc.prime.router.common.cleanHL7RecordConverted import gov.cdc.prime.router.common.cleanHL7RecordConvertedAndTransformed -import gov.cdc.prime.router.common.conditionCodedValidFHIRRecord1a +import gov.cdc.prime.router.common.conditionCodedValidFHIRRecord1 import gov.cdc.prime.router.common.garbledHL7Record import gov.cdc.prime.router.common.invalidEmptyFHIRRecord import gov.cdc.prime.router.common.invalidHL7Record @@ -62,8 +62,8 @@ import gov.cdc.prime.router.common.invalidHL7RecordConvertedAndTransformed import gov.cdc.prime.router.common.invalidMalformedFHIRRecord import gov.cdc.prime.router.common.invalidRadxMarsHL7Message import gov.cdc.prime.router.common.unparseableHL7Record -import gov.cdc.prime.router.common.validFHIRRecord1a -import gov.cdc.prime.router.common.validFHIRRecord2a +import gov.cdc.prime.router.common.validFHIRRecord1 +import gov.cdc.prime.router.common.validFHIRRecord2 import gov.cdc.prime.router.common.validRadxMarsHL7Message import gov.cdc.prime.router.common.validRadxMarsHL7MessageConverted import gov.cdc.prime.router.db.ReportStreamTestDatabaseContainer @@ -692,9 +692,9 @@ class FHIRConverterIntegrationTests { val receivedReportContents = listOf( - validFHIRRecord1a, + validFHIRRecord1, invalidEmptyFHIRRecord, - validFHIRRecord2a, + validFHIRRecord2, invalidMalformedFHIRRecord ).joinToString( "\n" @@ -750,7 +750,7 @@ class FHIRConverterIntegrationTests { } .map { Pair(it.first, it.second.toString(Charset.defaultCharset())) } assertThat(reportAndBundles).transform { pairs -> pairs.map { it.second } } - .containsOnly(conditionCodedValidFHIRRecord1a, validFHIRRecord2a) + .containsOnly(conditionCodedValidFHIRRecord1, validFHIRRecord2) val expectedQueueMessages = reportAndBundles.map { (report, fhirBundle) -> FhirDestinationFilterQueueMessage( report.reportId, diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRReceiverFilterIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRReceiverFilterIntegrationTests.kt index 4acfecbf826..d8bae65c3eb 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRReceiverFilterIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRReceiverFilterIntegrationTests.kt @@ -920,7 +920,7 @@ class FHIRReceiverFilterIntegrationTests : Logging { ReportStreamEventProperties.FILTER_TYPE to ReportStreamFilterType.QUALITY_FILTER, ReportStreamEventProperties.BUNDLE_DIGEST to BundleDigestLabResult( observationSummaries = AzureEventUtils.getObservationSummaries(bundle), - eventType = "", + eventType = "ORU^R01^ORU_R01", patientState = emptyList(), performerState = emptyList(), orderingFacilityState = emptyList() From 986d6fb4b327a001a2bcb5c4b11197439f1cc7e6 Mon Sep 17 00:00:00 2001 From: Josh Fisk Date: Fri, 13 Dec 2024 11:35:02 -0800 Subject: [PATCH 13/17] Allow alternate input on MSH for RADx_MARS (#16788) * Allow alternate input on MSH 5 and 6 for RADx_Mars * Using sample hl7 from ticket description --- .../v251/radxmars/onboarding/constraints.xml | 30 ------------------- .../v251/radxmars/production/constraints.xml | 30 ------------------- .../validation/MarsOtcElrValidatorTests.kt | 11 +++++++ .../marsotcelr/valid_altered_msh.hl7 | 9 ++++++ 4 files changed, 20 insertions(+), 60 deletions(-) create mode 100644 prime-router/src/test/resources/validation/marsotcelr/valid_altered_msh.hl7 diff --git a/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/onboarding/constraints.xml b/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/onboarding/constraints.xml index 75e5166f1dc..ec78da25b9d 100644 --- a/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/onboarding/constraints.xml +++ b/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/onboarding/constraints.xml @@ -584,27 +584,12 @@ Text="ISO"/> - - MSH-5.2 (Universal ID) shall contain one of the values in the list: ['2.16.840.1.114222.4.3.15.2','2.16.840.1.114222.4.3.15.1']. - - - - MSH-6.3 (Universal ID Type) shall contain the value 'ISO'. </Assertion> </Constraint> - <Constraint ID="MSH-6.2" Strength="SHALL"> - <Description> MSH-6.2 (Universal ID) shall contain the value '2.16.840.1.114222.4.1.217446'. </Description> - <Assertion> - <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="6[1].2[1]" - Text="2.16.840.1.114222.4.1.217446"/> - </Assertion> - </Constraint> <Constraint ID="MSH-7" Strength="SHALL"> <Description> MSH-7.1 (Time) shall match the regular expression '^(\d{14}\.\d{1,4}|\d{14})((\x2D|\x2B)\d{4})$'. </Description> <Assertion> @@ -612,13 +597,6 @@ Regex="^(\d{14}\.\d{1,4}|\d{14})((\x2D|\x2B)\d{4})$"/> </Assertion> </Constraint> - <Constraint ID="MSH-6.1" Strength="SHALL"> - <Description> MSH-6.1 (Namespace ID) shall contain the value 'AIMS.PLATFORM'. </Description> - <Assertion> - <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="6[1].1[1]" - Text="AIMS.PLATFORM"/> - </Assertion> - </Constraint> <Constraint ID="MSH-1" Strength="SHALL"> <Description> MSH-1 (Field Separator) shall contain the value '|'. </Description> <Assertion> @@ -679,14 +657,6 @@ <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="15[1]" Text="NE"/> </Assertion> </Constraint> - <Constraint ID="MSH-5.1" Strength="SHALL"> - <Description> MSH-5.1 (Namespace ID) shall contain one of the values in the list: ['AIMS.INTEGRATION.STG','AIMS.INTEGRATION.PRD']. </Description> - <Assertion> - <StringList CSV="AIMS.INTEGRATION.STG,AIMS.INTEGRATION.PRD" IgnoreCase="false" - NotPresentBehavior="PASS" - Path="5[1].1[1]"/> - </Assertion> - </Constraint> </ByID> <ByID ID="OBX_NIH_2-8-1"> <Constraint ID="OBX-19" Strength="SHALL"> diff --git a/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/production/constraints.xml b/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/production/constraints.xml index 6be6551b1dc..f96e980e3f9 100644 --- a/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/production/constraints.xml +++ b/prime-router/src/main/resources/metadata/hl7_validation/v251/radxmars/production/constraints.xml @@ -684,27 +684,12 @@ Text="ISO"/> </Assertion> </Constraint> - <Constraint ID="MSH-5.2" Strength="SHALL"> - <Description> MSH-5.2 (Universal ID) shall contain one of the values in the list: ['2.16.840.1.114222.4.3.15.2','2.16.840.1.114222.4.3.15.1']. </Description> - <Assertion> - <StringList CSV="2.16.840.1.114222.4.3.15.2,2.16.840.1.114222.4.3.15.1" IgnoreCase="false" - NotPresentBehavior="PASS" - Path="5[1].2[1]"/> - </Assertion> - </Constraint> <Constraint ID="MSH-6.3" Strength="SHALL"> <Description> MSH-6.3 (Universal ID Type) shall contain the value 'ISO'. </Description> <Assertion> <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="6[1].3[1]" Text="ISO"/> </Assertion> </Constraint> - <Constraint ID="MSH-6.2" Strength="SHALL"> - <Description> MSH-6.2 (Universal ID) shall contain the value '2.16.840.1.114222.4.1.217446'. </Description> - <Assertion> - <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="6[1].2[1]" - Text="2.16.840.1.114222.4.1.217446"/> - </Assertion> - </Constraint> <Constraint ID="MSH-7" Strength="SHALL"> <Description> MSH-7.1 (Time) shall match the regular expression '^(\d{14}\.\d{1,4}|\d{14})((\x2D|\x2B)\d{4})$'. </Description> <Assertion> @@ -712,13 +697,6 @@ Regex="^(\d{14}\.\d{1,4}|\d{14})((\x2D|\x2B)\d{4})$"/> </Assertion> </Constraint> - <Constraint ID="MSH-6.1" Strength="SHALL"> - <Description> MSH-6.1 (Namespace ID) shall contain the value 'AIMS.PLATFORM'. </Description> - <Assertion> - <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="6[1].1[1]" - Text="AIMS.PLATFORM"/> - </Assertion> - </Constraint> <Constraint ID="MSH-1" Strength="SHALL"> <Description> MSH-1 (Field Separator) shall contain the value '|'. </Description> <Assertion> @@ -779,14 +757,6 @@ <PlainText IgnoreCase="false" NotPresentBehavior="PASS" Path="15[1]" Text="NE"/> </Assertion> </Constraint> - <Constraint ID="MSH-5.1" Strength="SHALL"> - <Description> MSH-5.1 (Namespace ID) shall contain one of the values in the list: ['AIMS.INTEGRATION.STG','AIMS.INTEGRATION.PRD']. </Description> - <Assertion> - <StringList CSV="AIMS.INTEGRATION.STG,AIMS.INTEGRATION.PRD" IgnoreCase="false" - NotPresentBehavior="PASS" - Path="5[1].1[1]"/> - </Assertion> - </Constraint> </ByID> <ByID ID="OBR_NIH"> <Constraint ID="OBR-22.1" Strength="SHOULD"> diff --git a/prime-router/src/test/kotlin/validation/MarsOtcElrValidatorTests.kt b/prime-router/src/test/kotlin/validation/MarsOtcElrValidatorTests.kt index 8bcf227d3b4..16b35f45c91 100644 --- a/prime-router/src/test/kotlin/validation/MarsOtcElrValidatorTests.kt +++ b/prime-router/src/test/kotlin/validation/MarsOtcElrValidatorTests.kt @@ -32,4 +32,15 @@ class MarsOtcElrValidatorTests { val report = validator.validate(messages[0]) assertThat(report.isValid()).isTrue() } + + @Test + fun `test valid RADxMARS message with NIST invalid MSH-5-1, MSH-5-2, MSH-6-1, MSH-6-2 `() { + val sampleMessageInputStream = + this.javaClass.classLoader.getResourceAsStream("validation/marsotcelr/valid_altered_msh.hl7") + + val sampleMessage = sampleMessageInputStream!!.bufferedReader().use { it.readText() } + val messages = HL7Reader(ActionLogger()).getMessages(sampleMessage) + val report = validator.validate(messages[0]) + assertThat(report.isValid()).isTrue() + } } \ No newline at end of file diff --git a/prime-router/src/test/resources/validation/marsotcelr/valid_altered_msh.hl7 b/prime-router/src/test/resources/validation/marsotcelr/valid_altered_msh.hl7 new file mode 100644 index 00000000000..dbdea1b3ef7 --- /dev/null +++ b/prime-router/src/test/resources/validation/marsotcelr/valid_altered_msh.hl7 @@ -0,0 +1,9 @@ +MSH|^~\&|AbbottInformatics^2.16.840.1.113883.3.8589.4.1.22^ISO|AbbottInformatics^00Z0000002^CLIA|CDC PRIME^2.16.840.1.114222.4.1.237821^ISO|CDC PRIME^2.16.840.1.114222.4.1.237821^ISO|20241204094313+0100||ORU^R01^ORU_R01|20241204094313+0100_Your Test Kit ID|T|2.5.1|||NE|NE|||||PHLabReport-NoAck^ELR251R1_Rcvr_Prof^2.16.840.1.113883.9.11^ISO +SFT|Meadows Design, LLC|1.0.0|RADx MARS Hub API|1.0.0|| +PID|1||c2sense079177^^^&2.16.840.1.113883.3.8589.4.1.22&ISO^PI||Smith^Rebecca^P||20241204|F||2076-8^Native Hawaiian or Other Pacific Islander^HL70005^^^^2.5.1|^^^^60013^^^^||^^PH^^^111^1111111|||||||||H^Hispanic or Latino^HL70189^^^^2.5.1 +ORC|RE||Your Test Kit ID^^2.16.840.1.113883.3.8589.4.1.22^ISO|||||||||^^SA.Proctor|||||||||SA.Proctor|^^^^60013^^^^|^^PH^^^111^1111111| +OBR|1||Your Test Kit ID^^2.16.840.1.113883.3.8589.4.1.22^ISO|94558-4^SARS-CoV-2 (COVID-19) Ag [Presence] in Respiratory specimen by Rapid immunoassay^LN^^^^2.71|||20241204094313+0100|||||||||^^SA.Proctor||||||20241204094313+0100|||F +OBX|1|CWE|94558-4^SARS-CoV-2 (COVID-19) Ag [Presence] in Respiratory specimen by Rapid immunoassay^LN^^^^2.71||260415000^Not Detected^SCT^^^^20210301|||N^Normal^HL70078^^^^2.5.1|||F||||00Z0000016||10811877011337_DIT^^99ELR^^^^Vunknown||20241204094313+0100||||SA.Proctor^^^^^&2.16.840.1.113883.3.8589.4.1.152&ISO^XX^^^00Z0000016|13 Fake AtHome Test Street^^Fake City| +NTE|1|L|10811877011337_DIT +OBX|2|NM|35659-2^Age at specimen collection^LN^^^^2.71||28|a^year^UCUM^^^^2.1|||||F||||00Z0000016||||||||SA.Proctor^^^^^&2.16.840.1.113883.3.8589.4.1.152&ISO^XX^^^00Z0000016|13 Fake AtHome Test Street^^Fake City|||||QST +SPM|1|^Your Test Kit ID&&2.16.840.1.113883.3.8589.4.1.22&ISO||697989009^Anterior nares swab (specimen)^SCT^^^^20210301|||||||||||||20241204094313+0100|20241204094313+0100 \ No newline at end of file From f5f6a49914d8b50031017de411061af765ca65d9 Mon Sep 17 00:00:00 2001 From: Bill Cutshall <billcutshall@navapbc.com> Date: Fri, 13 Dec 2024 15:06:59 -0500 Subject: [PATCH 14/17] [16143] Changes from feedback in PR review. --- .../src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt index c6a7633740e..dc12c4a9e8c 100644 --- a/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt +++ b/prime-router/src/main/kotlin/fhirengine/utils/FHIRBundleHelpers.kt @@ -124,7 +124,6 @@ fun Bundle.addProvenanceReference() { * @return true if has a MesssageHeader that contains an R01 or ORU_R01, otherwise false. */ fun Bundle.isElr(): Boolean { - var isElr = false val code = FhirPathUtils.evaluate( null, this, @@ -134,10 +133,7 @@ fun Bundle.isElr(): Boolean { .filterIsInstance<CodeType>() .firstOrNull() ?.code - if (code != null && ((code == "R01") || (code == "ORU_R01"))) { - isElr = true - } - return isElr + return ((code == "R01") || (code == "ORU_R01")) } /** From 6cb62ecdf83f7ca20c97e87d2f8fa2f3894fe6e2 Mon Sep 17 00:00:00 2001 From: Jack Wang <jack.wang@focusconsulting.io> Date: Fri, 13 Dec 2024 16:20:36 -0500 Subject: [PATCH 15/17] 16409 do not use receive step to determine root report (#16723) * replace check for receive step with check for report_ids that do not appear as child in report_lineage * remove unnecessary join to action table * track payloadname for submissions from the submissions api * add tests for sendoriginal from convert step * order by action_id for consistent result ordering --- .../kotlin/fhirengine/engine/FHIRConverter.kt | 5 +- .../src/main/kotlin/history/db/ReportGraph.kt | 28 +-- .../common/UniversalPipelineTestUtils.kt | 2 +- .../azure/FHIRTranslatorIntegrationTests.kt | 166 +++++++++++++++++- 4 files changed, 183 insertions(+), 18 deletions(-) diff --git a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt index e5cd8908412..0d573d55b7f 100644 --- a/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt +++ b/prime-router/src/main/kotlin/fhirengine/engine/FHIRConverter.kt @@ -111,6 +111,7 @@ class FHIRConverter( companion object { private val clientIdHeader = "client_id" + private val payloadNameHeader = "payloadname" /** * Converts a [FhirConvertQueueMessage] into the input to the convert processing @@ -157,6 +158,7 @@ class FHIRConverter( val blobSubFolderName = message.blobSubFolderName val clientId = message.headers[clientIdHeader] + val payloadName = message.headers[payloadNameHeader] val sender = clientId?.takeIf { it.isNotBlank() }?.let { settings.findSender(it) } if (sender == null) { throw SubmissionSenderNotFound(clientId ?: "", reportId, blobUrl) @@ -178,7 +180,8 @@ class FHIRConverter( // is properly recorded in the report file table with the correct sender actionHistory.trackExternalInputReport( report, - BlobAccess.BlobInfo(format, blobUrl, blobDigest.toByteArray()) + BlobAccess.BlobInfo(format, blobUrl, blobDigest.toByteArray()), + payloadName ) actionHistory.trackActionSenderInfo(sender.fullName) diff --git a/prime-router/src/main/kotlin/history/db/ReportGraph.kt b/prime-router/src/main/kotlin/history/db/ReportGraph.kt index 103b9831eb3..0b44dcfe271 100644 --- a/prime-router/src/main/kotlin/history/db/ReportGraph.kt +++ b/prime-router/src/main/kotlin/history/db/ReportGraph.kt @@ -123,11 +123,10 @@ class ReportGraph( } /** - * Recursively goes up the report_linage table from any report until it reaches - * a report with an action type of "receive" (the root report) + * Recursively goes up the report_lineage table from any report until it reaches + * a report that does not appear in report_lineage as a child report (the root report) * - * This will return null if no report with action type "receive" is present or if - * the root is passed in + * This will return null if the root is passed in */ fun getRootReport(childReportId: UUID): ReportFile? { return db.transactReturning { txn -> @@ -172,19 +171,19 @@ class ReportGraph( .from(cte) .join(REPORT_FILE) .on(REPORT_FILE.REPORT_ID.eq(ItemGraphTable.ITEM_GRAPH.PARENT_REPORT_ID)) - .join(ACTION) - .on(ACTION.ACTION_ID.eq(REPORT_FILE.ACTION_ID)) - .where(ACTION.ACTION_NAME.eq(TaskAction.receive)) + .leftJoin(REPORT_LINEAGE) + .on(REPORT_FILE.REPORT_ID.eq(REPORT_LINEAGE.CHILD_REPORT_ID)) + .where(REPORT_LINEAGE.PARENT_REPORT_ID.isNull()) + .orderBy(REPORT_FILE.ACTION_ID.asc()) .fetchOneInto(Item::class.java) return rootItem } /** - * Recursively goes up the report_linage table from any report until it reaches - * all reports with an action type of "receive" (the root report) + * Recursively goes up the report_lineage table from any report until it reaches + * all reports that do not appear in report_lineage as a child report (the root report) * - * This will return null if no report with action type "receive" is present or if - * the root is passed in + * This will return null if the root is passed in * * If the passed in report ID has multiple root reports, they will all be returned */ @@ -476,9 +475,10 @@ class ReportGraph( .from(cte) .join(REPORT_FILE) .on(REPORT_FILE.REPORT_ID.eq(cte.field(0, UUID::class.java))) - .join(ACTION) - .on(ACTION.ACTION_ID.eq(REPORT_FILE.ACTION_ID)) - .where(ACTION.ACTION_NAME.eq(TaskAction.receive)) + .leftJoin(REPORT_LINEAGE) + .on(REPORT_FILE.REPORT_ID.eq(REPORT_LINEAGE.CHILD_REPORT_ID)) + .where(REPORT_LINEAGE.PARENT_REPORT_ID.isNull()) + .orderBy(REPORT_FILE.ACTION_ID.asc()) /** * Accepts a list of ids and walks down the report lineage graph diff --git a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt index 9a3aaf1c8b8..b647a93f997 100644 --- a/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt +++ b/prime-router/src/test/kotlin/common/UniversalPipelineTestUtils.kt @@ -441,7 +441,7 @@ object UniversalPipelineTestUtils { fileName: String = "mr_fhir_face.fhir", ): Report { val blobUrl = BlobAccess.uploadBlob( - "${TaskAction.receive.literal}/$fileName", + "${previousAction.literal}/$fileName", reportContents.toByteArray(), getBlobContainerMetadata(azuriteContainer) ) diff --git a/prime-router/src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt b/prime-router/src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt index 99eada67991..d8a9adeb1dd 100644 --- a/prime-router/src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt +++ b/prime-router/src/test/kotlin/fhirengine/azure/FHIRTranslatorIntegrationTests.kt @@ -640,7 +640,7 @@ class FHIRTranslatorIntegrationTests : Logging { } @Test - fun `successfully translate HL7 for FHIR receiver when isSendOriginal is true`() { + fun `successfully translate HL7 for FHIR receiver when isSendOriginal is true from receive step`() { // set up val receiverSetupData = listOf( UniversalPipelineTestUtils.ReceiverSetupData( @@ -720,7 +720,7 @@ class FHIRTranslatorIntegrationTests : Logging { } @Test - fun `successfully translate for FHIR receiver when isSendOriginal is true`() { + fun `successfully translate for FHIR receiver when isSendOriginal is true from receive step`() { // set up val receiverSetupData = listOf( UniversalPipelineTestUtils.ReceiverSetupData( @@ -798,4 +798,166 @@ class FHIRTranslatorIntegrationTests : Logging { assertThat(translatedValue).isEqualTo(reportContents.toByteArray()) } } + + @Test + fun `successfully translate HL7 for FHIR receiver when isSendOriginal is true from convert step`() { + // set up + val receiverSetupData = listOf( + UniversalPipelineTestUtils.ReceiverSetupData( + "x", + jurisdictionalFilter = listOf("true"), + qualityFilter = listOf("true"), + routingFilter = listOf("true"), + conditionFilter = listOf("true"), + format = MimeFormat.FHIR + ) + ) + val receivers = UniversalPipelineTestUtils.createReceivers(receiverSetupData) + val org = UniversalPipelineTestUtils.createOrganizationWithReceivers(receivers) + val translator = createFHIRTranslator(azureEventService, org) + val reportContents = File(HL7_WITH_BIRTH_TIME).readText() + val convertReport = UniversalPipelineTestUtils.createReport( + reportContents, + TaskAction.convert, + Event.EventAction.CONVERT, + azuriteContainer, + TaskAction.convert, + fileName = "originalhl7.hl7" + ) + val queueMessage = generateQueueMessage( + convertReport, + reportContents, + UniversalPipelineTestUtils.hl7SenderWithSendOriginal, + "phd.x" + ) + val fhirFunctions = UniversalPipelineTestUtils.createFHIRFunctionsInstance() + + // execute + fhirFunctions.process(queueMessage, 1, translator, ActionHistory(TaskAction.translate)) + + // check that send queue was updated + verify(exactly = 1) { + QueueAccess.sendMessage(QueueMessage.elrSendQueueName, any()) + } + + // check action table + UniversalPipelineTestUtils.checkActionTable(listOf(TaskAction.convert, TaskAction.translate)) + + // verify task and report_file tables were updated correctly in the Translate function (new task and new + // record file created) + ReportStreamTestDatabaseContainer.testDatabaseAccess.transact { txn -> + val report = fetchChildReports(convertReport, txn, 1).single() + assertThat(report.nextAction).isEqualTo(TaskAction.send) + assertThat(report.receivingOrg).isEqualTo("phd") + assertThat(report.receivingOrgSvc).isEqualTo("x") + assertThat(report.schemaName).isEqualTo("None") + assertThat(report.schemaTopic).isEqualTo(Topic.ELR_ELIMS) + assertThat(report.bodyFormat).isEqualTo("HL7") + + val batchTask = DSL.using(txn).select(Task.TASK.asterisk()).from(Task.TASK) + .where(Task.TASK.NEXT_ACTION.eq(TaskAction.batch)) + .fetchOneInto(Task.TASK) + // verify batch queue task does not exist + assertThat(batchTask).isNull() + + val sendTask = DSL.using(txn).select(Task.TASK.asterisk()).from(Task.TASK) + .where(Task.TASK.NEXT_ACTION.eq(TaskAction.send)) + .fetchOneInto(Task.TASK) + // verify send queue task exists + assertThat(sendTask).isNotNull() + assertThat(sendTask!!.reportId).isEqualTo(report.reportId) + + // verify message format is HL7 and is for the expected receiver + assertThat(sendTask.receiverName).isEqualTo("phd.x") + assertThat(sendTask.bodyFormat).isEqualTo("HL7") + + // verify message matches the original HL7 input + val translatedValue = BlobAccess.downloadBlobAsByteArray( + report.bodyUrl, + UniversalPipelineTestUtils.getBlobContainerMetadata(azuriteContainer) + ) + assertThat(translatedValue).isEqualTo(reportContents.toByteArray()) + } + } + + @Test + fun `successfully translate for FHIR receiver when isSendOriginal is true from convert step`() { + // set up + val receiverSetupData = listOf( + UniversalPipelineTestUtils.ReceiverSetupData( + "x", + jurisdictionalFilter = listOf("true"), + qualityFilter = listOf("true"), + routingFilter = listOf("true"), + conditionFilter = listOf("true"), + format = MimeFormat.FHIR + ) + ) + val receivers = UniversalPipelineTestUtils.createReceivers(receiverSetupData) + val org = UniversalPipelineTestUtils.createOrganizationWithReceivers(receivers) + val translator = createFHIRTranslator(azureEventService, org) + val reportContents = File(MULTIPLE_TARGETS_FHIR_PATH).readText() + val convertReport = UniversalPipelineTestUtils.createReport( + reportContents, + TaskAction.convert, + Event.EventAction.CONVERT, + azuriteContainer, + TaskAction.convert + ) + + val queueMessage = generateQueueMessage( + convertReport, + reportContents, + UniversalPipelineTestUtils.fhirSenderWithSendOriginal, + "phd.x" + ) + val fhirFunctions = UniversalPipelineTestUtils.createFHIRFunctionsInstance() + + // execute + fhirFunctions.process(queueMessage, 1, translator, ActionHistory(TaskAction.translate)) + + // check that send queue was updated + verify(exactly = 1) { + QueueAccess.sendMessage(QueueMessage.elrSendQueueName, any()) + } + + // check action table + UniversalPipelineTestUtils.checkActionTable(listOf(TaskAction.convert, TaskAction.translate)) + + // verify task and report_file tables were updated correctly in the Translate function (new task and new + // record file created) + ReportStreamTestDatabaseContainer.testDatabaseAccess.transact { txn -> + val report = fetchChildReports(convertReport, txn, 1).single() + assertThat(report.nextAction).isEqualTo(TaskAction.send) + assertThat(report.receivingOrg).isEqualTo("phd") + assertThat(report.receivingOrgSvc).isEqualTo("x") + assertThat(report.schemaName).isEqualTo("None") + assertThat(report.schemaTopic).isEqualTo(Topic.ELR_ELIMS) + assertThat(report.bodyFormat).isEqualTo("FHIR") + + val batchTask = DSL.using(txn).select(Task.TASK.asterisk()).from(Task.TASK) + .where(Task.TASK.NEXT_ACTION.eq(TaskAction.batch)) + .fetchOneInto(Task.TASK) + // verify batch queue task does not exist + assertThat(batchTask).isNull() + + val sendTask = DSL.using(txn).select(Task.TASK.asterisk()).from(Task.TASK) + .where(Task.TASK.NEXT_ACTION.eq(TaskAction.send)) + .fetchOneInto(Task.TASK) + // verify send queue task exists + assertThat(sendTask).isNotNull() + assertThat(sendTask!!.reportId).isEqualTo(report.reportId) + + // verify message format is FHIR and is for the expected receiver + assertThat(sendTask.receiverName).isEqualTo("phd.x") + assertThat(sendTask.bodyFormat).isEqualTo("FHIR") + + // verify message matches the original FHIR input + val translatedValue = BlobAccess.downloadBlobAsByteArray( + report.bodyUrl, + UniversalPipelineTestUtils.getBlobContainerMetadata(azuriteContainer) + ) + assertThat(translatedValue).isEqualTo(reportContents.toByteArray()) + } + } } \ No newline at end of file From ab4081ffa593fdff660a302b7dd23fbec0828df7 Mon Sep 17 00:00:00 2001 From: matts <22215332+devopsmatt@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:08:47 -0800 Subject: [PATCH 16/17] adding whitespece change in TF to rey to force TF deployment (#16817) --- operations/app/terraform/modules/chatops/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/operations/app/terraform/modules/chatops/main.tf b/operations/app/terraform/modules/chatops/main.tf index 722ee471762..99e8705d0e7 100644 --- a/operations/app/terraform/modules/chatops/main.tf +++ b/operations/app/terraform/modules/chatops/main.tf @@ -48,3 +48,4 @@ resource "azurerm_container_group" "chatops" { var.storage_account ] } + From 288a70d95e0093b4d3469a50b2f2c818a53fbd41 Mon Sep 17 00:00:00 2001 From: Jamie Albinson <jamie.albinson@focusconsulting.io> Date: Mon, 16 Dec 2024 15:11:22 -0500 Subject: [PATCH 17/17] 16722 authz documentation (#16769) --- .../authz/authz-deprecated-implementation.md | 151 ++++++++++++++++++ .../src/test/kotlin/tokens/ScopeTests.kt | 19 +++ 2 files changed, 170 insertions(+) create mode 100644 prime-router/docs/authz/authz-deprecated-implementation.md diff --git a/prime-router/docs/authz/authz-deprecated-implementation.md b/prime-router/docs/authz/authz-deprecated-implementation.md new file mode 100644 index 00000000000..4beaa25b869 --- /dev/null +++ b/prime-router/docs/authz/authz-deprecated-implementation.md @@ -0,0 +1,151 @@ +# Authorization Deep Dive + +## Current Design + +To authorize a user for an endpoint, we compare the scopes that are present on the access token versus what scope is +required. + +### Scope Design + +- A client can have multiple scopes +- Scopes are in the format of `{organization}.{senderOrReceiver}.{role}` +- `organization` and `senderOrReceiver` can be omitted with a wildcard `*` or `default` + +There are four possible roles. + +| Role | Definition | +|------------|---------------------------------------------------------------------------| +| primeadmin | system administrator with full access to all endpoints | +| admin | administrator with access to endpoints that manage their own organization | +| user | user with read access to endpoints scoped to their organization | +| report | able to submit a report as an organization | + + +Here are some examples given an organization of md-phd (Maryland Public Health Department) + +| Scope | Access | +|-------------------------|------------------------------------------------------------------------| +| `*.*.primeadmin` | System Administrator | +| `md-phd.*.admin` | Organization Administrator for md-phd | +| `md-phd.*.user` | Organization User for md-phd | +| `md-phd.*.report` | Organization Report Submitter for md-phd | +| `md-phd.default.admin` | Organization Administrator for md-phd | +| `md-phd.default.user` | Organization User for md-phd | +| `md-phd.default.report` | Organization Report Submitter for md-phd | +| `md-phd.abc.admin` | Organization Administrator for md-phd scoped to abc sender or receiver | +| `md-phd.abc.user` | Organization User for md-phd scoped to abc sender or receiver | + + + +We currently have three methods of authenticating and authorizing a user or machine for accessing +ReportStream endpoints. + +### Server2Server + +This is ReportStream code that handles the client credentials OAuth 2.0 flow. This is most often used in machine-to-machine +communication such as senders submitting reports. The important bit for authorization happens based on the scope requested +in the call to the `/api/token` endpoint. A member of the engagement team sets up an organization's public key under a +specific scope in the organization settings. When a request for an access token comes in with a requested scope, we check +the JWT assertion was signed with the public key under that scope in settings. + +If the request is successful, an access token is granted with a scope matching the pattern above. + +### Okta + +Users are all set up under our Okta instance. We add users to appropriate groups in Okta that correspond to what they +should be allowed to access. Those groups are in a custom string array claim called `organization` in the access token +which we then map to scopes that our system can handle. Scopes internal to okta are ignored. + +Here is the Okta group to scope mapping strategy given an organization of md-phd (Maryland Public Health Department) + +| Okta Group | ReportStream Scope | +|-------------------------|--------------------| +| `DHPrimeAdmins` | `*.*.primeadmin` | +| `DHmd-phdAdmins` | `md-phd.*.admin` | +| `DHSender_md-phdAdmins` | `md-phd.*.admin` | +| `DHSender_md-phd` | `md-phd.*.user` | +| `DHmd-phd` | `md-phd.*.user` | +* Note: There is no group that maps to the `report` role + + +### Azure Function Keys + +This is the default authentication process built into the Azure functions library. It is a simple shared secret that is +stored in Azure and shared with the client. It is still used on some endpoints for its simplicity of setup. It includes +no authorization check at all and should be deprecated for that reason. + +### Current system pros +- Flexible for onboarding senders/receivers to allow them to use the system they prefer +- The scopes are fine-grained allowing us to be specific about what resources a client should be able to access + +### Current system cons +- x-function-key authentication is almost a backdoor into our system given that it does not do authorization +- Scopes are difficult to understand and are often tailored to a single client rather than generic permissions +- Authorization code is spread widely across the codebase with a lot of duplication +- Okta group to scope mapping is clunky and prone to errors based on group naming in the Okta admin portal +- Difficult to keep track of which client is using what authentication system + + +## Authorization requirements by endpoint + +| Location | Function Name | Verb | URL | Auth Strategy | Role requirements | Restrictions | +|-------------------------------------------------------------------------------------------|-----------------------------|------------------|-------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|------------------------------------------------------------------|----------------------------------| +| [SenderFilesFunction](../../src/main/kotlin/azure/SenderFilesFunction.kt) | getSenderFiles | GET | /api/sender-files | [OktaAuthentication](../../src/main/kotlin/tokens/OktaAuthentication.kt) | System Admin | None | +| [AdminApiFunctions](../../src/main/kotlin/azure/AdminApiFunctions.kt) | getSendFailures | GET | /api/adm/getsendfailures | [OktaAuthentication](../../src/main/kotlin/tokens/OktaAuthentication.kt) | System Admin | None | +| [AdminApiFunctions](../../src/main/kotlin/azure/AdminApiFunctions.kt) | listreceiversconnstatus | GET | /api/adm/listreceiversconnstatus | [OktaAuthentication](../../src/main/kotlin/tokens/OktaAuthentication.kt) | System Admin | None | +| [AdminApiFunctions](../../src/main/kotlin/azure/AdminApiFunctions.kt) | getresend | GET | /api/adm/getresend | [OktaAuthentication](../../src/main/kotlin/tokens/OktaAuthentication.kt) | System Admin | None | +| [ApiKeysFunctions](../../src/main/kotlin/azure/ApiKeysFunctions.kt) | getApiKeys | GET | /api/settings/organizations/{organizationName}/public-keys | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [ApiKeysFunctions](../../src/main/kotlin/azure/ApiKeysFunctions.kt) | getApiKeysV1 | GET | /api/v1/settings/organizations/{organizationName}/public-keys | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [ApiKeysFunctions](../../src/main/kotlin/azure/ApiKeysFunctions.kt) | postApiKey | POST | /api/settings/organizations/{organizationName}/public-keys | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin or org admin | Organization | +| [ApiKeysFunctions](../../src/main/kotlin/azure/ApiKeysFunctions.kt) | deleteApiKey | DELETE | settings/organizations/{organizationName}/public-keys/{scope}/{kid} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin or org admin | Organization | +| [CheckFunction](../../src/main/kotlin/azure/CheckFunction.kt) | check | GET,POST | /api/check | x-functions-key | None | None | +| [CheckFunction](../../src/main/kotlin/azure/CheckFunction.kt) | checkreceiver | POST | /api/checkreceiver/org/{orgName}/receiver/{receiverName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin or org admin | Organization | +| [CovidResultMetadataFunction](../../src/main/kotlin/azure/CovidResultMetaDataFunction.kt) | save-covid-result-metadata | GET | /api/saveTestData | x-functions-key | None | None | +| [EmailEngineFunction](../../src/main/kotlin/azure/EmailEngineFunction.kt) | createEmailSchedule | POST | /api/email-schedule | EmailEngineFunction.validateUser (Custom Okta) | System Admin | None | +| [EmailEngineFunction](../../src/main/kotlin/azure/EmailEngineFunction.kt) | deleteEmailSchedule | DELETE | /api/email-schedule/{scheduleId} | EmailEngineFunction.validateUser (Custom Okta) | System Admin | None | +| [EmailSenderFunction](../../src/main/kotlin/azure/EmailSenderFunction.kt) | emailRegisteredOrganization | POST | /api/email-registered | None | None | None | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getOrganizations | GET,HEAD | /api/settings/organizations | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | HEAD: System Admin<br/>GET: System Admin, org admin, or org user | Head: None<br/>GET: Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getOneOrganization | GET | /api/settings/organizations/{organizationName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getSenders | GET | /api/settings/organizations/{organizationName}/senders | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | updateOneOrganization | DELETE,PUT | /api/settings/organizations/{organizationName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getOneSender | GET | /api/settings/organizations/{organizationName}/senders/{senderName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | updateOneSender | DELETE,PUT | /api/settings/organizations/{organizationName}/senders/{senderName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getReceivers | GET | /api/settings/organizations/{organizationName}/receivers | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getOneReceiver | GET | /api/settings/organizations/{organizationName}/receivers/{receiverName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | updateOneReceiver | DELETE,PUT | /api/settings/organizations/{organizationName}/receivers/{receiverName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [SettingsFunctions](../../src/main/kotlin/azure/SettingsFunctions.kt) | getSettingRevisionHistory | GET | /api/waters/org/{organizationName}/settings/revs/{settingSelector} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, or org user | Organization | +| [RequeueFunction](../../src/main/kotlin/azure/RequeueFunction.kt) | requeue | POST | /api/requeue/send | x-functions-key | None | None | +| [RequeueFunction](../../src/main/kotlin/azure/RequeueFunction.kt) | doResendFunction | POST | /api/adm/resend | [OktaAuthentication](../../src/main/kotlin/tokens/OktaAuthentication.kt) | System Admin | None | +| [TokenFunction](../../src/main/kotlin/azure/TokenFunction.kt) | token | POST | /api/token | [Server2ServerAuthentication](../../src/main/kotlin/tokens/Server2ServerAuthentication.kt) | Requires properly signed client assertion JWT | None | +| [HistoryFunctions](../../src/main/kotlin/azure/HistoryFunctions.kt) | getReports | GET,HEAD,OPTIONS | /api/history/report | HistoryFunctions.checkAuthenticated (Custom) | System Admin or org user (no org Admin) | Organization | +| [HistoryFunctions](../../src/main/kotlin/azure/HistoryFunctions.kt) | searchReports | POST | /api/v1/reports/search | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [HistoryFunctions](../../src/main/kotlin/azure/HistoryFunctions.kt) | getReportById | GET | /api/history/report/{reportId} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [HistoryFunctions](../../src/main/kotlin/azure/HistoryFunctions.kt) | getFacilitiesByReportId | GET | /api/history/report/{reportId}/facilities | HistoryFunctions.checkAuthenticated (Custom) | System Admin or org user (no org Admin) | Organization | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | getLookupTableList | GET,HEAD | /api/lookuptables/list | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | None | None | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | getLookupTableData | GET | /api/lookuptables/{tableName}/{tableVersion}/content | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | None | None | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | getActiveLookupTableData | GET | /api/lookuptables/{tableName}/content | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | None | None | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | getLookupTableInfo | GET | /api/lookuptables/{tableName}/{tableVersion}/info | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | None | None | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | createLookupTable | POST | /api/lookuptables/{tableName} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [LookupTableFunctions](../../src/main/kotlin/azure/LookupTableFunctions.kt) | activateLookupTable | PUT | /api/lookuptables/{tableName}/{tableVersion}/activate | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [MessagesFunctions](../../src/main/kotlin/azure/MessagesFunctions.kt) | messageSearch | GET | /api/messages | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [MessagesFunctions](../../src/main/kotlin/azure/MessagesFunctions.kt) | messageDetails | GET | /api/message/{id} | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [MetaDataFunction](../../src/main/kotlin/azure/MetaDataFunction.kt) | getLivdData | GET | /api/metadata/livd | None | None | None | +| [ReportFunction](../../src/main/kotlin/azure/ReportFunction.kt) | reports | POST | /api/reports | x-functions-key | None | None | +| [ReportFunction](../../src/main/kotlin/azure/ReportFunction.kt) | getMessagesFromTestBank | POST | /api/reports/testing | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [ReportFunction](../../src/main/kotlin/azure/ReportFunction.kt) | processFhirDataRequest | POST | /api/reports/testing/test | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [ReportFunction](../../src/main/kotlin/azure/ReportFunction.kt) | downloadReport | GET | /api/reports/download | x-functions-key | None | None | +| [ReportFunction](../../src/main/kotlin/azure/ReportFunction.kt) | waters | POST | /api/waters | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization and Sender | +| [ValidateFunction](../../src/main/kotlin/azure/ValidateFunction.kt) | validate | POST | /api/validate | None | None | None | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getDeliveriesV1 | POST | /api/v1/receivers/{receiverName}/deliveries | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getDeliveriesHistory | POST | /api/v1/waters/org/{organization}/deliveries | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getDeliveries | GET | /api/waters/org/{organization}/deliveries | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getDeliveryDetails | GET | /api/waters/report/{id}/delivery | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getEtorMetadataForDelivery | GET | /api/waters/report/{reportId}/delivery/etorMetadata | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getDeliveryFacilities | GET | /api/waters/report/{id}/facilities | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getReportItemsV1 | GET | /api/v1/report/{reportId}/items | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin | None | +| [DeliveryFunction](../../src/main/kotlin/history/azure/DeliveryFunction.kt) | getSubmittersV1 | POST | /api/v1/receivers/{receiverName}/deliveries/submitters/search | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [SubmissionFunction](../../src/main/kotlin/history/azure/SubmissionFunction.kt) | getOrgSubmissionsList | GET | /api/waters/org/{organization}/submissions | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [SubmissionFunction](../../src/main/kotlin/history/azure/SubmissionFunction.kt) | getReportDetailedHistory | GET | /api/waters/report/{id}/history | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | +| [SubmissionFunction](../../src/main/kotlin/history/azure/SubmissionFunction.kt) | getEtorMetadataForHistory | GET | /api/waters/report/{reportId}/history/etorMetadata | [AuthenticatedClaims](../../src/main/kotlin/tokens/AuthenticatedClaims.kt) | System Admin, org admin, org user, or report | Organization | + +*This is valid as of 12/16/24 diff --git a/prime-router/src/test/kotlin/tokens/ScopeTests.kt b/prime-router/src/test/kotlin/tokens/ScopeTests.kt index 8e3e1ad53b2..c0d0caf36da 100644 --- a/prime-router/src/test/kotlin/tokens/ScopeTests.kt +++ b/prime-router/src/test/kotlin/tokens/ScopeTests.kt @@ -144,4 +144,23 @@ class ScopeTests { assertThat(Scope.scopeListContainsScope("x x", "")).isFalse() assertThat(Scope.scopeListContainsScope("x x", " ")).isFalse() } + + @Test + fun `test mapped scopes`() { + val groupMemberships = listOf( + "DHPrimeAdmins", + "DHmd-phdAdmins", + "DHSender_md-phd", + "DHmd-phd" + ) + + val mappedScopes = Scope.mapOktaGroupsToScopes(groupMemberships) + + val expected = setOf( + "*.*.primeadmin", + "md-phd.*.admin", + "md-phd.*.user" + ) + assertThat(mappedScopes).isEqualTo(expected) + } } \ No newline at end of file