diff --git a/CHANGELOG.md b/CHANGELOG.md index 87e0d3eb1..3dd6b24df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +* Fixed issue with coding text being set from incorrect place when mapping allergy intolerances. + ### Added * Documented database requirements in [OPERATING.md](/OPERATING.md#database-requirements) diff --git a/gp2gp-translator/src/integrationTest/java/uk/nhs/adaptors/pss/translator/EhrExtractHandlingIT.java b/gp2gp-translator/src/integrationTest/java/uk/nhs/adaptors/pss/translator/EhrExtractHandlingIT.java index e5e06528f..dda9e9d78 100644 --- a/gp2gp-translator/src/integrationTest/java/uk/nhs/adaptors/pss/translator/EhrExtractHandlingIT.java +++ b/gp2gp-translator/src/integrationTest/java/uk/nhs/adaptors/pss/translator/EhrExtractHandlingIT.java @@ -77,7 +77,9 @@ public class EhrExtractHandlingIT { "entry[59].resource.id", "entry[59].resource.identifier[0].value", "entry[60].resource.id", - "entry[60].resource.identifier[0].value" + "entry[60].resource.identifier[0].value", + "entry[502].resource.id", + "entry[502].resource.identifier[0].value" ); @Autowired diff --git a/gp2gp-translator/src/integrationTest/resources/json/expectedBundle.json b/gp2gp-translator/src/integrationTest/resources/json/expectedBundle.json index c6dd267ab..7cda85827 100644 --- a/gp2gp-translator/src/integrationTest/resources/json/expectedBundle.json +++ b/gp2gp-translator/src/integrationTest/resources/json/expectedBundle.json @@ -30538,27 +30538,17 @@ "code": { "coding": [ { - "extension": [ - { - "url": "https://fhir.nhs.uk/STU3/StructureDefinition/Extension-coding-sctdescid", - "extension": [ - { - "url": "descriptionId", - "valueId": "250208012" - }, - { - "url": "descriptionDisplay", - "valueString": "Civil state unknown" - } - ] - } - ], "system": "http://snomed.info/sct", - "code": "160504008", - "display": "Marital state unknown" + "code": "41891011000001106", + "display": "Azelaic acid 20% cream" + }, + { + "system": "2.16.840.1.113883.2.1.6.4", + "code": "00254001", + "display": "Azelaic acid 20% cream" } ], - "text": "Adverse reaction to Mebeverine Hydrochloride" + "text": "Azelaic acid 20% cream" }, "patient": { "reference": "Patient/e2cf4cc1-08da-4971-845f-35b8447cabdd" @@ -30573,7 +30563,10 @@ }, "note": [ { - "text": "Status: Active" + "text": "Skin Allergy" + }, + { + "text": "Allergy Code: Allergy to drug" } ] } diff --git a/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK06/payload_part.xml b/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK06/payload_part.xml index 2dc5e2d98..92a421d4e 100644 --- a/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK06/payload_part.xml +++ b/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK06/payload_part.xml @@ -18051,34 +18051,27 @@ - - - - Adverse reaction to Mebeverine Hydrochloride + + + + H/O: drug allergy + + - - -
+ - + + + + - Status: Active + Skin Allergy - - - - - - - - - - diff --git a/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK07/payload_part_with_confidentiality_code.xml b/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK07/payload_part_with_confidentiality_code.xml index db3d391c7..0a1574bb8 100644 --- a/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK07/payload_part_with_confidentiality_code.xml +++ b/gp2gp-translator/src/integrationTest/resources/xml/RCMR_IN030000UK07/payload_part_with_confidentiality_code.xml @@ -18062,34 +18062,27 @@ - - - - Adverse reaction to Mebeverine Hydrochloride + + + + H/O: drug allergy + + - - -
+ - + + + + - Status: Active + Skin Allergy - - - - - - - - - - diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapper.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapper.java index 51a50f882..61a284919 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapper.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/mapper/AllergyIntoleranceMapper.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu3.model.AllergyIntolerance; import org.hl7.fhir.dstu3.model.Annotation; +import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.Encounter; import org.hl7.fhir.dstu3.model.Extension; @@ -42,10 +43,10 @@ public class AllergyIntoleranceMapper extends AbstractMapper { private static final String DRUG_ALLERGY_CODE = "14L..00"; private static final String NON_DRUG_ALLERGY_CODE = "SN53.00"; - // the meta profile is pre processed with the url so only the final section is required here + // the meta profile is pre-processed with the url so only the final section is required here private static final String META_PROFILE = "AllergyIntolerance-1"; private static final String ENCOUNTER_URL = "http://hl7.org/fhir/StructureDefinition/encounter-associatedEncounter"; - private static final String CODE_SYSTEM = "2.16.840.1.113883.2.1.6.3"; + private static final String EGTON_CODE_SYSTEM = "2.16.840.1.113883.2.1.6.3"; private static final String ALLERGY_TERM_TEXT = "H/O: drug allergy"; private static final String ALLERGY_NOTE = "Allergy Code: %s"; @@ -111,9 +112,34 @@ private AllergyIntolerance.AllergyIntoleranceCategory getCategory(RCMRMT030101UK return compoundStatement.getCode().getCode().equals(DRUG_ALLERGY_CODE) ? MEDICATION : ENVIRONMENT; } + private Annotation getAllergyNote(CodeableConcept codeableConceptFromCode, CodeableConcept codeableConceptFromValue) { + var codeDisplayName = codeableConceptFromCode.getCodingFirstRep().getDisplay(); + if (codeDisplayName != null + && !ALLERGY_TERM_TEXT.equals(codeDisplayName) + && !codeDisplayName.equals(codeableConceptFromValue.getCodingFirstRep().getDisplay())) { + + return new Annotation().setText(ALLERGY_NOTE.formatted(codeDisplayName)); + } + return null; + } + + private CodeableConcept getCodeableConceptFromNonEgtonCodeValue(RCMRMT030101UK04ObservationStatement observationStatement) { + if (observationStatement.hasValue() + && observationStatement.getValue() instanceof CD value + && !EGTON_CODE_SYSTEM.equals(value.getCodeSystem())) { + + return codeableConceptMapper.mapToCodeableConcept(value); + } + return null; + } + private void buildCode(AllergyIntolerance allergyIntolerance, RCMRMT030101UK04CompoundStatement compoundStatement) { - var observationStatement = - compoundStatement.getComponent().stream().map(RCMRMT030101UK04Component02::getObservationStatement).findFirst().get(); + var observationStatement = compoundStatement.getComponent() + .stream() + .map(RCMRMT030101UK04Component02::getObservationStatement) + .findFirst() + .get(); + var codeableConceptFromCode = codeableConceptMapper.mapToCodeableConcept(observationStatement.getCode()); var compoundCode = compoundStatement.getCode().getCode(); @@ -124,39 +150,43 @@ private void buildCode(AllergyIntolerance allergyIntolerance, RCMRMT030101UK04Co return; } - DegradedCodeableConcepts.addDegradedEntryIfRequired( - allergyIntolerance.getCode(), - DegradedCodeableConcepts.DEGRADED_NON_DRUG_ALLERGY); + DegradedCodeableConcepts.addDegradedEntryIfRequired(allergyIntolerance.getCode(), + DegradedCodeableConcepts.DEGRADED_NON_DRUG_ALLERGY); } if (DRUG_ALLERGY_CODE.equals(compoundCode)) { - if (observationStatement.hasValue() && observationStatement.getValue() instanceof CD value) { - if (!CODE_SYSTEM.equals(value.getCodeSystem())) { - var codeableConceptFromValue = codeableConceptMapper.mapToCodeableConcept(value); - allergyIntolerance.setCode(codeableConceptFromValue); - - var codeDisplayName = codeableConceptFromCode.getCodingFirstRep().getDisplay(); - if (codeDisplayName != null && !ALLERGY_TERM_TEXT.equals(codeDisplayName) - && !codeDisplayName.equals(codeableConceptFromValue.getCodingFirstRep().getDisplay())) { - allergyIntolerance.getNote().add(new Annotation().setText(ALLERGY_NOTE.formatted(codeDisplayName))); - } - } else { - allergyIntolerance.setCode(codeableConceptFromCode); - } - } else { - allergyIntolerance.setCode(codeableConceptFromCode); - } - - if (allergyIntolerance.getCode() == null) { + var codeableConceptFromValue = getCodeableConceptFromNonEgtonCodeValue(observationStatement); + if (codeableConceptFromValue == null && codeableConceptFromCode == null) { return; } + if (codeableConceptFromValue == null) { + allergyIntolerance.setCode(codeableConceptFromCode); - DegradedCodeableConcepts.addDegradedEntryIfRequired( + buildAllergyIntoleranceText(observationStatement, allergyIntolerance); + + DegradedCodeableConcepts.addDegradedEntryIfRequired( allergyIntolerance.getCode(), DegradedCodeableConcepts.DEGRADED_DRUG_ALLERGY); + return; + } + + allergyIntolerance.setCode(codeableConceptFromValue); + + var allergyNote = getAllergyNote(codeableConceptFromCode, codeableConceptFromValue); + if (allergyNote != null) { + allergyIntolerance.getNote().add(allergyNote); + } + } + + if (allergyIntolerance.getCode() == null) { + return; } buildAllergyIntoleranceText(observationStatement, allergyIntolerance); + + DegradedCodeableConcepts.addDegradedEntryIfRequired( + allergyIntolerance.getCode(), + DegradedCodeableConcepts.DEGRADED_DRUG_ALLERGY); } private void buildOnset(RCMRMT030101UK04CompoundStatement compoundStatement, AllergyIntolerance allergyIntolerance) { @@ -190,6 +220,13 @@ private DateTimeType getAssertedDateElement(TS availabilityTime, RCMRMT030101UK0 private void buildAllergyIntoleranceText(RCMRMT030101UK04ObservationStatement observationStatement, AllergyIntolerance allergyIntolerance) { if (allergyIntolerance.getCode() != null) { + if (observationStatement.hasValue() && observationStatement.getValue() instanceof CD value) { + var valueDisplayName = value.getDisplayName(); + if (!StringUtils.isEmpty(valueDisplayName)) { + allergyIntolerance.getCode().setText(valueDisplayName); + return; + } + } var originalTextFromCode = observationStatement.getCode().getOriginalText(); if (!StringUtils.isEmpty(originalTextFromCode)) { allergyIntolerance.getCode().setText(originalTextFromCode); 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 362b91bce..397e41d21 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 @@ -59,6 +59,7 @@ public class AllergyIntoleranceMapperTest { private static final int THREE = 3; private static final String ORIGINAL_TEXT_IN_CODE = "OriginalText from Code"; + private static final String DISPLAY_NAME_IN_VALUE = "Value displayName"; private static final String MULTILEX_CODE_SYSTEM = "2.16.840.1.113883.2.1.6.4"; private static final String MULTILEX_COCONUT_OIL = "01142009"; private static final String SNOMED_CODE_SYSTEM = "2.16.840.1.113883.2.1.3.2.4.15"; @@ -159,7 +160,7 @@ public void testMapDegradedDrugAllergy() { } @Test - public void testMapAllergyWithOriginalTextInObservationCode() { + public void When_AllergyWithOriginalTextAndNoValue_Expect_MapsCodingTextFromCodeOriginalText() { when(codeableConceptMapper.mapToCodeableConcept(any(CD.class))) .thenReturn(defaultCodeableConcept()) .thenReturn(secondaryCodeableConcept()); @@ -270,6 +271,24 @@ public void testMapAllergyWithDrugTermText() { assertThat(allergyIntolerance.getNote().size()).isOne(); } + @Test void When_DrugAllergyWithValueElement_Expect_MapsCodingTextFromValueDescription() { + when(codeableConceptMapper.mapToCodeableConcept(any(CD.class))) + .thenReturn(defaultCodeableConcept()) + .thenReturn(secondaryCodeableConcept()); + var ehrExtract = unmarshallEhrExtract("drug-allergy-with-value.xml"); + List allergyIntolerances = allergyIntoleranceMapper.mapResources(ehrExtract, getPatient(), + getEncounterList(), PRACTISE_CODE); + + assertThat(allergyIntolerances.size()).isEqualTo(1); + var allergyIntolerance = allergyIntolerances.get(0); + + assertFixedValues(allergyIntolerance); + + assertExtension(allergyIntolerance); + + assertThat(allergyIntolerance.getCode().getText()).isEqualTo(DISPLAY_NAME_IN_VALUE); + } + @ParameterizedTest @MethodSource("allergyStructuresWithTranslations") public void testTppNamedSchemaInValue(String filename) { @@ -345,6 +364,7 @@ private CodeableConcept defaultCodeableConcept() { var codeableConcept = new CodeableConcept(); var coding = new Coding(); coding.setDisplay(CODING_DISPLAY_1); + coding.setSystem(SNOMED_CODE_SYSTEM); codeableConcept.addCoding(coding); return codeableConcept; @@ -353,6 +373,7 @@ private CodeableConcept defaultCodeableConcept() { private CodeableConcept secondaryCodeableConcept() { var codeableConcept = new CodeableConcept(); var coding = new Coding(); + coding.setSystem(SNOMED_CODE_SYSTEM); coding.setDisplay(CODING_DISPLAY_2); codeableConcept.addCoding(coding); diff --git a/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/allergy-structure-with-original-text-in-code.xml b/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/allergy-structure-with-original-text-in-code.xml index da3e008da..ba71320e1 100644 --- a/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/allergy-structure-with-original-text-in-code.xml +++ b/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/allergy-structure-with-original-text-in-code.xml @@ -29,9 +29,6 @@ - -
diff --git a/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/drug-allergy-with-value.xml b/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/drug-allergy-with-value.xml new file mode 100644 index 000000000..744075a14 --- /dev/null +++ b/gp2gp-translator/src/test/resources/xml/AllergyIntolerance/drug-allergy-with-value.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + H/O: drug allergy + + + + + + + + + + + + + + + Skin Allergy + + + + + + + + + + +