From d9a87b969d297aa44eac71120f026ae6cdc7eb4f Mon Sep 17 00:00:00 2001 From: hospel Date: Mon, 11 Dec 2023 16:55:31 +0000 Subject: [PATCH 1/5] Update OperationOutcome example in README with new GP2GP code (#384) --- README.md | 63 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index c827f4f6c..8495e62f8 100644 --- a/README.md +++ b/README.md @@ -73,36 +73,41 @@ The endpoint also requires a JSON body that includes the needed patient NHS numb Endpoint calling: 1. Initial request: If you successfully configure the endpoint described above and call it, you should receive a 202-accepted response. This means the adaptor has received the request and is making the relevant requests. -2. Polling the request: after receiving a 202 response, we recommend polling the endpoint at regular intervals using an increasing call gap strategy. Each poll can return the following responses:- - 1. 204 No content: this response indicates that we are still processing the requests / waiting for the EHR message response. - 2. 200 Success: this response indicates we have successfully received and converted the EHR to JSON; you will also receive the FHIR bundle in the response's body. - 3. 400,404,500,501: The endpoint can return all these possible error codes. These will all provide a detailed error with an operationOutcome JSON model response in the body. This looks like... - - ``` - { - "resourceType": "OperationOutcome", - "meta": { - "profile": [ - "https://fhir.nhs.uk/STU3/StructureDefinition/GPConnect-OperationOutcome-1" - ] - }, - "issue": [ - { - "severity": "error", - "code": "exception", - "details": { - "coding": [ - { - "system": "https://fhir.nhs.uk/STU3/ValueSet/Spine-ErrorOrWarningCode-1", - "code": "PATIENT_NOT_FOUND", - "display": "GP2GP - Patient is not registered at the practice" - } - ] + 2. Polling the request: after receiving a 202 response, we recommend polling the endpoint at regular intervals using an increasing call gap strategy. Each poll can return the following responses:- + 1. 204 No content: this response indicates that we are still processing the requests / waiting for the EHR message response. + 2. 200 Success: this response indicates we have successfully received and converted the EHR to JSON; you will also receive the FHIR bundle in the response's body. + 3. 400,404,500,501: The endpoint can return all these possible error codes. These will all provide a detailed error with an operationOutcome JSON model response in the body. This looks like... + + ``` + { + "resourceType": "OperationOutcome", + "meta": { + "profile": [ + "https://fhir.nhs.uk/STU3/StructureDefinition/GPConnect-OperationOutcome-1" + ] + }, + "issue": [ + { + "severity": "error", + "code": "exception", + "details": { + "coding": [ + { + "system": "https://fhir.nhs.uk/STU3/ValueSet/Spine-ErrorOrWarningCode-1", + "code": "PATIENT_NOT_FOUND", + "display": "GP2GP - Patient is not registered at the practice" + }, + { + "system": "2.16.840.1.113883.2.1.3.2.4.17.101" + "code": "06" + "display": "Patient not at surgery" + } + ] + } } - } - ] - } - ``` + ] + } + ``` ### /$gpc.ack From e77f8ec82b846958c859c4e625205669cb7054af Mon Sep 17 00:00:00 2001 From: Harvey Sembhy NHS <135852870+HarveySembhyNHS@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:27:55 +0000 Subject: [PATCH 2/5] Update CHANGELOG to 1.3.0 (#386) --- CHANGELOG.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac7bbaa6e..1a630da1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [1.3.0] - 2023-12-11 + ### Added -* Added code section with specific GP2GP error into Codeable Concept response section +* Added code section with specific GP2GP error into Codeable Concept response section. + +### Changed +* Removed surplus references to Medication Statements from the Topic and Category entry arrays. The + [GP Connect documentation](https://developer.nhs.uk/apis/gpconnect-1-6-0/accessrecord_structured_development_consultation_guidance.html#clinical-item-references) states Medications should be referenced using the Medication Request resource, which is already done. +* Updated postman collection to include attachment tests. ## [1.2.1] - 2023-11-23 @@ -16,8 +23,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * A SystmOne attachment split into multiple chunks can arrive with the same filename "Untitled". Previously each fragment would be stored using the filename provided, which in the case of SystmOne caused chunks to overwrite each other. The adaptor now generates a UUID which is prepended to the filename of a provided chunk to ensure uniqueness. -* Removed surplus references to Medication Statements from the Topic and Category entry arrays. The -[GP Connect documentation](https://developer.nhs.uk/apis/gpconnect-1-6-0/accessrecord_structured_development_consultation_guidance.html#clinical-item-references) states Medications should be referenced using the Medication Request resource, which is already done. ## [1.2.0] - 2023-11-17 @@ -34,7 +39,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Changed * Changed `ReferralRequest` mapping to use `ASAP` instead of the `Stat` value. -* Updated postman collection to include attachment tests. ## [1.1.0] - 2023-11-09 From 3019a4a3f80e88a73fc5e1a4f6933423053a41e4 Mon Sep 17 00:00:00 2001 From: Adrian Clay Date: Tue, 12 Dec 2023 09:22:28 +0000 Subject: [PATCH 3/5] Clarify GP2GP error response --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a630da1a..393311f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [1.3.0] - 2023-12-11 ### Added -* Added code section with specific GP2GP error into Codeable Concept response section. +* In the event of a GP2GP failure, the raw error code is now available in the `/Patient/$gpc.migratestructuredrecord` response section with code system `2.16.840.1.113883.2.1.3.2.4.17.101`. ### Changed * Removed surplus references to Medication Statements from the Topic and Category entry arrays. The From d4b8ae96b1f8f9bb4cf03849b54da7a24154f99f Mon Sep 17 00:00:00 2001 From: hospel Date: Tue, 12 Dec 2023 10:18:24 +0000 Subject: [PATCH 4/5] NIAD-2900: pulling more information into CodeableConcept output (#382) * pulling more information to CodeableConcept output * changelog * method signature adjustment * pass params as per method signature --- CHANGELOG.md | 1 + .../common/util/CodeableConceptUtils.java | 2 +- .../LargeMessage/expectedBundleScenario1.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario2.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario3.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario4.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario5.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario6.json | 24 ++++++---- .../LargeMessage/expectedBundleScenario7.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario8.json | 48 +++++++++++-------- .../LargeMessage/expectedBundleScenario9.json | 48 +++++++++++-------- .../mapper/AgentDirectoryMapper.java | 9 ++-- .../translator/mapper/ConditionMapper.java | 10 ++-- .../translator/mapper/EncounterMapper.java | 4 +- .../mapper/ObservationCommentMapper.java | 3 +- .../translator/mapper/ObservationMapper.java | 1 - .../mapper/AgentDirectoryMapperTest.java | 2 +- .../mapper/AllergyIntoleranceMapperTest.java | 6 +-- .../mapper/ConditionMapperTest.java | 2 +- .../mapper/DocumentReferenceTest.java | 6 +-- .../mapper/EncounterMapperTest.java | 4 +- .../mapper/ObservationMapperTest.java | 4 +- .../mapper/ProcedureRequestMapperTest.java | 2 +- .../mapper/ReferralRequestMapperTest.java | 2 +- .../translator/mapper/TemplateMapperTest.java | 3 +- .../SpecimenBatteryMapperTest.java | 2 +- 26 files changed, 270 insertions(+), 201 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 393311f67..1621e0db6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [1.3.0] - 2023-12-11 ### Added +* Additional information (code, display and system) will be provided in PractionionerRole and Organization resources via Codeable Concept * In the event of a GP2GP failure, the raw error code is now available in the `/Patient/$gpc.migratestructuredrecord` response section with code system `2.16.840.1.113883.2.1.3.2.4.17.101`. ### Changed diff --git a/common/src/main/java/uk/nhs/adaptors/common/util/CodeableConceptUtils.java b/common/src/main/java/uk/nhs/adaptors/common/util/CodeableConceptUtils.java index df81a502f..efabaf33e 100644 --- a/common/src/main/java/uk/nhs/adaptors/common/util/CodeableConceptUtils.java +++ b/common/src/main/java/uk/nhs/adaptors/common/util/CodeableConceptUtils.java @@ -50,7 +50,7 @@ public static CodeableConcept createCodeableConceptWithEhrRequestAckOidCode(Stri * * @return CodeableConcept object with set code, system and display properties */ - public static CodeableConcept createCodeableConcept(String system, String code, String display) { + public static CodeableConcept createCodeableConcept(String code, String system, String display) { var codeableConcept = new CodeableConcept(); Coding coding = new Coding(); coding.setSystem(system); diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario1.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario1.json index 3aae5dc3f..ae3a9085a 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario1.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario1.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario2.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario2.json index 9173b8720..79217bf2f 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario2.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario2.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario3.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario3.json index b41b9520b..6cce4778c 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario3.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario3.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario4.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario4.json index da30d93ae..5f0b3686a 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario4.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario4.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario5.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario5.json index 8a5d1f538..f524c0ad0 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario5.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario5.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario6.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario6.json index a2d119d86..665f3ef14 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario6.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario6.json @@ -61,11 +61,13 @@ "value": "A28009" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "NHS Digital Assurance GP2GP 1", "telecom": [ { @@ -118,11 +120,13 @@ "organization": { "reference": "Organization/0B98DC27-535D-4BC1-A99F-AA5880A446E1" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario7.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario7.json index 3475b7832..aa2650ef9 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario7.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario7.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario8.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario8.json index b061b8d96..200d91a50 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario8.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario8.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario9.json b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario9.json index c05d25489..203b33bc5 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario9.json +++ b/gp2gp-translator/src/integrationTest/resources/json/LargeMessage/expectedBundleScenario9.json @@ -61,11 +61,13 @@ "value": "B83002" } ], - "type": [ - { - "text": "General practice (organisation)" - } - ], + "type": [ { + "coding": [ { + "system": "2.16.840.1.113883.2.1.3.2.4.15", + "code": "394745000", + "display": "General practice (organisation)" + } ] + } ], "name": "Ilkley and Wharfedale Medical Practice", "telecom": [ { @@ -119,11 +121,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { @@ -164,11 +168,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Administrator" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Administrator" + } ] } }, { @@ -236,11 +242,13 @@ "organization": { "reference": "Organization/9C3AB881-FCDE-48EC-8028-37B20E0AE893" }, - "code": [ - { - "text": "Partner" - } - ] + "code": [ { + "coding": [ { + "code": "309394004", + "display": "General Practitioner Principal" + } ], + "text": "Partner" + } ] } }, { diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapper.java index 31ffcecb9..a4bccbba2 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapper.java @@ -37,9 +37,11 @@ import io.micrometer.core.instrument.util.StringUtils; import uk.nhs.adaptors.pss.translator.util.AddressUtil; import uk.nhs.adaptors.pss.translator.util.TelecomUtil; +import static uk.nhs.adaptors.common.util.CodeableConceptUtils.createCodeableConcept; @Service public class AgentDirectoryMapper { + private static final String PRACT_META_PROFILE = "Practitioner-1"; private static final String ORG_META_PROFILE = "Organization-1"; private static final String PRACT_ROLE_META_PROFILE = "PractitionerRole-1"; @@ -221,12 +223,13 @@ private String getOrganizationName(String name) { } private CodeableConcept getText(CV code) { - var codeableConcept = new CodeableConcept(); + if (code != null) { if (StringUtils.isNotEmpty(code.getOriginalText())) { - return codeableConcept.setText(code.getOriginalText()); + return createCodeableConcept(code.getCode(), code.getCodeSystem(), + code.getDisplayName(), code.getOriginalText()); } else if (StringUtils.isNotEmpty(code.getDisplayName())) { - return codeableConcept.setText(code.getDisplayName()); + return createCodeableConcept(code.getCode(), code.getCodeSystem(), code.getDisplayName()); } } diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapper.java index 3d8e8c3b4..479cbfd08 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapper.java @@ -321,8 +321,8 @@ private Optional buildClinicalStatus(CD links } private CodeableConcept generateCategory() { - return createCodeableConcept(CARE_CONNECT_URL, - PROBLEM_LIST_ITEM_CODE, + return createCodeableConcept(PROBLEM_LIST_ITEM_CODE, + CARE_CONNECT_URL, PROBLEM_LIST_ITEM_DISPLAY); } @@ -347,17 +347,15 @@ private List buildRelatedClinicalContent(Bundle bundle, .toList(); // Parse bundle entries into condition reference extensions and return - var conditionExtensions = clinicalReferences + return clinicalReferences .stream() .map(BundleEntryComponent::getResource) .map(resource -> { var reference = new Reference(resource); reference.setReferenceElement(new StringType(resource.getId())); - var extension = buildReferenceExtension(RELATED_CLINICAL_CONTENT_URL, reference); - return extension; + return buildReferenceExtension(RELATED_CLINICAL_CONTENT_URL, reference); }).toList(); - return conditionExtensions; } private List getMedicationRequestIds(RCMRMT030101UK04EhrExtract ehrExtract, List statementRefs) { diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapper.java index 20e209318..18d9d025d 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapper.java @@ -336,7 +336,7 @@ private EncounterParticipantComponent getRecorder(RCMRMT030101UK04Author author) var recorder = new EncounterParticipantComponent(); return recorder - .addType(createCodeableConcept(RECORDER_SYSTEM, RECORDER_CODE, RECORDER_DISPLAY)) + .addType(createCodeableConcept(RECORDER_CODE, RECORDER_SYSTEM, RECORDER_DISPLAY)) .setIndividual(new Reference(PRACTITIONER_REFERENCE_PREFIX + author.getAgentRef().getId().getRoot())); } @@ -348,7 +348,7 @@ private EncounterParticipantComponent getPerformer(RCMRMT030101UK04Participant2 var performer = new EncounterParticipantComponent(); return performer - .addType(createCodeableConcept(PERFORMER_SYSTEM, PERFORMER_CODE, PERFORMER_DISPLAY)) + .addType(createCodeableConcept(PERFORMER_CODE, PERFORMER_SYSTEM, PERFORMER_DISPLAY)) .setIndividual(new Reference(PRACTITIONER_REFERENCE_PREFIX + participant2.getAgentRef().getId().getRoot())); } diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationCommentMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationCommentMapper.java index 76bfe99eb..6b43505cf 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationCommentMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationCommentMapper.java @@ -28,7 +28,6 @@ import uk.nhs.adaptors.common.util.CodeableConceptUtils; import uk.nhs.adaptors.pss.translator.util.DateFormatUtil; import uk.nhs.adaptors.pss.translator.util.ParticipantReferenceUtil; -import static uk.nhs.adaptors.common.util.CodeableConceptUtils.createCodeableConcept; @Service @AllArgsConstructor @@ -95,6 +94,6 @@ private Reference createPerformer(RCMRMT030101UK04EhrComposition composition, RC } private CodeableConcept createCodeableConcept() { - return CodeableConceptUtils.createCodeableConcept(CODING_SYSTEM, CODING_CODE, CODING_DISPLAY); + return CodeableConceptUtils.createCodeableConcept(CODING_CODE, CODING_SYSTEM, CODING_DISPLAY); } } diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapper.java index 94b59f9ca..5702c72b5 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapper.java @@ -62,7 +62,6 @@ public class ObservationMapper extends AbstractMapper { private static final String TEXT = "Text"; private static final BigInteger MINUS_ONE = new BigInteger("-1"); - private final CodeableConceptMapper codeableConceptMapper; private final DatabaseImmunizationChecker immunizationChecker; diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapperTest.java index ea3c1a001..2951c0971 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AgentDirectoryMapperTest.java @@ -140,7 +140,7 @@ public void mapAgentDirectoryWithAgentPersonAndRepresentedOrganizationWithDispla assertEquals(PRACT_ROLE_META_PROFILE, practitionerRole.getMeta().getProfile().get(0).getValue()); assertEquals("Practitioner/94F00D99-0601-4A8E-AD1D-1B564307B0A6", practitionerRole.getPractitioner().getReference()); assertEquals("Organization/94F00D99-0601-4A8E-AD1D-1B564307B0A6-ORG", practitionerRole.getOrganization().getReference()); - assertEquals("General practice", practitionerRole.getCodeFirstRep().getText()); + assertEquals("General practice", practitionerRole.getCode().get(0).getCoding().get(0).getDisplay()); } @Test diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapperTest.java index 99bcd521d..aeaa5963c 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapperTest.java @@ -469,11 +469,11 @@ private Patient getPatient() { } private CodeableConcept defaultCodeableConcept() { - return createCodeableConcept(SNOMED_CODE_SYSTEM, null, CODING_DISPLAY_1); + return createCodeableConcept(null, SNOMED_CODE_SYSTEM, CODING_DISPLAY_1); } private CodeableConcept secondaryCodeableConcept() { - return createCodeableConcept(SNOMED_CODE_SYSTEM, null, CODING_DISPLAY_2); + return createCodeableConcept(null, SNOMED_CODE_SYSTEM, CODING_DISPLAY_2); } private CodeableConcept tertiaryCodeableConcept() { @@ -481,7 +481,7 @@ private CodeableConcept tertiaryCodeableConcept() { } private CodeableConcept nonSnomedCodeableConcept() { - return createCodeableConcept(MULTILEX_CODE_SYSTEM, MULTILEX_COCONUT_OIL, CODING_DISPLAY_4); + return createCodeableConcept(MULTILEX_COCONUT_OIL, MULTILEX_CODE_SYSTEM, CODING_DISPLAY_4); } @SneakyThrows diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapperTest.java index feee24c63..aa5bdf394 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ConditionMapperTest.java @@ -252,7 +252,7 @@ public void mapConditionWithoutSnomedCodeInCoding() { @Test public void mapConditionWithSnomedCodeInCoding() { - var codeableConcept = createCodeableConcept("http://snomed.info/sct", "123456", "Display"); + var codeableConcept = createCodeableConcept("123456", "http://snomed.info/sct", "Display"); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); when(dateTimeMapper.mapDateTime(any(String.class))).thenCallRealMethod(); diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/DocumentReferenceTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/DocumentReferenceTest.java index 747918d50..2a06fa673 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/DocumentReferenceTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/DocumentReferenceTest.java @@ -145,7 +145,7 @@ public void mapNarrativeStatementToDocumentReferenceWithNullFlavors() { @Test public void mapNarrativeStatementWithSnomedCode() { - var codeableConcept = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); var ehrExtract = unmarshallEhrExtract("nested_narrative_statements.xml"); @@ -159,7 +159,7 @@ public void mapNarrativeStatementWithSnomedCode() { @Test public void mapNarrativeStatementWithoutSnomedCode() { - var codeableConcept = createCodeableConcept("not-a-snomed-system", null, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(null, "not-a-snomed-system", CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); var ehrExtract = unmarshallEhrExtract("nested_narrative_statements.xml"); @@ -261,7 +261,7 @@ private static List createAttachmentList() { } private void setUpCodeableConceptMock() { - var codeableConcept = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); } diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapperTest.java index e170ce5fe..ee5ed4c73 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/EncounterMapperTest.java @@ -179,7 +179,7 @@ public void testMapValidEncounterWithSnomedCode() { @Test public void testMapValidEncounterWithoutSnomedCode() { - var codeableConcept = createCodeableConcept("1.2.3.4.5", null, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(null, "1.2.3.4.5", CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); when(consultationListMapper.mapToConsultation(any(RCMRMT030101UK04EhrExtract.class), any(Encounter.class))) @@ -550,7 +550,7 @@ private void assertPeriod(Period period, String startDate, String endDate) { private void setUpCodeableConceptMock() { - var codeableConcept = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY); lenient().when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); lenient().when(immunizationChecker.isImmunization(any())).thenAnswer(new Answer() { @Override diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapperTest.java index d48864efd..60bee7265 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ObservationMapperTest.java @@ -305,7 +305,7 @@ public void When_MapObservation_WithNullFlavorSequenceComments_Expect_CommentsPo @Test public void When_MapObservation_WithoutSnomedCodeInCode_Expect_DegradedCodeableConcept() { - var codeableConcept = createCodeableConcept("1.2.3.4.5", null, CODING_DISPLAY_MOCK); + var codeableConcept = createCodeableConcept(null, "1.2.3.4.5", CODING_DISPLAY_MOCK); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); var ehrExtract = unmarshallEhrExtractElement("full_valid_data_observation_example.xml"); @@ -318,7 +318,7 @@ public void When_MapObservation_WithoutSnomedCodeInCode_Expect_DegradedCodeableC @Test public void When_MapObservation_WithSnomedCodeInCode_Expect_MappedWithoutDegrading() { - var codeableConcept = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY_MOCK); + var codeableConcept = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY_MOCK); lenient().when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); var ehrExtract = unmarshallEhrExtractElement("full_valid_data_observation_example.xml"); diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ProcedureRequestMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ProcedureRequestMapperTest.java index 713db9e9b..fcc2dfb77 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ProcedureRequestMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ProcedureRequestMapperTest.java @@ -217,7 +217,7 @@ private RCMRMT030101UK04EhrComposition getEhrComposition(RCMRMT030101UK04EhrExtr } private void setUpCodeableConceptMock() { - var codeableConcept = createCodeableConcept(CODING_SYSTEM, CODING_CODE, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(CODING_CODE, CODING_SYSTEM, CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())).thenReturn(codeableConcept); } diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java index 6cda78b8c..620a23483 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java @@ -58,7 +58,7 @@ public class ReferralRequestMapperTest { @Test public void mapReferralRequestWithValidData() { - var codeableConcept = createCodeableConcept(SNOMED_SYSTEM, REASON_CODE_1, CODING_DISPLAY); + var codeableConcept = createCodeableConcept(REASON_CODE_1, SNOMED_SYSTEM, CODING_DISPLAY); when(codeableConceptMapper.mapToCodeableConcept(any())) .thenReturn(codeableConcept); diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/TemplateMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/TemplateMapperTest.java index 1d5c4ef93..ffd4de1c4 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/TemplateMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/TemplateMapperTest.java @@ -32,6 +32,7 @@ @ExtendWith(MockitoExtension.class) public class TemplateMapperTest { + private static final String XML_RESOURCES_BASE = "xml/Template/"; private static final String PRACTISE_CODE = "TESTPRACTISECODE"; private static final String COMPOUND_ID = "C8B1BEAF-FB71-45D1-89DA-298148C00CE1"; @@ -45,7 +46,7 @@ public class TemplateMapperTest { private static final String IDENTIFIER = "https://PSSAdaptor/TESTPRACTISECODE"; private static final int THREE = 3; private static final String SNOMED_SYSTEM = "http://snomed.info/sct"; - private static final CodeableConcept CODEABLE_CONCEPT = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY_MOCK); + private static final CodeableConcept CODEABLE_CONCEPT = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY_MOCK); private static final List ENCOUNTER_LIST = List.of( (Encounter) new Encounter().setId(ENCOUNTER_ID) diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/diagnosticreport/SpecimenBatteryMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/diagnosticreport/SpecimenBatteryMapperTest.java index c8a4e6869..0ebfcd420 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/diagnosticreport/SpecimenBatteryMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/diagnosticreport/SpecimenBatteryMapperTest.java @@ -60,7 +60,7 @@ public class SpecimenBatteryMapperTest { private static final DateTimeType OBSERVATION_EFFECTIVE = parseToDateTimeType("20100223000000"); private static final String CODING_DISPLAY_MOCK = "Test Display"; private static final String SNOMED_SYSTEM = "http://snomed.info/sct"; - private static final CodeableConcept CODEABLE_CONCEPT = createCodeableConcept(SNOMED_SYSTEM, null, CODING_DISPLAY_MOCK); + private static final CodeableConcept CODEABLE_CONCEPT = createCodeableConcept(null, SNOMED_SYSTEM, CODING_DISPLAY_MOCK); private final List encounters = generateEncounters(); @Mock From 5cc7c8889c16e94f880366150a187d15caef40d4 Mon Sep 17 00:00:00 2001 From: Ben Hession <7346923+benhession@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:50:13 +0000 Subject: [PATCH 5/5] NIAD-2972: bugfix - Referral request priority code null pointer (#385) * Map priority field from the request statement's priority code, not other request statements in the ehrComposition. * Update CHANGELOG.md * Correct changelog entry for NIAD-2900 --- CHANGELOG.md | 7 +- .../mapper/ReferralRequestMapper.java | 100 ++----------- .../mapper/ReferralRequestMapperTest.java | 109 ++++++++++++-- .../nested_request_statement.xml | 133 ++++++++++++++++++ ...equest_statement_missing_priority_code.xml | 35 +++++ ...est_statement_unexpected_priority_code.xml | 39 +++++ .../two_nested_request_statements.xml | 108 ++++++++++++++ 7 files changed, 430 insertions(+), 101 deletions(-) create mode 100644 gp2gp-translator/src/test/resources/xml/RequestStatement/nested_request_statement.xml create mode 100644 gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_missing_priority_code.xml create mode 100644 gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_unexpected_priority_code.xml create mode 100644 gp2gp-translator/src/test/resources/xml/RequestStatement/two_nested_request_statements.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 1621e0db6..54dfabe31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Fixed +* Fixed issue where mapping failed due to a Referral Request Priority not being found. +* Additional information (code, display and system) will be provided in PractionionerRole and Organization resources via Codeable Concept + ## [1.3.0] - 2023-12-11 -### Added -* Additional information (code, display and system) will be provided in PractionionerRole and Organization resources via Codeable Concept +### Added * In the event of a GP2GP failure, the raw error code is now available in the `/Patient/$gpc.migratestructuredrecord` response section with code system `2.16.840.1.113883.2.1.3.2.4.17.101`. ### Changed diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapper.java index 41ec3a46b..48aa4c239 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapper.java @@ -2,12 +2,12 @@ import static org.hl7.fhir.dstu3.model.ReferralRequest.ReferralPriority; import static org.hl7.fhir.dstu3.model.ReferralRequest.ReferralPriorityEnumFactory; + import static uk.nhs.adaptors.pss.translator.util.CompoundStatementResourceExtractors.extractAllRequestStatements; import static uk.nhs.adaptors.pss.translator.util.ResourceUtil.buildIdentifier; import static uk.nhs.adaptors.pss.translator.util.ResourceUtil.generateMeta; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -25,8 +25,6 @@ import org.hl7.v3.CR; import org.hl7.v3.CV; import org.hl7.v3.IVLTS; -import org.hl7.v3.RCMRMT030101UK04Component02; -import org.hl7.v3.RCMRMT030101UK04Component4; import org.hl7.v3.RCMRMT030101UK04EhrComposition; import org.hl7.v3.RCMRMT030101UK04EhrExtract; import org.hl7.v3.RCMRMT030101UK04RequestStatement; @@ -53,6 +51,7 @@ public class ReferralRequestMapper extends AbstractMapper { "394849002", "urgent", "88694003", "asap" ); + private static final String SNOMED_CODE_SYSTEM = "2.16.840.1.113883.2.1.3.2.4.15"; private CodeableConceptMapper codeableConceptMapper; @@ -76,7 +75,7 @@ public ReferralRequest mapToReferralRequest(RCMRMT030101UK04EhrComposition ehrCo var identifier = buildIdentifier(id, practiseCode); var agent = ParticipantReferenceUtil.getParticipantReference(requestStatement.getParticipant(), ehrComposition); var authoredOn = getAuthoredOn(requestStatement.getAvailabilityTime()); - var referralPriority = getReferralPriorityFromEhrComposition(ehrComposition); + var referralPriority = getReferralPriority(requestStatement); referralRequest.setId(id); referralRequest.setMeta(generateMeta(META_PROFILE)); @@ -177,85 +176,24 @@ private String getActionDateText(IVLTS effectiveTime) { return ACTION_DATE_PREFIX + effectiveTimeValue.asStringValue(); } - private ReferralPriority getReferralPriorityFromEhrComposition(RCMRMT030101UK04EhrComposition ehrComposition) { - - if (ehrComposition == null || ehrComposition.getComponent().isEmpty()) { - return null; - } - - var topLevelComponents = ehrComposition.getComponent(); - - var priorityCode = getPriorityCodesFromTopLevelComponents(topLevelComponents); - - if (priorityCode == null) { - priorityCode = getReferralPriorityCodeFromChildComponents(topLevelComponents.get(0)); - } - - return new ReferralPriorityEnumFactory() - .fromCode(priorityCode); - } - - private String getPriorityCodesFromTopLevelComponents(List components) { - return components - .stream() - .filter(ReferralRequestMapper::hasPriorityCode) - .map(component4 -> component4.getRequestStatement().getPriorityCode().getCode()) - .findFirst() - .map(this::getReferralPriorityCode) - .orElse(null); - } + private ReferralPriority getReferralPriority(RCMRMT030101UK04RequestStatement requestStatement) { - private String getReferralPriorityCode(String priorityCode) { - if (PRIORITY_CODES.containsKey(priorityCode)) { - return PRIORITY_CODES.get(priorityCode); - } - throw new IllegalArgumentException("Unknown ReferralPriority code '" + priorityCode + "'"); - } - - private String getReferralPriorityCodeFromChildComponents(RCMRMT030101UK04Component4 topComponent) { - if (!topComponent.hasCompoundStatement()) { + var priorityCode = requestStatement.getPriorityCode(); + if (snomedCodeNotPresent(priorityCode)) { return null; } - var childComponents = topComponent.getCompoundStatement().getComponent(); - - if (childComponents == null) { - return null; + var hl7Code = priorityCode.getCode(); + if (PRIORITY_CODES.containsKey(hl7Code)) { + return new ReferralPriorityEnumFactory().fromCode(PRIORITY_CODES.get(hl7Code)); } - // We pass the child component to a recursive function, so it finds the priority code for each nested child - var priorityCode = getPriorityCode(childComponents); - return getReferralPriorityCode(priorityCode); + return null; } - private String getPriorityCode(List components) { - - var priorityCode = components - .stream() - .map(RCMRMT030101UK04Component02::getRequestStatement) - .filter(Objects::nonNull) - .map(RCMRMT030101UK04RequestStatement::getPriorityCode) - .filter(Objects::nonNull) - .map(CD::getCode) - .filter(StringUtils::isNotEmpty) - .findFirst() - .orElse(null); - - if (priorityCode != null) { - return priorityCode; - } - - var childComponents = components - .stream() - .filter(ReferralRequestMapper::hasComponentInCompoundStatement) - .map(c -> c.getCompoundStatement().getComponent()) - .filter(c -> !c.isEmpty()) - .findFirst() - .orElse(Collections.emptyList()); - - return childComponents.isEmpty() - ? null - : getPriorityCode(childComponents); + private boolean snomedCodeNotPresent(CV codeElement) { + return codeElement == null || !codeElement.hasCode() || !codeElement.hasCodeSystem() + || !SNOMED_CODE_SYSTEM.equals(codeElement.getCodeSystem()); } private boolean hasIdValue(RCMRMT030101UK04ResponsibleParty3 responsibleParty) { @@ -271,18 +209,6 @@ private boolean hasEffectiveTimeValue(IVLTS effectiveTime) { && effectiveTime.getCenter().getValue() != null; } - private static boolean hasPriorityCode(RCMRMT030101UK04Component4 component) { - return component.getRequestStatement() != null - && component.getRequestStatement().getPriorityCode() != null - && component.getRequestStatement().getPriorityCode().getCode() != null; - } - - private static boolean hasComponentInCompoundStatement(RCMRMT030101UK04Component02 component) { - return component.hasCompoundStatement() - && component.getCompoundStatement().getComponent() != null - && !component.getCompoundStatement().getComponent().isEmpty(); - } - private boolean isNotSelfReferral(RCMRMT030101UK04RequestStatement requestStatement) { for (CR qualifier : requestStatement.getCode().getQualifier()) { if (qualifier.getValue().getCode().equals(SELF_REFERRAL)) { diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java index 620a23483..d60409c87 100644 --- a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/mapper/ReferralRequestMapperTest.java @@ -7,10 +7,12 @@ import static org.mockito.Mockito.when; import static org.springframework.util.ResourceUtils.getFile; +import static uk.nhs.adaptors.common.util.CodeableConceptUtils.createCodeableConcept; import static uk.nhs.adaptors.pss.translator.util.XmlUnmarshallUtil.unmarshallFile; import static uk.nhs.adaptors.pss.translator.util.XmlUnmarshallUtil.unmarshallString; import java.util.List; +import java.util.function.Function; import java.util.stream.Stream; import org.hl7.fhir.dstu3.model.CodeableConcept; @@ -20,6 +22,7 @@ import org.hl7.fhir.dstu3.model.ReferralRequest; import org.hl7.fhir.dstu3.model.ReferralRequest.ReferralRequestStatus; import org.hl7.v3.RCMRMT030101UK04EhrComposition; +import org.hl7.v3.RCMRMT030101UK04RequestStatement; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -31,7 +34,6 @@ import lombok.SneakyThrows; import uk.nhs.adaptors.pss.translator.util.DegradedCodeableConcepts; -import static uk.nhs.adaptors.common.util.CodeableConceptUtils.createCodeableConcept; @ExtendWith(MockitoExtension.class) public class ReferralRequestMapperTest { @@ -48,6 +50,8 @@ public class ReferralRequestMapperTest { private static final String PATIENT_ID = "AD99032E-F103-46C0-BA6D-659C7947ECAF"; private static final String SNOMED_SYSTEM = "http://snomed.info/sct"; private static final String REASON_CODE_1 = "183885007"; + private static final String UNEXPECTED_PRIORITY_DISPLAY = "Delayed priority"; + private static final String PRIORITY_NOTE_PREPENDAGE = "Priority: "; @Mock private CodeableConceptMapper codeableConceptMapper; @@ -64,7 +68,8 @@ public void mapReferralRequestWithValidData() { var ehrComposition = unmarshallEhrCompositionElement("full_valid_data_example.xml"); - var referralRequest = mapReferralRequest(ehrComposition); + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertFixedValues(referralRequest), @@ -105,7 +110,8 @@ public void mapReferralRequestWithNoOptionalData() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - var referralRequest = mapReferralRequest(ehrComposition); + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertThat(referralRequest.getId()) @@ -139,7 +145,8 @@ public void mapReferralRequestWithNoReferencedEncounter() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - ReferralRequest referralRequest = mapReferralRequest(ehrComposition); + ReferralRequest referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertThat(referralRequest.getContext().getResource()) .isNull(); @@ -171,7 +178,8 @@ public void mapReferralRequestWithRequesterPrfParticipant() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - ReferralRequest referralRequest = mapReferralRequest(ehrComposition); + ReferralRequest referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertThat(referralRequest.getId()) @@ -215,7 +223,8 @@ public void mapReferralRequestWithRequesterEhrCompositionParticipant2() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - ReferralRequest referralRequest = mapReferralRequest(ehrComposition); + ReferralRequest referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertThat(referralRequest.getId()) @@ -254,7 +263,8 @@ public void mapReferralRequestWithRecipientResponsiblePartyNoValidTypeCode() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - ReferralRequest referralRequest = mapReferralRequest(ehrComposition); + ReferralRequest referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertThat(referralRequest.getId()) @@ -291,7 +301,8 @@ public void mapReferralRequestWithPriorityNoteWithUsingDisplayName() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - ReferralRequest referralRequest = mapReferralRequest(ehrComposition); + ReferralRequest referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertAll( () -> assertThat(referralRequest.getId()) @@ -329,7 +340,8 @@ public void mapDegradedReferralRequest() { """; var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - var referralRequest = mapReferralRequest(ehrComposition); + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertThat(referralRequest.getReasonCode().get(0).getCoding().get(0)) .isEqualTo(DegradedCodeableConcepts.DEGRADED_REFERRAL); @@ -358,7 +370,8 @@ public void mapReferralRequestPriority(String code, String display, String expec var ehrComposition = unmarshallStringToEhrCompositionElement(inputXml); - var referralRequest = mapReferralRequest(ehrComposition); + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); assertThat(referralRequest.getPriority().getDisplay()) .isEqualTo(expectedDisplay); @@ -371,6 +384,76 @@ private static Stream priorityCodes() { arguments("88694003", "asap", "ASAP")); } + @Test + public void When_MapToReferralRequest_With_NestedRequestStatement_Expect_PriorityCodeMapped() { + var ehrComposition = unmarshallEhrCompositionElement("nested_request_statement.xml"); + + var referralRequest = mapReferralRequest(ehrComposition, this::getNestedRequestStatement); + + assertThat(referralRequest.getPriority()).isEqualTo(ReferralRequest.ReferralPriority.ROUTINE); + } + + @Test + public void When_MapToReferralRequest_With_MissingPriorityCode_Expect_PriorityCodeNotMapped() { + var ehrComposition = unmarshallEhrCompositionElement("request_statement_missing_priority_code.xml"); + + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); + + assertThat(referralRequest.getPriority()).isNull(); + } + + @Test + public void When_MapToReferralRequest_With_TwoNestedRequestStatements_Expect_CorrectPriorityCodeMapped() { + var ehrComposition = unmarshallEhrCompositionElement("two_nested_request_statements.xml"); + + var referralRequest = mapReferralRequest(ehrComposition, this::getNestedRequestStatement); + + assertThat(referralRequest.getPriority()) + .isEqualTo(ReferralRequest.ReferralPriority.ASAP); + } + + @Test + public void When_MapToReferralRequest_With_UnexpectedPriorityCode_Expect_PriorityFieldNotPopulated() { + var ehrComposition = unmarshallEhrCompositionElement("request_statement_unexpected_priority_code.xml"); + + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); + + assertThat(referralRequest.getPriority()).isNull(); + } + + @Test + public void When_MapToReferralRequest_With_UnexpectedPriorityCode_Expect_PriorityAddedToNotes() { + var ehrComposition = unmarshallEhrCompositionElement("request_statement_unexpected_priority_code.xml"); + + var referralRequest = mapReferralRequest(ehrComposition, + composition -> composition.getComponent().get(0).getRequestStatement()); + + var priorityNotes = referralRequest.getNote() + .stream() + .filter(note -> note.hasText() && note.getText().contains(PRIORITY_NOTE_PREPENDAGE + UNEXPECTED_PRIORITY_DISPLAY)) + .toList(); + + assertThat(priorityNotes.size()) + .withFailMessage("Expected priority to have one entry in notes") + .isEqualTo(1); + } + + private RCMRMT030101UK04RequestStatement getNestedRequestStatement(RCMRMT030101UK04EhrComposition ehrComposition) { + return ehrComposition.getComponent() + .get(0) + .getCompoundStatement() + .getComponent() + .get(1) + .getCompoundStatement() + .getComponent() + .get(0) + .getRequestStatement(); + } + + + private void assertFixedValues(ReferralRequest referralRequest) { assertAll( () -> assertThat(referralRequest.getMeta().getProfile().get(0).getValue()) @@ -388,8 +471,10 @@ private void assertFixedValues(ReferralRequest referralRequest) { ); } - private static ReferralRequest mapReferralRequest(RCMRMT030101UK04EhrComposition ehrComposition) { - var requestStatement = ehrComposition.getComponent().get(0).getRequestStatement(); + private static ReferralRequest mapReferralRequest(RCMRMT030101UK04EhrComposition ehrComposition, + Function extractRequestStatement) { + + var requestStatement = extractRequestStatement.apply(ehrComposition); Patient patient = new Patient(); patient.setId(PATIENT_ID); diff --git a/gp2gp-translator/src/test/resources/xml/RequestStatement/nested_request_statement.xml b/gp2gp-translator/src/test/resources/xml/RequestStatement/nested_request_statement.xml new file mode 100644 index 000000000..8a16f3aa5 --- /dev/null +++ b/gp2gp-translator/src/test/resources/xml/RequestStatement/nested_request_statement.xml @@ -0,0 +1,133 @@ + + + + GP Surgery + + + +
+ + + + + + + + + Charnock + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + +
+ + + + + + + + + + + tablet + + + + + + + + + + + + + + tablet + + + + + + + + + + + + One To Be Taken At Night + + + + + + + + + + + + +
+ + + + + + + + + + + + NHS e-Referral Service, Purpose: Unknown + + +
+ + + + Routine + + + + + + + + \ No newline at end of file diff --git a/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_missing_priority_code.xml b/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_missing_priority_code.xml new file mode 100644 index 000000000..abdb5cd5a --- /dev/null +++ b/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_missing_priority_code.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + Test request statement text + New line + + +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_unexpected_priority_code.xml b/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_unexpected_priority_code.xml new file mode 100644 index 000000000..9b478e9de --- /dev/null +++ b/gp2gp-translator/src/test/resources/xml/RequestStatement/request_statement_unexpected_priority_code.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + Test request statement text + New line + + + +
+ + + + Delayed priority + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gp2gp-translator/src/test/resources/xml/RequestStatement/two_nested_request_statements.xml b/gp2gp-translator/src/test/resources/xml/RequestStatement/two_nested_request_statements.xml new file mode 100644 index 000000000..9c655c686 --- /dev/null +++ b/gp2gp-translator/src/test/resources/xml/RequestStatement/two_nested_request_statements.xml @@ -0,0 +1,108 @@ + + + + GP Surgery + + + +
+ + + + + + + + + Charnock + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + NHS e-Referral Service, Purpose: Unknown + + +
+ + + + Routine + + + + + + + + + + + +
+ + + + + + + + + + + + NHS e-Referral Service, Purpose: Unknown + + +
+ + + + Routine + + + + + + + + \ No newline at end of file