55import static org .springframework .util .CollectionUtils .isEmpty ;
66import static org .springframework .util .CollectionUtils .newHashMap ;
77
8+ import java .time .Duration ;
89import java .time .Instant ;
910import java .util .Collections ;
1011import java .util .List ;
3233import uk .nhs .adaptors .gp2gp .ehr .model .EhrExtractStatus .EhrReceivedAcknowledgement .ErrorDetails ;
3334import uk .nhs .adaptors .gp2gp .gpc .GetGpcStructuredTaskDefinition ;
3435import uk .nhs .adaptors .gp2gp .mhs .exception .MessageOutOfOrderException ;
35- import uk .nhs .adaptors .gp2gp .mhs .exception .NonExistingInteractionIdException ;
36+ import uk .nhs .adaptors .gp2gp .mhs .exception .UnrecognisedInteractionIdException ;
3637
3738@ Service
3839@ Slf4j
@@ -64,7 +65,6 @@ public class EhrExtractStatusService {
6465 private static final String ROOT_ID = "rootId" ;
6566 private static final String CONVERSATION_CLOSED = "conversationClosed" ;
6667 private static final String MESSAGE_REF = "messageRef" ;
67- private static final String EHR_EXTRACT_MESSAGE_REF = "ehrExtractMessageRef" ;
6868 private static final String ERRORS = "errors" ;
6969 private static final String ERROR = "error" ;
7070 private static final String SENT_TO_MHS = "sentToMhs" ;
@@ -114,6 +114,9 @@ public class EhrExtractStatusService {
114114 private static final String CONTENT_TYPE_PLACEHOLDER = "CONTENT_TYPE_PLACEHOLDER_ID=" ;
115115 private static final String FILENAME_TYPE_PLACEHOLDER = "FILENAME_PLACEHOLDER_ID=" ;
116116 private static final String ACKS_SET = ACK_HISTORY + DOT + ACKS ;
117+ public static final int EHR_EXTRACT_SENT_DAYS_LIMIT = 8 ;
118+ private static final String REASON_ERROR_CODE = "04" ;
119+ public static final String REASON_ERROR_MESSAGE = "The acknowledgement has been received after 8 days" ;
117120
118121 private final MongoTemplate mongoTemplate ;
119122 private final EhrExtractStatusRepository ehrExtractStatusRepository ;
@@ -169,8 +172,8 @@ public Map<String, String> fetchDocumentObjectNameAndSize(String conversationId)
169172 }
170173
171174 public EhrExtractStatus updateEhrExtractStatusAccessStructured (
172- GetGpcStructuredTaskDefinition structuredTaskDefinition , String structuredRecordJsonFilename
173- ) {
175+ GetGpcStructuredTaskDefinition structuredTaskDefinition , String structuredRecordJsonFilename ) {
176+
174177 Query query = createQueryForConversationId (structuredTaskDefinition .getConversationId ());
175178 Instant now = Instant .now ();
176179
@@ -196,8 +199,8 @@ public EhrExtractStatus updateEhrExtractStatusAccessDocument(
196199 String storagePath ,
197200 int base64ContentLength ,
198201 String errorMessage ,
199- String filename
200- ) {
202+ String filename ) {
203+
201204 Query query = new Query ();
202205 query .addCriteria (Criteria
203206 .where (CONVERSATION_ID ).is (documentTaskDefinition .getConversationId ())
@@ -228,8 +231,8 @@ public EhrExtractStatus updateEhrExtractStatusAccessDocument(
228231
229232 public EhrExtractStatus updateEhrExtractStatusCore (
230233 SendEhrExtractCoreTaskDefinition sendEhrExtractCoreTaskDefinition ,
231- Instant requestSentAt
232- ) {
234+ Instant requestSentAt ) {
235+
233236 Query query = createQueryForConversationId (sendEhrExtractCoreTaskDefinition .getConversationId ());
234237
235238 Update update = createUpdateWithUpdatedAt ();
@@ -250,8 +253,8 @@ public EhrExtractStatus updateEhrExtractStatusCore(
250253
251254 public void updateEhrExtractStatusCorePending (
252255 SendEhrExtractCoreTaskDefinition sendEhrExtractCoreTaskDefinition ,
253- Instant requestSentAt
254- ) {
256+ Instant requestSentAt ) {
257+
255258 Query query = createQueryForConversationId (sendEhrExtractCoreTaskDefinition .getConversationId ());
256259
257260 Update update = createUpdateWithUpdatedAt ();
@@ -267,6 +270,7 @@ public void updateEhrExtractStatusCorePending(
267270 }
268271
269272 public Optional <EhrExtractStatus > updateEhrExtractStatusContinue (String conversationId ) {
273+
270274 var isDuplicate = checkForContinueOutOfOrderAndDuplicate (conversationId );
271275 if (!isDuplicate ) {
272276 Query query = createQueryForConversationId (conversationId );
@@ -305,6 +309,14 @@ public void updateEhrExtractStatusAck(String conversationId, EhrReceivedAcknowle
305309 return ;
306310 }
307311
312+ if (hasAcknowledgementExceededEightDays (conversationId , ack .getReceived ())) {
313+ updateEhrExtractStatusError (conversationId ,
314+ REASON_ERROR_CODE ,
315+ REASON_ERROR_MESSAGE ,
316+ this .getClass ().getSimpleName ());
317+ return ;
318+ }
319+
308320 Query query = createQueryForConversationId (conversationId );
309321
310322 Update update = createUpdateWithUpdatedAt ();
@@ -356,8 +368,7 @@ public void saveAckForConversation(String conversationId, EhrReceivedAcknowledge
356368
357369 public void updateEhrExtractStatusAccessDocumentDocumentReferences (
358370 String conversationId ,
359- List <EhrExtractStatus .GpcDocument > documents
360- ) {
371+ List <EhrExtractStatus .GpcDocument > documents ) {
361372 Query query = createQueryForConversationId (conversationId );
362373
363374 Update .AddToSetBuilder updateBuilder = createUpdateWithUpdatedAt ().addToSet (GPC_DOCUMENTS );
@@ -371,8 +382,7 @@ private void getEhrExtractStatus(
371382 Query query ,
372383 List <EhrExtractStatus .GpcDocument > docs ,
373384 Update .AddToSetBuilder updateBuilder ,
374- FindAndModifyOptions returningUpdatedRecordOption
375- ) {
385+ FindAndModifyOptions returningUpdatedRecordOption ) {
376386 Update update = updateBuilder .each (docs );
377387
378388 EhrExtractStatus ehrExtractStatus = mongoTemplate .findAndModify (query ,
@@ -402,8 +412,8 @@ public void updateEhrExtractStatusAcknowledgement(
402412 public void updateEhrExtractStatusAcknowledgement (
403413 SendAcknowledgementTaskDefinition taskDefinition ,
404414 String ackMessageId ,
405- String updatedAt
406- ) {
415+ String updatedAt ) {
416+
407417 Update update = createUpdateWithUpdatedAt ();
408418 update .set (ACK_PENDING_TASK_ID_PATH , taskDefinition .getTaskId ());
409419 update .set (ACK_PENDING_MESSAGE_ID_PATH , ackMessageId );
@@ -417,8 +427,8 @@ public EhrExtractStatus updateEhrExtractStatusError(
417427 String conversationId ,
418428 String errorCode ,
419429 String errorMessage ,
420- String taskType
421- ) {
430+ String taskType ) {
431+
422432 Update update = createUpdateWithUpdatedAt ();
423433 Instant now = Instant .now ();
424434 update .set (ERROR_OCCURRED_AT_PATH , now );
@@ -571,23 +581,29 @@ private Update createUpdateWithUpdatedAt() {
571581 return update ;
572582 }
573583
574- private boolean isEhrStatusWaitingForFinalAck (String conversationId ) {
575- var ehrExtractStatus = ehrExtractStatusRepository .findByConversationId (conversationId )
576- .orElseThrow (() -> new NonExistingInteractionIdException ("ACK" , conversationId ));
584+ protected boolean isEhrStatusWaitingForFinalAck (String conversationId ) {
585+ var ehrExtractStatus = fetchEhrExtractStatus (conversationId , "ACK" );
577586
578587 return ehrExtractStatus .getAckPending () != null ;
579588 }
580589
581- private boolean hasFinalAckBeenReceived (String conversationId ) {
582- var ehrExtractStatus = ehrExtractStatusRepository .findByConversationId (conversationId )
583- .orElseThrow (() -> new NonExistingInteractionIdException ("ACK" , conversationId ));
590+ protected boolean hasFinalAckBeenReceived (String conversationId ) {
591+ var ehrExtractStatus = fetchEhrExtractStatus (conversationId , "ACK" );
584592
585593 return ehrExtractStatus .getEhrReceivedAcknowledgement () != null ;
586594 }
587595
596+ private boolean hasAcknowledgementExceededEightDays (String conversationId , Instant ackReceivedTimestamp ) {
597+ var ehrExtractStatus = fetchEhrExtractStatus (conversationId , "ACK" );
598+
599+ Duration duration = Duration .between (ehrExtractStatus .getUpdatedAt (), ackReceivedTimestamp );
600+ long daysSinceLastUpdate = duration .toDays ();
601+
602+ return daysSinceLastUpdate > EHR_EXTRACT_SENT_DAYS_LIMIT ;
603+ }
604+
588605 private boolean checkForContinueOutOfOrderAndDuplicate (String conversationId ) {
589- var ehrExtractStatus = ehrExtractStatusRepository .findByConversationId (conversationId )
590- .orElseThrow (() -> new NonExistingInteractionIdException ("Continue" , conversationId ));
606+ var ehrExtractStatus = fetchEhrExtractStatus (conversationId , "Continue" );
591607
592608 if (ehrExtractStatus .getEhrExtractCorePending () == null ) {
593609 throw new MessageOutOfOrderException ("Continue" , conversationId );
@@ -601,4 +617,9 @@ private boolean checkForContinueOutOfOrderAndDuplicate(String conversationId) {
601617
602618 return false ;
603619 }
620+
621+ private EhrExtractStatus fetchEhrExtractStatus (String conversationId , String messageType ) {
622+ return ehrExtractStatusRepository .findByConversationId (conversationId )
623+ .orElseThrow (() -> new UnrecognisedInteractionIdException (messageType , conversationId ));
624+ }
604625}
0 commit comments