diff --git a/src/main/java/uk/nhs/prm/e2etests/enumeration/Gp2GpSystem.java b/src/main/java/uk/nhs/prm/e2etests/enumeration/Gp2GpSystem.java index 1b01f129..de92b341 100644 --- a/src/main/java/uk/nhs/prm/e2etests/enumeration/Gp2GpSystem.java +++ b/src/main/java/uk/nhs/prm/e2etests/enumeration/Gp2GpSystem.java @@ -9,21 +9,27 @@ "into properties files. There are several cases in the codebase where the environments (dev, preprod, perf) etc" + "are being referred to as strings. This enum would be an ideal candidate to expand out.", priority = MEDIUM) public enum Gp2GpSystem { - REPO_DEV("B85002"), - REPO_TEST("B86041"), - EMIS_PTL_INT("N82668"), - TPP_PTL_INT("M85019"); + REPO_DEV("B85002", "200000001613"), + REPO_TEST("B86041", "200000001694"), + EMIS_PTL_INT("N82668", "200000000631"), + TPP_PTL_INT("M85019", "200000000149"); private final String odsCode; + private final String asidCode; - Gp2GpSystem(String odsCode) { + Gp2GpSystem(String odsCode, String asidCode) { this.odsCode = odsCode; + this.asidCode = asidCode; } public String odsCode() { return odsCode; } + public String asidCode() { + return asidCode; + } + public static Gp2GpSystem repoInEnv(String nhsEnvironment) { switch (nhsEnvironment) { case "dev" -> { return REPO_DEV; } @@ -31,4 +37,4 @@ public static Gp2GpSystem repoInEnv(String nhsEnvironment) { default -> throw new InvalidNhsEnvironmentException(); } } -} +} \ No newline at end of file diff --git a/src/main/java/uk/nhs/prm/e2etests/model/database/TransferTrackerRecord.java b/src/main/java/uk/nhs/prm/e2etests/model/database/TransferTrackerRecord.java index 6030a4a4..5684b40e 100644 --- a/src/main/java/uk/nhs/prm/e2etests/model/database/TransferTrackerRecord.java +++ b/src/main/java/uk/nhs/prm/e2etests/model/database/TransferTrackerRecord.java @@ -19,7 +19,8 @@ public class TransferTrackerRecord { private static final String DEFAULT_TIMESTAMP = LocalDateTime.now() + "Z"; private String conversationId; - private String largeEhrCoreMessageId; + @Builder.Default + private String largeEhrCoreMessageId = ""; private String nemsMessageId; private String nhsNumber; private String sourceGp; diff --git a/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/EhrRequestTemplateContext.java b/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/EhrRequestTemplateContext.java index b87312f3..e2e32b72 100644 --- a/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/EhrRequestTemplateContext.java +++ b/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/EhrRequestTemplateContext.java @@ -27,5 +27,4 @@ public class EhrRequestTemplateContext implements TemplateContext { @Pattern(regexp = ASID_REGEX, message = "An invalid ASID Code (new GP) was provided.") private String asidCode; - } diff --git a/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/SmallEhrTemplateContext.java b/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/SmallEhrTemplateContext.java index 0319ae86..91427d5f 100644 --- a/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/SmallEhrTemplateContext.java +++ b/src/main/java/uk/nhs/prm/e2etests/model/templatecontext/SmallEhrTemplateContext.java @@ -12,13 +12,14 @@ @Getter @Builder public class SmallEhrTemplateContext implements TemplateContext { + @Builder.Default @Pattern(regexp = UUID_REGEX, message = "An invalid Conversation ID was provided.") - private String conversationId; + private String inboundConversationId = UUID.randomUUID().toString().toUpperCase(); @Pattern(regexp = NHS_NUMBER_REGEX, message = "An invalid NHS Number was provided.") private String nhsNumber; @Builder.Default @Pattern(regexp = UUID_REGEX, message = "An invalid Message ID was provided.") - private String messageId = UUID.randomUUID().toString(); -} + private String messageId = UUID.randomUUID().toString().toUpperCase(); +} \ No newline at end of file diff --git a/src/main/java/uk/nhs/prm/e2etests/queue/AbstractMessageQueue.java b/src/main/java/uk/nhs/prm/e2etests/queue/AbstractMessageQueue.java index 19936713..297d0942 100644 --- a/src/main/java/uk/nhs/prm/e2etests/queue/AbstractMessageQueue.java +++ b/src/main/java/uk/nhs/prm/e2etests/queue/AbstractMessageQueue.java @@ -3,22 +3,27 @@ import lombok.extern.log4j.Log4j2; import org.awaitility.core.ConditionTimeoutException; import software.amazon.awssdk.services.sqs.model.PurgeQueueInProgressException; -import uk.nhs.prm.e2etests.model.SqsMessage; import uk.nhs.prm.e2etests.model.nems.NemsResolutionMessage; -import uk.nhs.prm.e2etests.service.SqsService; +import org.awaitility.core.ConditionTimeoutException; import uk.nhs.prm.e2etests.utility.MappingUtility; +import uk.nhs.prm.e2etests.service.SqsService; +import uk.nhs.prm.e2etests.model.SqsMessage; +import lombok.extern.log4j.Log4j2; -import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Optional; import java.util.List; import java.util.Map; -import java.util.Optional; + import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import static org.awaitility.Awaitility.await; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; @Log4j2 public abstract class AbstractMessageQueue { @@ -61,7 +66,7 @@ public SqsMessage getMessageContaining(String substring) { return foundMessage; } - public List getAllMessageContaining(String substring, int expectedNumberOfMessages) { + public List getAllMessagesContaining(String substring, int expectedNumberOfMessages) { // This method for now only try to get at least 2 messages from the queue. May need renaming or amending log.info(CHECKING_QUEUE_LOG_MESSAGE, this.queueUri); List allMessages = new ArrayList<>(); @@ -185,4 +190,31 @@ private boolean hasResolutionMessageNow(NemsResolutionMessage messageToCheck) { protected void postAMessageWithAttributes(String message, Map attributes) { this.sqsService.postAMessage(queueUri, message, attributes); } + + public List attemptToGetAllMessagesContaining(String substring, int expectedNumberOfMessages, long secondsToPoll) { + if(expectedNumberOfMessages <= 0 || secondsToPoll <= 0) + throw new IllegalArgumentException("Expected number of messages or seconds to poll must be greater than 0."); + + log.info("Attempting to get at least {} message(s) with substring {} on queue {}.", expectedNumberOfMessages, substring, this.queueUri); + + List allMessages = new ArrayList<>(); + + try { + await().atMost(secondsToPoll, TimeUnit.SECONDS).with().pollInterval(100, TimeUnit.MILLISECONDS).untilAsserted(() -> { + Optional found = findMessageContaining(substring); + + if (found.isPresent()) { + boolean isNewMessage = allMessages.stream() + .noneMatch(sqsMessage -> sqsMessage.getId().equals(found.get().getId())); + if (isNewMessage) allMessages.add(found.get()); + } + + assertThat("", allMessages.size() >= expectedNumberOfMessages); + }); + } catch (ConditionTimeoutException exception) { + log.error("Failed to get at least {} message(s) with substring {} on queue {}, returning all found.", expectedNumberOfMessages, substring, this.queueUri); + } + + return allMessages; + } } \ No newline at end of file diff --git a/src/main/java/uk/nhs/prm/e2etests/repository/TransferTrackerDatabaseRepository.java b/src/main/java/uk/nhs/prm/e2etests/repository/TransferTrackerDatabaseRepository.java index 00194cbe..3c41dc73 100644 --- a/src/main/java/uk/nhs/prm/e2etests/repository/TransferTrackerDatabaseRepository.java +++ b/src/main/java/uk/nhs/prm/e2etests/repository/TransferTrackerDatabaseRepository.java @@ -30,12 +30,16 @@ public TransferTrackerDatabaseRepository( } public void save(TransferTrackerRecord transferTrackerDynamoDbEntry) { + // Update the conversation ID so that it can be saved into the Transfer Tracker DynamoDB. + final String conversationId = transferTrackerDynamoDbEntry.getConversationId(); + transferTrackerDynamoDbEntry.setConversationId(conversationId.toLowerCase()); + transferTrackerTable.putItem(transferTrackerDynamoDbEntry); } public Optional findByConversationId(String conversationId) { return Optional.ofNullable( - transferTrackerTable.getItem(Key.builder().partitionValue(conversationId).build()) + transferTrackerTable.getItem(Key.builder().partitionValue(conversationId.toLowerCase()).build()) ); } } diff --git a/src/test/java/uk/nhs/prm/e2etests/test/RepositoryE2ETest.java b/src/test/java/uk/nhs/prm/e2etests/test/RepositoryE2ETest.java index edb0281a..d49290a3 100644 --- a/src/test/java/uk/nhs/prm/e2etests/test/RepositoryE2ETest.java +++ b/src/test/java/uk/nhs/prm/e2etests/test/RepositoryE2ETest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; @@ -60,10 +61,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.util.AssertionErrors.assertFalse; +import static uk.nhs.prm.e2etests.enumeration.Gp2GpSystem.EMIS_PTL_INT; +import static uk.nhs.prm.e2etests.enumeration.Gp2GpSystem.TPP_PTL_INT; import static uk.nhs.prm.e2etests.enumeration.MessageType.EHR_CORE; import static uk.nhs.prm.e2etests.enumeration.MessageType.EHR_FRAGMENT; -import static uk.nhs.prm.e2etests.enumeration.TemplateVariant.EHR_REQUEST; +import static uk.nhs.prm.e2etests.enumeration.TemplateVariant.*; import static uk.nhs.prm.e2etests.enumeration.TransferTrackerStatus.EHR_REQUEST_SENT; +import static uk.nhs.prm.e2etests.enumeration.TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE; import static uk.nhs.prm.e2etests.utility.XmlComparisonUtility.comparePayloads; import static uk.nhs.prm.e2etests.utility.XmlComparisonUtility.getPayloadOptional; import static uk.nhs.prm.e2etests.utility.NhsIdentityUtility.randomNemsMessageId; @@ -78,7 +82,6 @@ class RepositoryE2ETest { private final PdsAdaptorService pdsAdaptorService; private final TemplatingService templatingService; private final HealthCheckService healthCheckService; - private final SimpleAmqpQueue mhsInboundQueue; private final Gp2GpMessengerOQ gp2gpMessengerOQ; private final EhrTransferServiceTransferCompleteOQ ehrTransferServiceTransferCompleteOQ; @@ -176,7 +179,7 @@ void shouldVerifyThatASmallEhrXMLIsUnchanged() { String asidCodeForTestPatient = "200000000149"; SmallEhrTemplateContext smallEhrTemplateContext = SmallEhrTemplateContext.builder() - .conversationId(inboundConversationId.toUpperCase()) + .inboundConversationId(inboundConversationId.toUpperCase()) .nhsNumber(nhsNumberForTestPatient) .build(); @@ -208,7 +211,7 @@ void shouldVerifyThatASmallEhrXMLIsUnchanged() { log.info("inbound conversationId: {}", inboundConversationId); log.info("conversationIdExists: {}", transferTrackerService.conversationIdExists(inboundConversationId)); - String status = transferTrackerService.waitForStatusMatching(inboundConversationId, TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status); + String status = transferTrackerService.waitForStatusMatching(inboundConversationId, EHR_TRANSFER_TO_REPO_COMPLETE.status); log.info("tracker db status: {}", status); @@ -289,7 +292,7 @@ void shouldVerifyThatALargeEhrXMLIsUnchanged() { largeEhrFragments.forEach(fragment -> mhsInboundQueue.sendMessage(fragment, inboundConversationId)); - status = transferTrackerService.waitForStatusMatching(inboundConversationId, TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status); + status = transferTrackerService.waitForStatusMatching(inboundConversationId, EHR_TRANSFER_TO_REPO_COMPLETE.status); log.info("tracker db status: {}", status); // Put a EHR request to inboundQueueFromMhs @@ -316,7 +319,7 @@ void shouldVerifyThatALargeEhrXMLIsUnchanged() { ); // get all message fragments from gp2gp-messenger observability queue and compare with inbound fragments - List allFragments = gp2gpMessengerOQ.getAllMessageContaining(EHR_FRAGMENT.interactionId, 2); + List allFragments = gp2gpMessengerOQ.getAllMessagesContaining(EHR_FRAGMENT.interactionId, 2); assertThat(allFragments.size()).isGreaterThanOrEqualTo(2); String largeEhrFragment1Payload = getPayloadOptional(largeEhrFragments.get(0)).orElseThrow(); @@ -332,7 +335,7 @@ void shouldVerifyThatALargeEhrXMLIsUnchanged() { boolean identicalWithFragment1 = !compareWithFragment1.hasDifferences(); boolean identicalWithFragment2 = !compareWithFragment2.hasDifferences(); - templatingService.getTemplatedString(TemplateVariant.SMALL_EHR, SmallEhrTemplateContext.builder().build()); + templatingService.getTemplatedString(SMALL_EHR, SmallEhrTemplateContext.builder().build()); assertTrue(identicalWithFragment1 || identicalWithFragment2); }); @@ -428,13 +431,13 @@ void shouldReceivingAndTrackAllLargeEhrFragments_DevAndTest() { RepoIncomingMessage triggerMessage = new RepoIncomingMessageBuilder() .withPatient(largeEhrAtEmisWithRepoMof) - .withEhrSourceGp(Gp2GpSystem.EMIS_PTL_INT) + .withEhrSourceGp(EMIS_PTL_INT) .withEhrDestinationAsRepo(nhsProperties.getNhsEnvironment()) .build(); ehrTransferServiceRepoIncomingQueue.send(triggerMessage); assertThat(ehrTransferServiceEhrCompleteOQ.getMessageContaining(triggerMessage.getConversationId())).isNotNull(); - assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status)); + assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), EHR_TRANSFER_TO_REPO_COMPLETE.status)); } @ParameterizedTest @@ -458,25 +461,51 @@ void shouldTransferRepresentativeSizesAndTypesOfEhrs_DevOnly(Gp2GpSystem sourceS TimeUnit.MINUTES)) .isNotNull(); - assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status)); + assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), EHR_TRANSFER_TO_REPO_COMPLETE.status)); + } + + @ParameterizedTest + @ValueSource(ints = {2, 4, 6}) + void shouldRejectDuplicatedEhrRequestMessagesFromTheSameGP(int numberOfEhrRequests) { + // given + String patientNhsNumber = Patient.PATIENT_WITH_SMALL_EHR_IN_REPO_AND_MOF_SET_TO_TPP.nhsNumber(); + EhrRequestTemplateContext templateContext = EhrRequestTemplateContext.builder() + .nhsNumber(patientNhsNumber) + .newGpOdsCode(TPP_PTL_INT.odsCode()) + .asidCode(TPP_PTL_INT.asidCode()).build(); + String ehrRequestMessage = this.templatingService.getTemplatedString(EHR_REQUEST, templateContext); + String conversationId = templateContext.getOutboundConversationId(); + + // when + addSmallEhrToEhrRepo(patientNhsNumber); + + for(int i = 0; i < numberOfEhrRequests; i++) { + mhsInboundQueue.sendMessage(ehrRequestMessage, conversationId); + log.info("Duplicate EHR Request {} of {} sent to MHS Inbound queue successfully.", (i + 1), numberOfEhrRequests); + } + + final List foundOutboundMessages = this.gp2gpMessengerOQ + .attemptToGetAllMessagesContaining(conversationId, numberOfEhrRequests, 30); + final String outboundEhrCore = foundOutboundMessages.get(0).getBody(); - // option: assert in ehr-repo - check all messages complete - evaluate need based on: - // - ehr out round trip testing - // - implementation of PRMT-2972 + // then + assertThat(foundOutboundMessages.size()).isEqualTo(1); + assertThat(outboundEhrCore).contains(patientNhsNumber); + assertThat(outboundEhrCore).contains(EHR_CORE.interactionId); } private static Stream largeEhrScenariosRunningOnCommit_ButNotEmisWhichIsCurrentlyHavingIssues() { return largeEhrScenariosRunningOnCommit().filter(args -> - args.get()[0] != Gp2GpSystem.EMIS_PTL_INT); + args.get()[0] != EMIS_PTL_INT); } private static Stream largeEhrScenariosRunningOnCommit() { return Stream.of( - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS) ); } @@ -503,18 +532,18 @@ void shouldTransferRemainingSizesAndTypesOfEhrs_DevOnly(Gp2GpSystem sourceSystem TimeUnit.MINUTES)) .isNotNull(); - assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status)); + assertTrue(transferTrackerService.isStatusForConversationIdPresent(triggerMessage.getConversationId(), EHR_TRANSFER_TO_REPO_COMPLETE.status)); } private static Stream largeEhrScenariosToBeRunAsRequired() { return Stream.of( // 5mins+ variation -> removed from regression as intermittently takes 2+ hours // to complete which, while successful, is not sufficiently timely for on-commit regression - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.HIGH_FRAGMENT_COUNT), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.HIGH_FRAGMENT_COUNT), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.HIGH_FRAGMENT_COUNT), // 20mins+, filling FSS disks causing outages -> to be run ad hoc as needed - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.SUPER_LARGE) + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.SUPER_LARGE) // could not move it EMIS to TPP - Large Message general failure // need to establish current TPP limits that are applying in this case @@ -577,17 +606,17 @@ private void checkThatTransfersHaveCompletedSuccessfully(List conversati long timeElapsed = Duration.between(timeLastRequestSent, finishedAt).toSeconds(); log.info("Total time taken for: " + conversationId + " in seconds was no more than : {}", timeElapsed); - assertTrue(transferTrackerService.isStatusForConversationIdPresent(conversationId, TransferTrackerStatus.EHR_TRANSFER_TO_REPO_COMPLETE.status)); + assertTrue(transferTrackerService.isStatusForConversationIdPresent(conversationId, EHR_TRANSFER_TO_REPO_COMPLETE.status)); } } private static Stream loadTestScenarios() { return Stream.of( - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.SINGLE_LARGE_FRAGMENT), - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.LARGE_MEDICAL_HISTORY), - Arguments.of(Gp2GpSystem.EMIS_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS), + Arguments.of(EMIS_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS), Arguments.of(Gp2GpSystem.TPP_PTL_INT, LargeEhrVariant.MULTIPLE_LARGE_FRAGMENTS) // // // 5mins + variation -> let's run these overnight @@ -657,4 +686,23 @@ void shouldSendUnexpectedMessageFormatsThroughToEhrTransferServiceDeadLetterQueu assertThat(ehrTransferServiceParsingDeadLetterQueue.getMessageContaining(message)).isNotNull(); }); } + + // ============ HELPER METHODS ============ + private void addSmallEhrToEhrRepo(String nhsNumber) { + final SmallEhrTemplateContext smallEhrTemplateContext = SmallEhrTemplateContext.builder() + .nhsNumber(nhsNumber) + .build(); + final String inboundConversationId = smallEhrTemplateContext.getInboundConversationId(); + final String smallEhrMessage = this.templatingService.getTemplatedString(SMALL_EHR_WITHOUT_LINEBREAKS, smallEhrTemplateContext); + + this.transferTrackerService.save(TransferTrackerRecord.builder() + .conversationId(inboundConversationId) + .nhsNumber(nhsNumber) + .sourceGp(Gp2GpSystem.TPP_PTL_INT.odsCode()) + .nemsMessageId(randomNemsMessageId()) + .state(EHR_REQUEST_SENT.status).build()); + + this.mhsInboundQueue.sendMessage(smallEhrMessage, inboundConversationId); + this.transferTrackerService.waitForStatusMatching(inboundConversationId, EHR_TRANSFER_TO_REPO_COMPLETE.status); + } } diff --git a/src/test/resources/templates/small-ehr-without-linebreaks.hbs b/src/test/resources/templates/small-ehr-without-linebreaks.hbs index 0bbd4be2..903c5a80 100644 --- a/src/test/resources/templates/small-ehr-without-linebreaks.hbs +++ b/src/test/resources/templates/small-ehr-without-linebreaks.hbs @@ -1 +1 @@ -{"ebXML": "YGM24-820388B85002-8226522b09c33f8279b1e094ce{{conversationId}}urn:nhs:names:services:gp2gpRCMR_IN030000UK06{{messageId}}2023-05-03T11:48:15Z2023-05-03T15:58:15Zalways", "payload": "DR DK NANDI'S PRACTICEDaveAvenueDR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNAssuranceTeamTwoDR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TN
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNNairobi sheep diseaseProblem severity: Major TEST patient with doctor note and line brea...Thyroid hormone tests normal
Nairobi sheep disease
TEST patient with doctor note and line break test
tablettablettest multiline notes!!!<html> </html>take one as neededNairobi sheep disease
(New Episode). TEST patient with doctor note and line breakdeliberately add some linebreaks and <> tags to test how it will be stored in EHR test test <html> testinng <h1> some html </h1> <br> <br> <br></html>
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNtest doctor note with without linebreaks!
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNApplied
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TN ** Care started at DR DK NANDI'S PRACTICE (Applied) **", "attachments": [], "external_attachments": []} \ No newline at end of file +{"ebXML": "YGM24-820388B85002-8226522b09c33f8279b1e094ce{{inboundConversationId}}urn:nhs:names:services:gp2gpRCMR_IN030000UK06{{messageId}}2023-05-03T11:48:15Z2023-05-03T15:58:15Zalways", "payload": "DR DK NANDI'S PRACTICEDaveAvenueDR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNAssuranceTeamTwoDR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TN
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNNairobi sheep diseaseProblem severity: Major TEST patient with doctor note and line brea...Thyroid hormone tests normal
Nairobi sheep disease
TEST patient with doctor note and line break test
tablettablettest multiline notes!!!<html> </html>take one as neededNairobi sheep disease
(New Episode). TEST patient with doctor note and line breakdeliberately add some linebreaks and <> tags to test how it will be stored in EHR test test <html> testinng <h1> some html </h1> <br> <br> <br></html>
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNtest doctor note with without linebreaks!
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TNApplied
DR DK NANDI'S PRACTICE342 Troy RoadHorsforthLeedsWest YorkshireLS18 5TN ** Care started at DR DK NANDI'S PRACTICE (Applied) **", "attachments": [], "external_attachments": []} \ No newline at end of file