Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

NIAD-2843: Blood pressure NarrativeStatements are also mapped as Observation comments, leading to duplication #367

Merged
merged 9 commits into from
Nov 14, 2023
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Updated

* Updated the way Observation comments are mapped so that blood pressure NarrativeStatements are not duplicated into
in a separate observation.

### Changed

* Changed `ReferralRequest` mapping to use `ASAP` instead of the `Stat` value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31674,44 +31674,6 @@
"comment": "Comments - Aaaargh"
}
},
{
"resource": {
"resourceType": "Observation",
"id": "EC913E83-7610-4FBD-9A60-1769D42E9DEB",
"meta": {
"profile": [
"https://fhir.nhs.uk/STU3/StructureDefinition/CareConnect-GPC-Observation-1"
]
},
"identifier": [
{
"system": "https://PSSAdaptor/D5445",
"value": "EC913E83-7610-4FBD-9A60-1769D42E9DEB"
}
],
"status": "final",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "37331000000100",
"display": "Comment note"
}
]
},
"subject": {
"reference": "Patient/e2cf4cc1-08da-4971-845f-35b8447cabdd"
},
"effectiveDateTime": "2006-04-25T15:30:00+00:00",
"issued": "2020-01-01T01:01:01.000+00:00",
"performer": [
{
"reference": "Practitioner/2D70F602-6BB1-47E0-B2EC-39912A59787D"
}
],
"comment": "Systolic Measurement Absent: Unknown"
}
},
{
"resource": {
"resourceType": "Observation",
Expand Down Expand Up @@ -31847,47 +31809,6 @@
]
}
},
{
"resource": {
"resourceType": "Observation",
"id": "B27EB734-741C-4152-9E41-7BAB5EF9DD5E",
"meta": {
"profile": [
"https://fhir.nhs.uk/STU3/StructureDefinition/CareConnect-GPC-Observation-1"
]
},
"identifier": [
{
"system": "https://PSSAdaptor/D5445",
"value": "B27EB734-741C-4152-9E41-7BAB5EF9DD5E"
}
],
"status": "final",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "37331000000100",
"display": "Comment note"
}
]
},
"subject": {
"reference": "Patient/e2cf4cc1-08da-4971-845f-35b8447cabdd"
},
"context": {
"reference": "Encounter/9FB8560B-A7FF-4F04-9E0B-CFBB4D0AF4E9"
},
"effectiveDateTime": "2006-04-25T15:30:00+00:00",
"issued": "2010-01-13T15:13:32.000+00:00",
"performer": [
{
"reference": "Practitioner/70555A33-0550-405D-BB67-E9805440B38C"
}
],
"comment": "Systolic Measurement Absent: Unknown"
}
},
{
"resource": {
"resourceType": "Observation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import static org.hl7.fhir.dstu3.model.Enumerations.DocumentReferenceStatus;

import static uk.nhs.adaptors.pss.translator.util.CompoundStatementResourceExtractors.extractAllNarrativeStatements;
import static uk.nhs.adaptors.pss.translator.util.CompoundStatementResourceExtractors.extractAllNonBloodPressureNarrativeStatements;
import static uk.nhs.adaptors.pss.translator.util.ParticipantReferenceUtil.getParticipantReference;
import static uk.nhs.adaptors.pss.translator.util.ResourceUtil.buildIdentifier;

Expand Down Expand Up @@ -38,7 +38,7 @@
@AllArgsConstructor
public class DocumentReferenceMapper extends AbstractMapper<DocumentReference> {

// TODO: Add file Size using the uncompressed/unencoded size of the document (NIAD-2030)
// TODO: Add file Size using the uncompressed/un-encoded size of the document (NIAD-2030)

private static final String META_PROFILE = "https://fhir.nhs.uk/STU3/StructureDefinition/CareConnect-GPC-DocumentReference-1";
private static final String ABSENT_ATTACHMENT = "AbsentAttachment";
Expand All @@ -51,7 +51,7 @@ public List<DocumentReference> mapResources(RCMRMT030101UK04EhrExtract ehrExtrac
List<Encounter> encounterList, Organization organization, List<PatientAttachmentLog> attachments) {

return mapEhrExtractToFhirResource(ehrExtract, (extract, composition, component) ->
extractAllNarrativeStatements(component)
extractAllNonBloodPressureNarrativeStatements(component)
.filter(Objects::nonNull)
.filter(ResourceFilterUtil::isDocumentReference)
.map(narrativeStatement -> mapDocumentReference(narrativeStatement, composition, patient, encounterList,
Expand All @@ -60,12 +60,12 @@ public List<DocumentReference> mapResources(RCMRMT030101UK04EhrExtract ehrExtrac
}

public boolean hasDocumentReferences(RCMRMT030101UK04EhrExtract ehrExtract) {
return mapEhrExtractToFhirResource(ehrExtract, (extract, composition, component) ->
extractAllNarrativeStatements(component)
.filter(Objects::nonNull)
.filter(ResourceFilterUtil::isDocumentReference)
.map(narrativeStatement -> new DocumentReference())
).toList().size() > 0;
return !mapEhrExtractToFhirResource(ehrExtract, (extract, composition, component) ->
extractAllNonBloodPressureNarrativeStatements(component)
.filter(Objects::nonNull)
.filter(ResourceFilterUtil::isDocumentReference)
.map(narrativeStatement -> new DocumentReference())
).toList().isEmpty();
}

private DocumentReference mapDocumentReference(RCMRMT030101UK04NarrativeStatement narrativeStatement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import static org.hl7.fhir.dstu3.model.Observation.ObservationStatus.FINAL;

import static uk.nhs.adaptors.pss.translator.util.CompoundStatementResourceExtractors.extractAllNarrativeStatements;
import static uk.nhs.adaptors.pss.translator.util.CompoundStatementResourceExtractors.extractAllNonBloodPressureNarrativeStatements;
import static uk.nhs.adaptors.pss.translator.util.ResourceFilterUtil.isDocumentReference;
import static uk.nhs.adaptors.pss.translator.util.ResourceUtil.addContextToObservation;
import static uk.nhs.adaptors.pss.translator.util.ResourceUtil.buildIdentifier;
Expand Down Expand Up @@ -43,7 +43,7 @@ public List<Observation> mapResources(RCMRMT030101UK04EhrExtract ehrExtract, Pat
String practiseCode) {

return mapEhrExtractToFhirResource(ehrExtract, (extract, composition, component) ->
extractAllNarrativeStatements(component)
extractAllNonBloodPressureNarrativeStatements(component)
.filter(Objects::nonNull)
.filter(narrativeStatement -> !isDocumentReference(narrativeStatement))
.map(narrativeStatement -> mapObservation(ehrExtract, composition, narrativeStatement, patient, encounters, practiseCode)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,25 @@ public static Stream<RCMRMT030101UK04RequestStatement> extractAllRequestStatemen
);
}

public static Stream<RCMRMT030101UK04NarrativeStatement> extractAllNarrativeStatements(RCMRMT030101UK04Component4 component4) {
return Stream.concat(
Stream.of(component4.getNarrativeStatement()),
component4.hasCompoundStatement() ? CompoundStatementUtil.extractResourcesFromCompound(component4.getCompoundStatement(),
RCMRMT030101UK04Component02::hasNarrativeStatement, RCMRMT030101UK04Component02::getNarrativeStatement)
.stream()
.map(RCMRMT030101UK04NarrativeStatement.class::cast)
: Stream.empty()
);
public static Stream<RCMRMT030101UK04NarrativeStatement> extractAllNonBloodPressureNarrativeStatements(
RCMRMT030101UK04Component4 component4) {

/*
As blood pressures already map their own NarrativeStatements, we do not want to map these again if the
provided component contains a blood pressure triple.
See PR #367 AKA NIAD-2843 for details.
*/
Stream<RCMRMT030101UK04NarrativeStatement> childNarrativeStatements =
hasCompoundStatementAndIsNotBloodPressure(component4)
? CompoundStatementUtil.extractResourcesFromCompound(
component4.getCompoundStatement(),
RCMRMT030101UK04Component02::hasNarrativeStatement,
RCMRMT030101UK04Component02::getNarrativeStatement)
.stream()
.map(RCMRMT030101UK04NarrativeStatement.class::cast)
: Stream.empty();

return Stream.concat(Stream.of(component4.getNarrativeStatement()), childNarrativeStatements);
}

public static Stream<RCMRMT030101UK04MedicationStatement> extractAllMedications(RCMRMT030101UK04Component4 component4) {
Expand All @@ -149,4 +159,9 @@ private static boolean isNotAllergy(RCMRMT030101UK04CompoundStatement compoundSt
}
return true;
}

private static boolean hasCompoundStatementAndIsNotBloodPressure(RCMRMT030101UK04Component4 component4) {
return component4.hasCompoundStatement()
&& !isBloodPressureWithBatteryAndBloodPressureTriple(component4.getCompoundStatement());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ public void mapObservationsWithFullDataSingleObservation() {
assertThat(observation.getContext().getResource()).isEqualTo(encounter);
}

@Test
public void When_MappingObservationsWithBloodPressureTriple_Expect_ObservationCommentNotToBeCreated() {
var ehrExtract = unmarshallEhrExtract("narrative_statement_in_blood_pressure.xml");

var encounter = new Encounter();
encounter.setId(ENCOUNTER_ID);

List<Observation> observations = observationCommentMapper.mapResources(
ehrExtract,
patient,
Collections.singletonList(encounter),
PRACTISE_CODE);

assertThat(observations)
.hasSize(0);
}

@Test
public void mapObservationsWithFullDataMultipleObservations() {
var ehrExtract = unmarshallEhrExtract("multiple_narrative_statements.xml");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<EhrExtract xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" classCode="EXTRACT" moodCode="EVN">
<component typeCode="COMP">
<ehrFolder classCode="FOLDER" moodCode="EVN">
<component typeCode="COMP">
<ehrComposition classCode="COMPOSITION" moodCode="EVN">
<id root="58EC471C-8438-4D55-A132-BB1400FFB195"/>
<code code="196401000000100" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Non-consultation data">
<originalText>Summary Event Entry</originalText>
</code>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20230912"/>
<author contextControlCode="OP" typeCode="AUT">
<time value="20230912165630"/>
<agentRef classCode="AGNT">
<id root="FD5FD24C-D657-1C3B-2F42-8334EC23A810"/>
</agentRef>
</author>
<Participant2 contextControlCode="OP" typeCode="RESP">
<agentRef classCode="AGNT">
<id root="FD5FD24C-D657-1C3B-2F42-8334EC23A810"/>
</agentRef>
</Participant2>
<component typeCode="COMP">
<CompoundStatement classCode="BATTERY" moodCode="EVN">
<id root="B7170865-DAFF-43F4-BE52-BB0979E745EB"/>
<code code="254063019" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="O/E - blood pressure reading">
<translation code="246..00" codeSystem="2.16.840.1.113883.2.1.6.2" displayName="O/E - blood pressure reading"/>
</code>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20230912"/>
<component contextConductionInd="true" typeCode="COMP">
<ObservationStatement classCode="OBS" moodCode="EVN">
<id root="E1EE7567-D740-4DCF-A676-CDB52B65E2EB"/>
<code code="120159016" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Systolic arterial pressure">
<translation code="2469.00" codeSystem="2.16.840.1.113883.2.1.6.2" displayName="O/E - Systolic BP reading"/>
</code>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20230912"/>
<value unit="1" value="120" xsi:type="PQ">
<translation value="120">
<originalText>mmHg</originalText>
</translation>
</value>
</ObservationStatement>
</component>
<component contextConductionInd="true" typeCode="COMP">
<ObservationStatement classCode="OBS" moodCode="EVN">
<id root="7E50A4D4-745A-4E5B-BFA6-39228D1D9F68"/>
<code code="2734671000000117" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Diastolic arterial pressure">
<translation code="246A.00" codeSystem="2.16.840.1.113883.2.1.6.2" displayName="O/E - Diastolic BP reading"/>
</code>
<statusCode code="COMPLETE"/>
<effectiveTime>
<center nullFlavor="NI"/>
</effectiveTime>
<availabilityTime value="20230912"/>
<value unit="1" value="80" xsi:type="PQ">
<translation value="80">
<originalText>mmHg</originalText>
</translation>
</value>
</ObservationStatement>
</component>
<component contextConductionInd="true" typeCode="COMP">
<NarrativeStatement classCode="OBS" moodCode="EVN">
<id root="6D9AF82E-E989-49E9-B9DB-D8AF6AB4ED23"/>
<text>test uncat data</text>
<statusCode code="COMPLETE"/>
<availabilityTime value="20230912"/>
</NarrativeStatement>
</component>
</CompoundStatement>
</component>
</ehrComposition>
</component>
</ehrFolder>
</component>
</EhrExtract>