Skip to content

Commit 21c86a2

Browse files
author
Adrian Clay
authored
NIAD-3204: Allow sending an ehrComposition without an author or Participant2 (#932)
Having done some testing with other GP2GP implementations we've identified that other systems will accept this and generate a fake placeholder Dr within their system when ingesting the record. While the GP Connect spec insists that an Encounter has a participant of type REC, it is preferable to send a GP2GP extract than fail the transfer completely.
1 parent d940bb9 commit 21c86a2

File tree

5 files changed

+70
-39
lines changed

5 files changed

+70
-39
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
in the resultant XML will no longer contain the superfluous 'Earliest Recall Date: <startDate>' value.
1313
* When mapping `ProcedureRequests` with a `requestor` referencing a `device` without a `manufacturer` a spurious
1414
`"null"` is no longer output in the generated `"Recall Device:"` text.
15+
* When mapping an `Encounter` without a Recorder `participant`, now send the author as `nulFlavor=UNK`.
16+
Previously this would raise the error "EhrMapperException: Encounter.participant recorder is required" and send a
17+
failure to the requesting system.
1518

1619
### Added
1720

service/src/main/java/uk/nhs/adaptors/gp2gp/ehr/mapper/EncounterMapper.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@ public String mapEncounterToEhrComposition(Encounter encounter) {
7373
.originalText(buildOriginalText(encounter))
7474
.locationName(buildLocationPertinentInformation(encounter));
7575

76-
final String recReference = findParticipantWithCoding(encounter, ParticipantCoding.RECORDER)
77-
.map(agentDirectory::getAgentId)
78-
.orElseThrow(() -> new EhrMapperException("Encounter.participant recorder is required"));
79-
encounterStatementTemplateParameters.author(recReference);
76+
final Optional<String> recReference = findParticipantWithCoding(encounter, ParticipantCoding.RECORDER)
77+
.map(agentDirectory::getAgentId);
78+
recReference.map(encounterStatementTemplateParameters::author);
8079

8180
messageContext.getInputBundleHolder()
8281
.getListReferencedToEncounter(encounter.getIdElement(), CONSULTATION_LIST_CODE)
@@ -88,7 +87,7 @@ public String mapEncounterToEhrComposition(Encounter encounter) {
8887
final Optional<String> pprfReference = findParticipantWithCoding(encounter, ParticipantCoding.PERFORMER)
8988
.map(agentDirectory::getAgentId);
9089

91-
encounterStatementTemplateParameters.participant2(pprfReference.orElse(recReference));
90+
encounterStatementTemplateParameters.participant2(pprfReference.orElse(recReference.orElse(null)));
9291

9392
updateEhrFolderEffectiveTime(encounter);
9493

service/src/test/java/uk/nhs/adaptors/gp2gp/ehr/mapper/EncounterMapperTest.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public class EncounterMapperTest {
127127
+ "example-encounter-resource-18.json";
128128
private static final String OUTPUT_XML_WITH_NO_EHR_COMPOSITION_COMPONENTS = TEST_FILES_DIRECTORY
129129
+ "expected-output-encounter-14.xml";
130+
public static final String OUTPUT_XML_WITH_NUL_AUTHOR_PARTICIPANT2 = TEST_FILES_DIRECTORY + "expected-output-encounter-15.xml";
130131

131132
@Mock
132133
private RandomIdGeneratorService randomIdGeneratorService;
@@ -159,7 +160,7 @@ public void tearDown() {
159160
@ParameterizedTest
160161
@MethodSource("testFilePaths")
161162
public void When_MappingParsedEncounterJson_Expect_EhrCompositionXmlOutput(String input, String output) throws IOException {
162-
when(randomIdGeneratorService.createNewId()).thenReturn(TEST_ID);
163+
lenient().when(randomIdGeneratorService.createNewId()).thenReturn(TEST_ID);
163164
var sampleComponent = ResourceTestFileUtils.getFileContent(SAMPLE_EHR_COMPOSITION_COMPONENT);
164165

165166
String expectedOutputMessage = ResourceTestFileUtils.getFileContent(output);
@@ -189,6 +190,7 @@ private static Stream<Arguments> testFilePaths() {
189190
Arguments.of(INPUT_JSON_WITH_TYPE_AND_NO_CODING_AND_TEXT, OUTPUT_XML_WITH_TYPE_AND_NO_CODING_AND_TEXT),
190191
Arguments.of(INPUT_JSON_WITH_TYPE_AND_NO_CODING_AND_TEXT_AND_NO_TEXT, OUTPUT_XML_WITH_TYPE_AND_NO_CODING_AND_TEXT_AND_NO_TEXT),
191192
Arguments.of(INPUT_JSON_WITHOUT_PERFORMER_PARTICIPANT, OUTPUT_XML_WITH_RECORDER_AS_PARTICIPANT2),
193+
Arguments.of(INPUT_JSON_WITHOUT_RECORDER_PARTICIPANT, OUTPUT_XML_WITH_NUL_AUTHOR_PARTICIPANT2),
192194
Arguments.of(INPUT_JSON_WITH_NO_LOCATION_REFERENCE, OUTPUT_XML_WITH_NO_LOCATION_REFERENCE)
193195
);
194196
}
@@ -223,21 +225,6 @@ public void When_MappingEncounterWithInvalidParticipantReferenceResourceType_Exp
223225
.hasMessage("Not supported agent reference: Patient/6D340A1B-BC15-4D4E-93CF-BBCB5B74DF73");
224226
}
225227

226-
@Test
227-
public void When_MappingEncounterWithoutRecorderParticipant_Expect_Exception() throws IOException {
228-
var sampleComponent = ResourceTestFileUtils.getFileContent(SAMPLE_EHR_COMPOSITION_COMPONENT);
229-
230-
var jsonInput = ResourceTestFileUtils.getFileContent(INPUT_JSON_WITHOUT_RECORDER_PARTICIPANT);
231-
232-
Encounter parsedEncounter = new FhirParseService().parseResource(jsonInput, Encounter.class);
233-
234-
when(encounterComponentsMapper.mapComponents(parsedEncounter)).thenReturn(sampleComponent);
235-
236-
assertThatThrownBy(() -> encounterMapper.mapEncounterToEhrComposition(parsedEncounter))
237-
.isExactlyInstanceOf(EhrMapperException.class)
238-
.hasMessage("Encounter.participant recorder is required");
239-
}
240-
241228
@Test
242229
public void When_MappingEmptyConsultation_Expect_NoEhrCompositionGenerated() throws IOException {
243230
var jsonInput = ResourceTestFileUtils.getFileContent(INPUT_JSON_ENCOUNTER_NO_ASSOCIATED_CONSULTATION);

service/src/test/resources/ehr/mapper/encounter/example-encounter-resource-14.json

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,7 @@
2828
"subject":{
2929
"reference":"Patient/88F14BF6-CADE-47D6-90E2-B10519BF956F"
3030
},
31-
"participant":[
32-
{
33-
"type":[
34-
{
35-
"coding":[
36-
{
37-
"system":"http://hl7.org/fhir/v3/ParticipationType",
38-
"code":"PPRF",
39-
"display":"primary performer"
40-
}
41-
]
42-
}
43-
],
44-
"individual":{
45-
"reference":"Practitioner/6D340A1B-BC15-4D4E-93CF-BBCB5B74DF73"
46-
}
47-
}
48-
],
31+
"participant":[],
4932
"period":{
5033
"start":"2010-01-13T15:20:00+00:00",
5134
"end":"2010-01-13T16:20:00+00:00"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<component typeCode="COMP">
2+
<ehrComposition classCode="COMPOSITION" moodCode="EVN">
3+
<id root="test-id" />
4+
<code code="24561000000109" displayName="A+E report" codeSystem="2.16.840.1.113883.2.1.3.2.4.15">
5+
<originalText>GP Surgery</originalText>
6+
</code>
7+
<statusCode code="COMPLETE" />
8+
<effectiveTime>
9+
<low value="20100113152000"/><high value="20100113162000"/>
10+
</effectiveTime>
11+
<availabilityTime value="20100113152000"/>
12+
<author typeCode="AUT" contextControlCode="OP">
13+
<time value="20100113151332" />
14+
<agentRef classCode="AGNT">
15+
<id nullFlavor="UNK" />
16+
</agentRef>
17+
</author>
18+
<location typeCode="LOC">
19+
<locatedEntity classCode="LOCE">
20+
<code code="394730007" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="Healthcare related organisation" />
21+
<locatedPlace classCode="PLC" determinerCode="INSTANCE">
22+
<name>Test Location</name>
23+
</locatedPlace>
24+
</locatedEntity>
25+
</location>
26+
<Participant2 typeCode="PRF" contextControlCode="OP">
27+
<agentRef classCode="AGNT">
28+
<id nullFlavor="UNK" />
29+
</agentRef>
30+
</Participant2>
31+
<component typeCode="COMP" >
32+
<ObservationStatement classCode="OBS" moodCode="EVN">
33+
<id root="BA6EA7CB-3E2F-46FA-918C-C0B5178C1D4E" />
34+
<code code="907511000006105" codeSystem="2.16.840.1.113883.2.1.3.2.4.15" displayName="[RFC] Chest infection">
35+
<originalText>Test</originalText>
36+
</code>
37+
<statusCode code="COMPLETE" />
38+
<effectiveTime>
39+
<center value="20201110115000"/>
40+
</effectiveTime>
41+
<availabilityTime value="20201110115000"/>
42+
43+
44+
<pertinentInformation typeCode="PERT">
45+
<sequenceNumber value="+1" />
46+
<pertinentAnnotation classCode="OBS" moodCode="EVN">
47+
<text>Test Observation</text>
48+
</pertinentAnnotation>
49+
</pertinentInformation>
50+
51+
<Participant typeCode="PRF" contextControlCode="OP">
52+
<agentRef classCode="AGNT">
53+
<id root="6423EA0F-1F1C-4255-AEBA-D142BE836D50"/>
54+
</agentRef>
55+
</Participant>
56+
</ObservationStatement>
57+
</component>
58+
</ehrComposition>
59+
</component>

0 commit comments

Comments
 (0)