From 13fc272faf0e9fdd0c9ea6d320310d35fca3e8b6 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Wed, 9 Jul 2025 15:20:05 +0100 Subject: [PATCH 01/10] CCM-10447: update for new failed reason codes --- sandbox/messages/2WL45YuHOLATvC3GspEu0oSioux.json | 2 ++ sandbox/messages/2WL4JtCiOe7l2TT4szwPjNJah3z.json | 2 ++ sandbox/messages/2WL4MOuSeCTODDAScFG7KIq9a5r.json | 2 ++ sandbox/messages/2WL4QcKGjNHvHFQeKgYbapZJGHK.json | 1 + sandbox/messages/2WL4W9RgbuLLByXdR77H8vjKSDd.json | 2 ++ sandbox/messages/2WL4cPfBRuPKa44JxhyXYf2kr1E.json | 1 + sandbox/messages/2WL4ibGoigirgbH4yQwqbPaJXyQ.json | 1 + sandbox/messages/2WL4khXn32dOOj4bB4bi8Tkllrq.json | 1 + sandbox/messages/2WL4mvx6eBva8dcIK60VEGIfcgZ.json | 1 + sandbox/messages/2WL4pcpmKxYYblm3PSKVEqcmEPX.json | 1 + sandbox/messages/2WL4vHFZzInmaYwq6HRNDqTX8dH.json | 2 ++ sandbox/messages/2WL4xcWKvz4F32g0htBEl8DINzn.json | 2 ++ sandbox/messages/2WL50w41YaZXcyFCNT346LY8rlz.json | 2 ++ sandbox/messages/2WL54x0XQjCbWeE5lN0DKQZcokU.json | 2 ++ sandbox/messages/2WL5eDefrbW31uw1il84WdF8ndH.json | 1 + sandbox/messages/2WL5eYSWGzCHlGmzNxuqVusPxDg.json | 2 ++ sandbox/messages/2WL5f8j4XVxUPgd3OOqXVYvVFIW.json | 3 +++ sandbox/messages/2bBBpsiMl2rnQt99qm6JLZ6w1vq.json | 2 ++ specification/documentation/GetMessage.md | 1 + specification/schemas/components/MessageStatus.yaml | 4 ++++ specification/schemas/components/SupplierStatus.yaml | 4 ++++ specification/schemas/responses/MessageResponse.yaml | 8 ++++++++ 22 files changed, 47 insertions(+) diff --git a/sandbox/messages/2WL45YuHOLATvC3GspEu0oSioux.json b/sandbox/messages/2WL45YuHOLATvC3GspEu0oSioux.json index 982977cee..c7b0a922e 100644 --- a/sandbox/messages/2WL45YuHOLATvC3GspEu0oSioux.json +++ b/sandbox/messages/2WL45YuHOLATvC3GspEu0oSioux.json @@ -12,6 +12,7 @@ "messageReference": "d1cc6082-729e-4e31-8842-ac3279d3f72d", "messageStatus": "failed", "messageStatusDescription": "Failed reason: NHS number not found", + "messageFailureReasonCode": "MFR_PDSV_0004", "channels": [ { "type": "nhsapp", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: NHS number not found", + "channelFailureReasonCode": "CFR_PDSV_0004", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4JtCiOe7l2TT4szwPjNJah3z.json b/sandbox/messages/2WL4JtCiOe7l2TT4szwPjNJah3z.json index 5918c3c47..524dc421a 100644 --- a/sandbox/messages/2WL4JtCiOe7l2TT4szwPjNJah3z.json +++ b/sandbox/messages/2WL4JtCiOe7l2TT4szwPjNJah3z.json @@ -12,6 +12,7 @@ "messageReference": "e21cd9c0-75af-4596-9e9a-57fa7581fe59", "messageStatus": "failed", "messageStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s phone is off, has no signal, or their text message inbox is full. You can try to send the message again. You’ll still be charged for text messages to phones that are not accepting messages.", + "messageFailureReasonCode": "MFR_SUPE_0007", "channels": [ { "type": "sms", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s phone is off, has no signal, or their text message inbox is full. You can try to send the message again. You’ll still be charged for text messages to phones that are not accepting messages.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4MOuSeCTODDAScFG7KIq9a5r.json b/sandbox/messages/2WL4MOuSeCTODDAScFG7KIq9a5r.json index 616392db6..a8ee0d575 100644 --- a/sandbox/messages/2WL4MOuSeCTODDAScFG7KIq9a5r.json +++ b/sandbox/messages/2WL4MOuSeCTODDAScFG7KIq9a5r.json @@ -12,6 +12,7 @@ "messageReference": "b9603694-5542-4043-b905-1e570b26d4c2", "messageStatus": "failed", "messageStatusDescription": "Failed reason: We had an unexpected error while sending the letter to our printing provider.", + "messageFailureReasonCode": "MFR_SUPE_0007", "channels": [ { "type": "letter", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: We had an unexpected error while sending the letter to our printing provider.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4QcKGjNHvHFQeKgYbapZJGHK.json b/sandbox/messages/2WL4QcKGjNHvHFQeKgYbapZJGHK.json index f974985db..7e95f8003 100644 --- a/sandbox/messages/2WL4QcKGjNHvHFQeKgYbapZJGHK.json +++ b/sandbox/messages/2WL4QcKGjNHvHFQeKgYbapZJGHK.json @@ -12,6 +12,7 @@ "messageReference": "4fbc5f73-0f7c-4304-b848-5c6ccb781c84", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Patient does not exist in PDS", + "messageFailureReasonCode": "MFR_PDSV_0006", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:40Z", diff --git a/sandbox/messages/2WL4W9RgbuLLByXdR77H8vjKSDd.json b/sandbox/messages/2WL4W9RgbuLLByXdR77H8vjKSDd.json index 175de6674..af791ce1a 100644 --- a/sandbox/messages/2WL4W9RgbuLLByXdR77H8vjKSDd.json +++ b/sandbox/messages/2WL4W9RgbuLLByXdR77H8vjKSDd.json @@ -12,6 +12,7 @@ "messageReference": "0397b134-e30d-4fb1-9060-0d204b0ac340", "messageStatus": "failed", "messageStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s inbox is full or their anti-spam filter rejects your email. Check your content does not look like spam before you try to send the message again.", + "messageFailureReasonCode": "MFR_SUPE_0007", "channels": [ { "type": "email", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s inbox is full or their anti-spam filter rejects your email. Check your content does not look like spam before you try to send the message again.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4cPfBRuPKa44JxhyXYf2kr1E.json b/sandbox/messages/2WL4cPfBRuPKa44JxhyXYf2kr1E.json index 4a3a5f5f2..47dab6ed4 100644 --- a/sandbox/messages/2WL4cPfBRuPKa44JxhyXYf2kr1E.json +++ b/sandbox/messages/2WL4cPfBRuPKa44JxhyXYf2kr1E.json @@ -12,6 +12,7 @@ "messageReference": "d85be1f0-1593-41b0-94d2-beae6ee7dcc0", "messageStatus": "failed", "messageStatusDescription": "Failed reason: patient record invalidated", + "messageFailureReasonCode": "MFR_PDSV_0008", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:45Z", diff --git a/sandbox/messages/2WL4ibGoigirgbH4yQwqbPaJXyQ.json b/sandbox/messages/2WL4ibGoigirgbH4yQwqbPaJXyQ.json index a6cf99899..ff33d5031 100644 --- a/sandbox/messages/2WL4ibGoigirgbH4yQwqbPaJXyQ.json +++ b/sandbox/messages/2WL4ibGoigirgbH4yQwqbPaJXyQ.json @@ -12,6 +12,7 @@ "messageReference": "2f2e071c-9fba-4dde-bf8d-8dd0c8060300", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Patient is formally dead", + "messageFailureReasonCode": "MFR_PDSV_0112", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4khXn32dOOj4bB4bi8Tkllrq.json b/sandbox/messages/2WL4khXn32dOOj4bB4bi8Tkllrq.json index caa3424f1..7c7918a15 100644 --- a/sandbox/messages/2WL4khXn32dOOj4bB4bi8Tkllrq.json +++ b/sandbox/messages/2WL4khXn32dOOj4bB4bi8Tkllrq.json @@ -12,6 +12,7 @@ "messageReference": "68cc8e05-c404-405a-a41d-92cdb8afd9e3", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Patient is informally dead", + "messageFailureReasonCode": "MFR_PDSV_0111", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4mvx6eBva8dcIK60VEGIfcgZ.json b/sandbox/messages/2WL4mvx6eBva8dcIK60VEGIfcgZ.json index b91abd6e7..04e3a74a1 100644 --- a/sandbox/messages/2WL4mvx6eBva8dcIK60VEGIfcgZ.json +++ b/sandbox/messages/2WL4mvx6eBva8dcIK60VEGIfcgZ.json @@ -12,6 +12,7 @@ "messageReference": "1791d23b-6f5d-4153-ab45-637bd7711d41", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Patient has exit code", + "messageFailureReasonCode": "MFR_PDSV_0110", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4pcpmKxYYblm3PSKVEqcmEPX.json b/sandbox/messages/2WL4pcpmKxYYblm3PSKVEqcmEPX.json index 1a0e5d2a4..57d589cfd 100644 --- a/sandbox/messages/2WL4pcpmKxYYblm3PSKVEqcmEPX.json +++ b/sandbox/messages/2WL4pcpmKxYYblm3PSKVEqcmEPX.json @@ -12,6 +12,7 @@ "messageReference": "2c98d875-3843-4919-9c79-2034e957e251", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Name response is invalid: Contact detail is malformed", + "messageFailureReasonCode": "MFR_PDSV_0001", "timestamps": { "created": "2023-10-09T10:31:37Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4vHFZzInmaYwq6HRNDqTX8dH.json b/sandbox/messages/2WL4vHFZzInmaYwq6HRNDqTX8dH.json index c0ce57f50..90564ad92 100644 --- a/sandbox/messages/2WL4vHFZzInmaYwq6HRNDqTX8dH.json +++ b/sandbox/messages/2WL4vHFZzInmaYwq6HRNDqTX8dH.json @@ -12,6 +12,7 @@ "messageReference": "d1cc6082-729e-4e31-8842-ac3279d3f72d", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Contact detail is missing", + "messageFailureReasonCode": "MFR_PDSV_0002", "channels": [ { "type": "nhsapp", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: Contact detail is missing", + "channelFailureReasonCode": "CFR_PDSV_0002", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL4xcWKvz4F32g0htBEl8DINzn.json b/sandbox/messages/2WL4xcWKvz4F32g0htBEl8DINzn.json index a68314f68..56fa095b3 100644 --- a/sandbox/messages/2WL4xcWKvz4F32g0htBEl8DINzn.json +++ b/sandbox/messages/2WL4xcWKvz4F32g0htBEl8DINzn.json @@ -12,6 +12,7 @@ "messageReference": "0b88296d-b7e3-4697-be86-7424444a205c", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Contact detail is missing", + "messageFailureReasonCode": "MFR_PDSV_0002", "channels": [ { "type": "email", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: Contact detail is missing", + "channelFailureReasonCode": "CFR_PDSV_0002", "timestamps": { "created": "2023-10-09T10:31:59Z", "failed": "2023-10-09T10:52:12Z" diff --git a/sandbox/messages/2WL50w41YaZXcyFCNT346LY8rlz.json b/sandbox/messages/2WL50w41YaZXcyFCNT346LY8rlz.json index 62989c7e2..4d20d03cb 100644 --- a/sandbox/messages/2WL50w41YaZXcyFCNT346LY8rlz.json +++ b/sandbox/messages/2WL50w41YaZXcyFCNT346LY8rlz.json @@ -12,6 +12,7 @@ "messageReference": "7b2be2cf-7e59-4b15-b199-fd4ba0cb9f19", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Contact detail is missing", + "messageFailureReasonCode": "MFR_PDSV_0002", "channels": [ { "type": "sms", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: Contact detail is missing", + "channelFailureReasonCode": "CFR_PDSV_0002", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL54x0XQjCbWeE5lN0DKQZcokU.json b/sandbox/messages/2WL54x0XQjCbWeE5lN0DKQZcokU.json index 130c573ca..eaaae732c 100644 --- a/sandbox/messages/2WL54x0XQjCbWeE5lN0DKQZcokU.json +++ b/sandbox/messages/2WL54x0XQjCbWeE5lN0DKQZcokU.json @@ -12,6 +12,7 @@ "messageReference": "1226417c-f683-4d68-afe8-2d52321a6b70", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Contact detail is missing", + "messageFailureReasonCode": "MFR_PDSV_0002", "channels": [ { "type": "letter", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: Contact detail is missing", + "channelFailureReasonCode": "CFR_PDSV_0002", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:31:59Z", diff --git a/sandbox/messages/2WL5eDefrbW31uw1il84WdF8ndH.json b/sandbox/messages/2WL5eDefrbW31uw1il84WdF8ndH.json index ad23c63ff..212b1f1a8 100644 --- a/sandbox/messages/2WL5eDefrbW31uw1il84WdF8ndH.json +++ b/sandbox/messages/2WL5eDefrbW31uw1il84WdF8ndH.json @@ -19,6 +19,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: NHS number not found", + "channelFailureReasonCode": "CFR_PDSV_0004", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", diff --git a/sandbox/messages/2WL5eYSWGzCHlGmzNxuqVusPxDg.json b/sandbox/messages/2WL5eYSWGzCHlGmzNxuqVusPxDg.json index c47119991..3db4df677 100644 --- a/sandbox/messages/2WL5eYSWGzCHlGmzNxuqVusPxDg.json +++ b/sandbox/messages/2WL5eYSWGzCHlGmzNxuqVusPxDg.json @@ -19,6 +19,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: NHS number not found", + "channelFailureReasonCode": "CFR_PDSV_0004", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", @@ -37,6 +38,7 @@ "cascadeOrder": 2, "channelStatus": "failed", "channelStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s inbox is full or their anti-spam filter rejects your email. Check your content does not look like spam before you try to send the message again.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", diff --git a/sandbox/messages/2WL5f8j4XVxUPgd3OOqXVYvVFIW.json b/sandbox/messages/2WL5f8j4XVxUPgd3OOqXVYvVFIW.json index 9fb11c5de..126ce0165 100644 --- a/sandbox/messages/2WL5f8j4XVxUPgd3OOqXVYvVFIW.json +++ b/sandbox/messages/2WL5f8j4XVxUPgd3OOqXVYvVFIW.json @@ -19,6 +19,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: NHS number not found", + "channelFailureReasonCode": "CFR_PDSV_0004", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", @@ -37,6 +38,7 @@ "cascadeOrder": 2, "channelStatus": "failed", "channelStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s inbox is full or their anti-spam filter rejects your email. Check your content does not look like spam before you try to send the message again.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", @@ -55,6 +57,7 @@ "cascadeOrder": 3, "channelStatus": "failed", "channelStatusDescription": "Failed reason: The provider could not deliver the message. This can happen when the recipient’s phone is off, has no signal, or their text message inbox is full. You can try to send the message again. You’ll still be charged for text messages to phones that are not accepting messages.", + "channelFailureReasonCode": "CFR_SUPE_0007", "timestamps": { "created": "2023-10-09T10:31:59Z", "enriched": "2023-10-09T10:39:37Z", diff --git a/sandbox/messages/2bBBpsiMl2rnQt99qm6JLZ6w1vq.json b/sandbox/messages/2bBBpsiMl2rnQt99qm6JLZ6w1vq.json index 9887387c4..2bfa6ea3d 100644 --- a/sandbox/messages/2bBBpsiMl2rnQt99qm6JLZ6w1vq.json +++ b/sandbox/messages/2bBBpsiMl2rnQt99qm6JLZ6w1vq.json @@ -12,6 +12,7 @@ "messageReference": "1226417c-f683-4d68-afe8-2d52321a6b70", "messageStatus": "failed", "messageStatusDescription": "Failed reason: Contact detail is missing", + "messageFailureReasonCode": "MFR_PDSV_0002", "channels": [ { "type": "sms", @@ -20,6 +21,7 @@ "cascadeOrder": 1, "channelStatus": "failed", "channelStatusDescription": "Failed reason: Contact detail is missing", + "channelFailureReasonCode": "CFR_PDSV_0002", "timestamps": { "created": "2023-10-09T10:31:59Z", "failed": "2023-10-09T10:52:12Z" diff --git a/specification/documentation/GetMessage.md b/specification/documentation/GetMessage.md index e60a98f3e..c0b97f44d 100644 --- a/specification/documentation/GetMessage.md +++ b/specification/documentation/GetMessage.md @@ -22,6 +22,7 @@ Key values that are returned for each of these channels are: * `type` - the channel type * `channelStatus` - the status of that channel * `channelStatusDescription` - the channel status description +* `channelFailureReasonCode` - the channel failed reason code * `supplierStatus` - the status provided by the supplier for this channel * `retryCount` - the number of times we have attempted delivery * `timestamps` - timestamps of key events diff --git a/specification/schemas/components/MessageStatus.yaml b/specification/schemas/components/MessageStatus.yaml index dd9f9891a..e4c290dd3 100644 --- a/specification/schemas/components/MessageStatus.yaml +++ b/specification/schemas/components/MessageStatus.yaml @@ -19,6 +19,10 @@ properties: type: string description: If there is extra information associated with the status of this message, it is provided here. example: " " + messageFailureReasonCode: + type: string + description: If there is a failed reason code associated with this message, it is provided here. + example: "MFR_PDSV_0005" channels: type: array minItems: 0 diff --git a/specification/schemas/components/SupplierStatus.yaml b/specification/schemas/components/SupplierStatus.yaml index 3aac5052f..307e836ce 100644 --- a/specification/schemas/components/SupplierStatus.yaml +++ b/specification/schemas/components/SupplierStatus.yaml @@ -31,6 +31,10 @@ properties: type: string description: If there is extra information associated with the status of this channel, it is provided here. example: " " + channelFailureReasonCode: + type: string + description: If there is a failed reason code associated with this channel, it is provided here. + example: "CFR_PDSV_0005" supplierStatus: $ref: ../enums/SupplierStatusEnum.yaml timestamp: diff --git a/specification/schemas/responses/MessageResponse.yaml b/specification/schemas/responses/MessageResponse.yaml index 56251854a..b4473af6b 100644 --- a/specification/schemas/responses/MessageResponse.yaml +++ b/specification/schemas/responses/MessageResponse.yaml @@ -26,6 +26,10 @@ properties: type: string description: If there is extra information associated with the status of this message, it is provided here. example: "" + messageFailureReasonCode: + type: string + description: If there is a failed reason code associated with this message, it is provided here. + example: "MFR_PDSV_0005" channels: type: array description: |- @@ -55,6 +59,10 @@ properties: type: string description: If there is extra information associated with the status of this channel, it is provided here. example: "" + channelFailureReasonCode: + type: string + description: If there is a failed reason code associated with this channel, it is provided here. + example: "MFR_DSV_0005" supplierStatus: description: |- The current status of this message within the channel at the time this response was generated. From 513e61ef80a7976ac3ef74b3fc42e1ca3a79ce17 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Thu, 10 Jul 2025 08:50:41 +0100 Subject: [PATCH 02/10] CCM-10447: fix sonar scan error --- scripts/perform-static-analysis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/perform-static-analysis.sh b/scripts/perform-static-analysis.sh index 89a0cb595..452b37d00 100755 --- a/scripts/perform-static-analysis.sh +++ b/scripts/perform-static-analysis.sh @@ -18,7 +18,7 @@ set -e # ============================================================================== # SEE: https://hub.docker.com/r/sonarsource/sonar-scanner-cli/tags, use the `linux/amd64` os/arch -image_version=5.0.1@sha256:494ecc3b5b1ee1625bd377b3905c4284e4f0cc155cff397805a244dee1c7d575 +image_version=11.3@sha256:7462f132388135e32b948f8f18ff0db9ae28a87c6777f1df5b2207e04a6d7c5c # ============================================================================== From 093c496ac8f9d090cd22c201118dd06486362d34 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Thu, 10 Jul 2025 09:21:36 +0100 Subject: [PATCH 03/10] CCM-10447: amend documentation examples --- specification/schemas/components/MessageStatus.yaml | 4 ++-- specification/schemas/components/SupplierStatus.yaml | 4 ++-- specification/schemas/responses/MessageResponse.yaml | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/specification/schemas/components/MessageStatus.yaml b/specification/schemas/components/MessageStatus.yaml index e4c290dd3..9ec05ebe4 100644 --- a/specification/schemas/components/MessageStatus.yaml +++ b/specification/schemas/components/MessageStatus.yaml @@ -18,11 +18,11 @@ properties: messageStatusDescription: type: string description: If there is extra information associated with the status of this message, it is provided here. - example: " " + example: "Failed reason: Contact detail is missing" messageFailureReasonCode: type: string description: If there is a failed reason code associated with this message, it is provided here. - example: "MFR_PDSV_0005" + example: "MFR_PDSV_0002" channels: type: array minItems: 0 diff --git a/specification/schemas/components/SupplierStatus.yaml b/specification/schemas/components/SupplierStatus.yaml index 307e836ce..fc804ab7f 100644 --- a/specification/schemas/components/SupplierStatus.yaml +++ b/specification/schemas/components/SupplierStatus.yaml @@ -30,11 +30,11 @@ properties: channelStatusDescription: type: string description: If there is extra information associated with the status of this channel, it is provided here. - example: " " + example: "Failed reason: Contact detail is missing" channelFailureReasonCode: type: string description: If there is a failed reason code associated with this channel, it is provided here. - example: "CFR_PDSV_0005" + example: "CFR_PDSV_0002" supplierStatus: $ref: ../enums/SupplierStatusEnum.yaml timestamp: diff --git a/specification/schemas/responses/MessageResponse.yaml b/specification/schemas/responses/MessageResponse.yaml index b4473af6b..a3fc84126 100644 --- a/specification/schemas/responses/MessageResponse.yaml +++ b/specification/schemas/responses/MessageResponse.yaml @@ -25,11 +25,11 @@ properties: messageStatusDescription: type: string description: If there is extra information associated with the status of this message, it is provided here. - example: "" + example: "Failed reason: Contact detail is missing" messageFailureReasonCode: type: string description: If there is a failed reason code associated with this message, it is provided here. - example: "MFR_PDSV_0005" + example: "MFR_PDSV_0002" channels: type: array description: |- @@ -58,11 +58,11 @@ properties: channelStatusDescription: type: string description: If there is extra information associated with the status of this channel, it is provided here. - example: "" + example: "Failed reason: Contact detail is missing" channelFailureReasonCode: type: string description: If there is a failed reason code associated with this channel, it is provided here. - example: "MFR_DSV_0005" + example: "CFR_PDSV_0002" supplierStatus: description: |- The current status of this message within the channel at the time this response was generated. From 436221a19b3256114c041510a0d05c6aa70300f1 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Tue, 15 Jul 2025 16:35:43 +0100 Subject: [PATCH 04/10] CCM-10448: add an e2e test for a failed message --- .../test_invalid_end_to_end_internal_dev.rst | 11 +++ .../test_invalid_end_to_end_uat.rst | 11 +++ tests/end_to_end/test_failure.py | 71 +++++++++++++++++++ tests/lib/assertions.py | 19 ++--- tests/lib/generators.py | 46 ++++++++++++ tests/lib/helper.py | 4 -- 6 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst create mode 100644 tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst create mode 100644 tests/end_to_end/test_failure.py diff --git a/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst b/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst new file mode 100644 index 000000000..890f77041 --- /dev/null +++ b/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst @@ -0,0 +1,11 @@ +Scenario: An API consumer sending a request with an invalid message sees the request transition to a failed status in the Internal Dev environment +================================================================================================================================================== + +| **Given** the API consumer submits a request with an invalid message +| **When** the request is submitted +| **Then** the response is a 201 success +| **And** the request transitions to a failed status + +**Asserts** +- Response returns a 201 status code +- Message is present in NHS Notify as failed diff --git a/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst b/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst new file mode 100644 index 000000000..a79301e43 --- /dev/null +++ b/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst @@ -0,0 +1,11 @@ +Scenario: An API consumer sending a request with an invalid message sees the request transition to a failed status in the uat environment +========================================================================================================================================= + +| **Given** the API consumer submits a request with an invalid message +| **When** the request is submitted +| **Then** the response is a 201 success +| **And** the request transitions to a failed status + +**Asserts** +- Response returns a 201 status code +- Message is present in NHS Notify as failed diff --git a/tests/end_to_end/test_failure.py b/tests/end_to_end/test_failure.py new file mode 100644 index 000000000..d7b7fe6ed --- /dev/null +++ b/tests/end_to_end/test_failure.py @@ -0,0 +1,71 @@ +import pytest +import os +from lib import Assertions, Helper, Generators +from lib.fixtures import * # NOSONAR +from notifications_python_client.notifications import NotificationsAPIClient + + +@pytest.mark.e2e +@pytest.mark.devtest +def test_invalid_end_to_end_internal_dev(url, bearer_token): + """ + .. include:: ../../partials/happy_path/test_invalid_end_to_end_internal_dev.rst + """ + headers = Generators.generate_valid_headers(bearer_token.value) + + resp = Helper.send_single_message( + url, headers, Generators.generate_invalid_send_message_body("email", "internal-dev") + ) + + message_id = resp.json().get("data").get("id") + + Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") + + resp = Helper.get_message(url, headers, message_id) + + Assertions.assert_get_message_status( + resp, + "failed", + "Failed reason: No valid request item plans were generated", + "MFR_CFGV_0005" + ) + + Assertions.assert_get_message_response_channels( + resp, + "failed", + "Failed reason: Alternative contact detail is malformed", + "CFR_CLIV_0001", + ) + + +@pytest.mark.e2e +@pytest.mark.uattest +def test_invalid_end_to_end_uat(url, bearer_token): + """ + .. include:: ../../partials/happy_path/test_invalid_end_to_end_uat.rst + """ + headers = Generators.generate_valid_headers(bearer_token.value) + + resp = Helper.send_single_message( + url, headers, Generators.generate_invalid_send_message_body("email", "internal-qa") + ) + + message_id = resp.json().get("data").get("id") + + Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") + + resp = Helper.get_message(url, headers, message_id) + + Assertions.assert_get_message_status( + resp, + "failed", + "Failed reason: No valid request item plans were generated", + "MFR_CFGV_0005" + ) + + Assertions.assert_get_message_response_channels( + resp, + "failed", + "Failed reason: Alternative contact detail is malformed", + "CFR_CLIV_0001", + ) diff --git a/tests/lib/assertions.py b/tests/lib/assertions.py index 5a36ef5aa..d76cbbafd 100644 --- a/tests/lib/assertions.py +++ b/tests/lib/assertions.py @@ -139,24 +139,25 @@ def assert_200_response_message(resp, base_url): assert response.get("links").get("self").endswith(f"/v1/messages/{response.get('id')}") @staticmethod - def assert_get_message_status(resp, status, failure_reason=None): + def assert_get_message_status(resp, status, failure_reason=None, failure_reason_code=None): response = resp.json().get("data") assert response.get("attributes").get("messageStatus") == status if status == "failed": assert response.get("attributes").get("messageStatusDescription") == failure_reason + assert response.get("attributes").get("messageFailureReasonCode") == failure_reason_code @staticmethod - def assert_get_message_response_channels(resp, channel_type, channel_status): + def assert_get_message_response_channels(resp, status, failure_reason=None, failure_reason_code=None): response = resp.json().get("data") channels = response.get("attributes").get("channels") for c in range(len(channels)): - assert response.get("attributes").get("channels")[c].get("type") in channel_type - assert response.get("attributes").get("channels")[c].get("retryCount") == 1 - assert response.get("attributes").get("channels")[c].get("channelStatus") in channel_status - assert response.get("attributes").get("channels")[c].get("timestamps") is not None - assert response.get("attributes").get("channels")[c].get("routingPlan") is not None - assert response.get("attributes").get("channels")[c].get("cascadeType") in ["primary", "secondary"] - assert response.get("attributes").get("channels")[c].get("cascadeOrder") is not None + assert response.get("attributes").get("channels")[c].get("channelStatus") == status + if status == "failed": + assert response.get("attributes").get("channels")[c].get("channelStatusDescription") == failure_reason + assert ( + response.get("attributes").get("channels")[c].get("channelFailureReasonCode") + == failure_reason_code + ) @staticmethod def assert_201_response_messages(resp, environment): diff --git a/tests/lib/generators.py b/tests/lib/generators.py index cd47caaeb..425be7ccc 100644 --- a/tests/lib/generators.py +++ b/tests/lib/generators.py @@ -122,6 +122,52 @@ def generate_send_message_body(channel, environment, personalisation="Hello"): } } + @staticmethod + def generate_invalid_send_message_body(channel, environment, personalisation="Hello"): + if environment == "internal-dev": + nhs_number = "9627193232" + if channel == "nhsapp": + nhs_number = "9842434109" + elif environment == "internal-qa": + nhs_number = "9730617953" + else: + raise ValueError(f"Invalid environment value provided: {environment}") + if channel == "nhsapp": + routing_plan_id = constants.NHS_APP_ROUTING_PLAN + elif channel == "email": + routing_plan_id = constants.EMAIL_ROUTING_PLAN + elif channel == "sms": + routing_plan_id = constants.SMS_ROUTING_PLAN + elif channel == "letter": + routing_plan_id = constants.LETTER_ROUTING_PLAN + else: + raise ValueError(f"Invalid channel value provided: {channel}") + return { + "data": { + "type": "Message", + "attributes": { + "routingPlanId": routing_plan_id, + "messageReference": str(uuid.uuid1()), + "recipient": { + "nhsNumber": nhs_number, + "contactDetails": { + "sms": "aaa", + "email": "aaa", + "address": { + "lines": [] + } + } + }, + "originator": { + "odsCode": "X26" + }, + "personalisation": { + "exampleParameter": personalisation + } + } + } + } + @staticmethod def generate_invalid_value_error(pointer): return Generators.generate_error(constants.ERROR_INVALID_VALUE, source={ diff --git a/tests/lib/helper.py b/tests/lib/helper.py index b958fdfa1..817523a20 100644 --- a/tests/lib/helper.py +++ b/tests/lib/helper.py @@ -45,10 +45,6 @@ def poll_get_message(url, headers, message_id, end_state="delivered", poll_time= message_status = get_message_response.json().get("data").get("attributes").get("messageStatus") time.sleep(10) - if message_status == "failed": - raise ValueError(f"Request ended up in an unexpected state. \ - Message status: {message_status}, Message ID: {message_id}") - if message_status != end_state: raise TimeoutError(f"Request took too long to be processed. \ Message status: {message_status}, Message ID: {message_id}") From 9090e5193a26b1c86c596dddb018e884df66d0d6 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Wed, 16 Jul 2025 10:09:19 +0100 Subject: [PATCH 05/10] CCM-10448: move new e2e test for a failed message --- .../post_v1_message-batches/happy_path.md | 18 +++++++ .../post_v1_single-message/happy_path.md | 18 +++++++ tests/api/message_batches/test_201_success.py | 51 ++++++++++++++++++- tests/api/single_message/test_201_success.py | 47 ++++++++++++++++- ...1_message_batch_terminal_failed_status.rst | 14 +++++ ...st_201_messages_terminal_failed_status.rst | 14 +++++ .../test_invalid_end_to_end_internal_dev.rst | 11 ---- .../test_invalid_end_to_end_uat.rst | 11 ---- tests/lib/generators.py | 46 ----------------- 9 files changed, 160 insertions(+), 70 deletions(-) create mode 100644 tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst create mode 100644 tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst delete mode 100644 tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst delete mode 100644 tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst diff --git a/docs/tests/post_v1_message-batches/happy_path.md b/docs/tests/post_v1_message-batches/happy_path.md index 72b45a85f..abe471534 100644 --- a/docs/tests/post_v1_message-batches/happy_path.md +++ b/docs/tests/post_v1_message-batches/happy_path.md @@ -3,6 +3,24 @@ ## 201 - Success +### Scenario: An API consumer creating a message that has a terminal status of FAILED + +**Given** the API consumer provides valid contact details for the recipient in their new message +
+**When** the request is submitted +
+**Then** the response is a 201 success +
+ +**Asserts** +- Response returns a 201 status code +- Response body matches expected result +- Response contains correctly formatted link to new message URI +- Message in NHS Notify reaches terminal status of FAILED +- Message has expected failure reason and code +- Channel has expected failure reason and code + + ### Scenario: An API consumer creating a batch of messages with an undefined NHS number receives a 201 response **Given** the API consumer does not provide an NHS number for a recipient in their new message batch and the allowAnonymousPatient flag is set to true diff --git a/docs/tests/post_v1_single-message/happy_path.md b/docs/tests/post_v1_single-message/happy_path.md index b9ab4ed7b..0102b47f3 100644 --- a/docs/tests/post_v1_single-message/happy_path.md +++ b/docs/tests/post_v1_single-message/happy_path.md @@ -3,6 +3,24 @@ These tests target the API endpoint POST /v1/messages testing successful responses when valid data is provided. +## Scenario: An API consumer creating a message that has a terminal status of FAILED + +**Given** the API consumer provides valid contact details for the recipient in their new message +
+**When** the request is submitted +
+**Then** the response is a 201 success +
+ +**Asserts** +- Response returns a 201 status code +- Response body matches expected result +- Response contains correctly formatted link to new message URI +- Message in NHS Notify reaches terminal status of FAILED +- Message has expected failure reason and code +- Channel has expected failure reason and code + + ## Scenario: An API consumer creating a message with an undefined NHS number receives a 201 response **Given** the API consumer does not provide an NHS number for the recipient in their new message and the allowAnonymousPatient flag is set to true diff --git a/tests/api/message_batches/test_201_success.py b/tests/api/message_batches/test_201_success.py index 8f738fa09..c76b1dca2 100644 --- a/tests/api/message_batches/test_201_success.py +++ b/tests/api/message_batches/test_201_success.py @@ -1,6 +1,6 @@ import requests import pytest -from lib import Assertions, Generators +from lib import Assertions, Helper, Generators from lib.fixtures import * # NOSONAR from lib.constants.constants import VALID_ACCEPT_HEADERS, DEFAULT_CONTENT_TYPE, \ VALID_CONTENT_TYPE_HEADERS, VALID_NHS_NUMBER, VALID_SMS_NUMBERS @@ -125,3 +125,52 @@ def test_201_message_batch_valid_contact_details( json=data, ) Assertions.assert_201_response(resp, data) + + +@pytest.mark.test +@pytest.mark.devtest +def test_201_message_batch_terminal_failed_status( + url, + bearer_token +): + """ + .. include:: ../partials/happy_path/test_201_message_batch_terminal_failed_status.rst + """ + headers = Generators.generate_valid_headers(bearer_token.value) + data = Generators.generate_valid_create_message_batch_body("dev") + data["data"]["attributes"]["messages"][0]["recipient"].pop("nhsNumber", None) + data["data"]["attributes"]["messages"][0]["recipient"][ + "contactDetails" + ] = { + "name": { + "firstName": "name", + "lastName": "last" + } + } + + resp = requests.post( + f"{url}{MESSAGE_BATCHES_ENDPOINT}", + headers=headers, + json=data, + ) + Assertions.assert_201_response(resp, data) + + message_id = resp.json().get("data").get("attributes").get("messages")[0].get("id") + + Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") + + resp = Helper.get_message(url, headers, message_id) + + Assertions.assert_get_message_status( + resp, + "failed", + "Failed reason: No valid request item plans were generated", + "MFR_CFGV_0005" + ) + + Assertions.assert_get_message_response_channels( + resp, + "failed", + "Failed reason: Not registered with NHS App", + "CFR_SUPE_0001" + ) diff --git a/tests/api/single_message/test_201_success.py b/tests/api/single_message/test_201_success.py index 73f539067..dd6826aae 100644 --- a/tests/api/single_message/test_201_success.py +++ b/tests/api/single_message/test_201_success.py @@ -1,6 +1,6 @@ import requests import pytest -from lib import Assertions, Generators +from lib import Assertions, Helper, Generators from lib.fixtures import * # NOSONAR from lib.constants.messages_paths import MESSAGES_ENDPOINT from lib.constants.constants import VALID_ACCEPT_HEADERS, DEFAULT_CONTENT_TYPE, \ @@ -113,3 +113,48 @@ def test_201_message_valid_contact_details(url, bearer_token, valid_sms_numbers) ) Assertions.assert_201_response_messages(resp, url) + + +@pytest.mark.test +@pytest.mark.devtest +def test_201_message_terminal_failed_status(url, bearer_token): + """ + .. include:: ../partials/happy_path/test_201_messages_terminal_failed_status.rst + """ + headers = Generators.generate_valid_headers(bearer_token.value) + data = Generators.generate_valid_create_message_body("dev") + data["data"]["attributes"]["recipient"].pop("nhsNumber", None) + data["data"]["attributes"]["recipient"]["contactDetails"] = { + "name": { + "firstName": "name", + "lastName": "last" + } + } + + resp = requests.post( + f"{url}{MESSAGES_ENDPOINT}", + headers=headers, + json=data + ) + + Assertions.assert_201_response_messages(resp, url) + + message_id = resp.json().get("data").get("id") + + Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") + + resp = Helper.get_message(url, headers, message_id) + + Assertions.assert_get_message_status( + resp, + "failed", + "Failed reason: No valid request item plans were generated", + "MFR_CFGV_0005" + ) + + Assertions.assert_get_message_response_channels( + resp, + "failed", + "Failed reason: Not registered with NHS App", + "CFR_SUPE_0001" + ) diff --git a/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst b/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst new file mode 100644 index 000000000..bdf378786 --- /dev/null +++ b/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst @@ -0,0 +1,14 @@ +Scenario: An API consumer creating a message that has a terminal status of FAILED +================================================================================= + +| **Given** the API consumer provides valid contact details for the recipient in their new message +| **When** the request is submitted +| **Then** the response is a 201 success + +**Asserts** +- Response returns a 201 status code +- Response body matches expected result +- Response contains correctly formatted link to new message URI +- Message in NHS Notify reaches terminal status of FAILED +- Message has expected failure reason and code +- Channel has expected failure reason and code diff --git a/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst b/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst new file mode 100644 index 000000000..bdf378786 --- /dev/null +++ b/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst @@ -0,0 +1,14 @@ +Scenario: An API consumer creating a message that has a terminal status of FAILED +================================================================================= + +| **Given** the API consumer provides valid contact details for the recipient in their new message +| **When** the request is submitted +| **Then** the response is a 201 success + +**Asserts** +- Response returns a 201 status code +- Response body matches expected result +- Response contains correctly formatted link to new message URI +- Message in NHS Notify reaches terminal status of FAILED +- Message has expected failure reason and code +- Channel has expected failure reason and code diff --git a/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst b/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst deleted file mode 100644 index 890f77041..000000000 --- a/tests/docs/partials/happy_path/test_invalid_end_to_end_internal_dev.rst +++ /dev/null @@ -1,11 +0,0 @@ -Scenario: An API consumer sending a request with an invalid message sees the request transition to a failed status in the Internal Dev environment -================================================================================================================================================== - -| **Given** the API consumer submits a request with an invalid message -| **When** the request is submitted -| **Then** the response is a 201 success -| **And** the request transitions to a failed status - -**Asserts** -- Response returns a 201 status code -- Message is present in NHS Notify as failed diff --git a/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst b/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst deleted file mode 100644 index a79301e43..000000000 --- a/tests/docs/partials/happy_path/test_invalid_end_to_end_uat.rst +++ /dev/null @@ -1,11 +0,0 @@ -Scenario: An API consumer sending a request with an invalid message sees the request transition to a failed status in the uat environment -========================================================================================================================================= - -| **Given** the API consumer submits a request with an invalid message -| **When** the request is submitted -| **Then** the response is a 201 success -| **And** the request transitions to a failed status - -**Asserts** -- Response returns a 201 status code -- Message is present in NHS Notify as failed diff --git a/tests/lib/generators.py b/tests/lib/generators.py index 425be7ccc..cd47caaeb 100644 --- a/tests/lib/generators.py +++ b/tests/lib/generators.py @@ -122,52 +122,6 @@ def generate_send_message_body(channel, environment, personalisation="Hello"): } } - @staticmethod - def generate_invalid_send_message_body(channel, environment, personalisation="Hello"): - if environment == "internal-dev": - nhs_number = "9627193232" - if channel == "nhsapp": - nhs_number = "9842434109" - elif environment == "internal-qa": - nhs_number = "9730617953" - else: - raise ValueError(f"Invalid environment value provided: {environment}") - if channel == "nhsapp": - routing_plan_id = constants.NHS_APP_ROUTING_PLAN - elif channel == "email": - routing_plan_id = constants.EMAIL_ROUTING_PLAN - elif channel == "sms": - routing_plan_id = constants.SMS_ROUTING_PLAN - elif channel == "letter": - routing_plan_id = constants.LETTER_ROUTING_PLAN - else: - raise ValueError(f"Invalid channel value provided: {channel}") - return { - "data": { - "type": "Message", - "attributes": { - "routingPlanId": routing_plan_id, - "messageReference": str(uuid.uuid1()), - "recipient": { - "nhsNumber": nhs_number, - "contactDetails": { - "sms": "aaa", - "email": "aaa", - "address": { - "lines": [] - } - } - }, - "originator": { - "odsCode": "X26" - }, - "personalisation": { - "exampleParameter": personalisation - } - } - } - } - @staticmethod def generate_invalid_value_error(pointer): return Generators.generate_error(constants.ERROR_INVALID_VALUE, source={ From 014cb607f97e0f10a331a5d6732499c851314514 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Wed, 16 Jul 2025 10:26:21 +0100 Subject: [PATCH 06/10] CCM-10448: amend documentation for new e2e test for a failed message --- docs/tests/post_v1_message-batches/happy_path.md | 2 +- docs/tests/post_v1_single-message/happy_path.md | 2 +- .../test_201_message_batch_terminal_failed_status.rst | 2 +- .../happy_path/test_201_messages_terminal_failed_status.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tests/post_v1_message-batches/happy_path.md b/docs/tests/post_v1_message-batches/happy_path.md index abe471534..de6fb4456 100644 --- a/docs/tests/post_v1_message-batches/happy_path.md +++ b/docs/tests/post_v1_message-batches/happy_path.md @@ -5,7 +5,7 @@ ### Scenario: An API consumer creating a message that has a terminal status of FAILED -**Given** the API consumer provides valid contact details for the recipient in their new message +**Given** the API consumer provides details for an unreachable recipient in their new message
**When** the request is submitted
diff --git a/docs/tests/post_v1_single-message/happy_path.md b/docs/tests/post_v1_single-message/happy_path.md index 0102b47f3..97fbffb8b 100644 --- a/docs/tests/post_v1_single-message/happy_path.md +++ b/docs/tests/post_v1_single-message/happy_path.md @@ -5,7 +5,7 @@ These tests target the API endpoint POST /v1/messages testing successful respons ## Scenario: An API consumer creating a message that has a terminal status of FAILED -**Given** the API consumer provides valid contact details for the recipient in their new message +**Given** the API consumer provides details for an unreachable recipient in their new message
**When** the request is submitted
diff --git a/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst b/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst index bdf378786..afe4bf000 100644 --- a/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst +++ b/tests/docs/partials/happy_path/test_201_message_batch_terminal_failed_status.rst @@ -1,7 +1,7 @@ Scenario: An API consumer creating a message that has a terminal status of FAILED ================================================================================= -| **Given** the API consumer provides valid contact details for the recipient in their new message +| **Given** the API consumer provides details for an unreachable recipient in their new message | **When** the request is submitted | **Then** the response is a 201 success diff --git a/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst b/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst index bdf378786..afe4bf000 100644 --- a/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst +++ b/tests/docs/partials/happy_path/test_201_messages_terminal_failed_status.rst @@ -1,7 +1,7 @@ Scenario: An API consumer creating a message that has a terminal status of FAILED ================================================================================= -| **Given** the API consumer provides valid contact details for the recipient in their new message +| **Given** the API consumer provides details for an unreachable recipient in their new message | **When** the request is submitted | **Then** the response is a 201 success From b522254472f4b7ec38d063e9b883ad1ee2fd682d Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Wed, 16 Jul 2025 11:10:18 +0100 Subject: [PATCH 07/10] CCM-10448: repoint backend to de-iaho3 --- proxies/live/apiproxy/targets/target.xml | 12 ++++++++---- ...ssignMessage.MessageBatches.Create.Request.xml | 15 +++++++++++---- .../AssignMessage.Messages.Create.Request.xml | 15 +++++++++++---- .../AssignMessage.Messages.GetSingle.Request.xml | 15 +++++++++++---- .../AssignMessage.NhsAppAccounts.Get.Request.xml | 15 +++++++++++---- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/proxies/live/apiproxy/targets/target.xml b/proxies/live/apiproxy/targets/target.xml index c9c0bfdd3..3e7779475 100644 --- a/proxies/live/apiproxy/targets/target.xml +++ b/proxies/live/apiproxy/targets/target.xml @@ -18,10 +18,14 @@ true - - - - {requestpath} + {% if ENVIRONMENT_TYPE == 'sandbox' %} + + + + {requestpath} + {% else %} + https://comms-apim.de-iaho3.communications.national.nhs.uk + {% endif %} 29000 diff --git a/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml b/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml index 3dfbc673b..21ce497b9 100644 --- a/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml +++ b/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml @@ -16,10 +16,17 @@ target.copy.pathsuffix false - - requestpath - /api/v1/send - + {% if ENVIRONMENT_TYPE == 'sandbox' %} + + requestpath + /api/v1/send + + {% else %} + + target.url + https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/send + + {% endif %} %data.payload# diff --git a/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml b/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml index 2a8e9cd5c..1179f3ba2 100644 --- a/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml +++ b/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml @@ -16,10 +16,17 @@ target.copy.pathsuffix false - - requestpath - /api/v1/messages - + {% if ENVIRONMENT_TYPE == 'sandbox' %} + + requestpath + /api/v1/messages + + {% else %} + + target.url + https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/messages + + {% endif %} %data.payload# diff --git a/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml b/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml index ce54ec959..358278336 100644 --- a/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml +++ b/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml @@ -16,10 +16,17 @@ target.copy.pathsuffix false - - requestpath - - + {% if ENVIRONMENT_TYPE == 'sandbox' %} + + requestpath + + + {% else %} + + target.url + https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/messages/{data.messageId} + + {% endif %}
{backendCorrelationId}
diff --git a/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml b/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml index 6d71f721a..181ec442f 100644 --- a/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml +++ b/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml @@ -16,10 +16,17 @@ target.copy.pathsuffix false - - requestpath - /api/channels/nhsapp/accounts - + {% if ENVIRONMENT_TYPE == 'sandbox' %} + + requestpath + /api/channels/nhsapp/accounts + + {% else %} + + target.url + https://comms-apim.de-iaho3.communications.national.nhs.uk/api/channels/nhsapp/accounts + + {% endif %}
{backendCorrelationId}
From 28913cb755e329be022199894583a8cd00b965e6 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Wed, 16 Jul 2025 15:12:47 +0100 Subject: [PATCH 08/10] CCM-10448: move new e2e test for a failed message --- tests/end_to_end/test_failure.py | 71 -------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 tests/end_to_end/test_failure.py diff --git a/tests/end_to_end/test_failure.py b/tests/end_to_end/test_failure.py deleted file mode 100644 index d7b7fe6ed..000000000 --- a/tests/end_to_end/test_failure.py +++ /dev/null @@ -1,71 +0,0 @@ -import pytest -import os -from lib import Assertions, Helper, Generators -from lib.fixtures import * # NOSONAR -from notifications_python_client.notifications import NotificationsAPIClient - - -@pytest.mark.e2e -@pytest.mark.devtest -def test_invalid_end_to_end_internal_dev(url, bearer_token): - """ - .. include:: ../../partials/happy_path/test_invalid_end_to_end_internal_dev.rst - """ - headers = Generators.generate_valid_headers(bearer_token.value) - - resp = Helper.send_single_message( - url, headers, Generators.generate_invalid_send_message_body("email", "internal-dev") - ) - - message_id = resp.json().get("data").get("id") - - Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") - - resp = Helper.get_message(url, headers, message_id) - - Assertions.assert_get_message_status( - resp, - "failed", - "Failed reason: No valid request item plans were generated", - "MFR_CFGV_0005" - ) - - Assertions.assert_get_message_response_channels( - resp, - "failed", - "Failed reason: Alternative contact detail is malformed", - "CFR_CLIV_0001", - ) - - -@pytest.mark.e2e -@pytest.mark.uattest -def test_invalid_end_to_end_uat(url, bearer_token): - """ - .. include:: ../../partials/happy_path/test_invalid_end_to_end_uat.rst - """ - headers = Generators.generate_valid_headers(bearer_token.value) - - resp = Helper.send_single_message( - url, headers, Generators.generate_invalid_send_message_body("email", "internal-qa") - ) - - message_id = resp.json().get("data").get("id") - - Helper.poll_get_message(url=url, headers=headers, message_id=message_id, end_state="failed") - - resp = Helper.get_message(url, headers, message_id) - - Assertions.assert_get_message_status( - resp, - "failed", - "Failed reason: No valid request item plans were generated", - "MFR_CFGV_0005" - ) - - Assertions.assert_get_message_response_channels( - resp, - "failed", - "Failed reason: Alternative contact detail is malformed", - "CFR_CLIV_0001", - ) From 5c8b42fc14bdd69456f741041ee84ca56634dced Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 1 Aug 2025 13:45:39 +0100 Subject: [PATCH 09/10] CCM-10447: revert repoint backend to de-iaho3 --- proxies/live/apiproxy/targets/target.xml | 11 +++-------- ...ssignMessage.MessageBatches.Create.Request.xml | 15 ++++----------- .../AssignMessage.Messages.Create.Request.xml | 15 ++++----------- .../AssignMessage.Messages.GetSingle.Request.xml | 15 ++++----------- .../AssignMessage.NhsAppAccounts.Get.Request.xml | 15 ++++----------- 5 files changed, 19 insertions(+), 52 deletions(-) diff --git a/proxies/live/apiproxy/targets/target.xml b/proxies/live/apiproxy/targets/target.xml index 3e7779475..285ebe25c 100644 --- a/proxies/live/apiproxy/targets/target.xml +++ b/proxies/live/apiproxy/targets/target.xml @@ -18,14 +18,9 @@ true - {% if ENVIRONMENT_TYPE == 'sandbox' %} - - - - {requestpath} - {% else %} - https://comms-apim.de-iaho3.communications.national.nhs.uk - {% endif %} + + + 29000 diff --git a/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml b/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml index 21ce497b9..3dfbc673b 100644 --- a/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml +++ b/proxies/shared/policies/AssignMessage.MessageBatches.Create.Request.xml @@ -16,17 +16,10 @@ target.copy.pathsuffix false - {% if ENVIRONMENT_TYPE == 'sandbox' %} - - requestpath - /api/v1/send - - {% else %} - - target.url - https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/send - - {% endif %} + + requestpath + /api/v1/send + %data.payload# diff --git a/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml b/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml index 1179f3ba2..2a8e9cd5c 100644 --- a/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml +++ b/proxies/shared/policies/AssignMessage.Messages.Create.Request.xml @@ -16,17 +16,10 @@ target.copy.pathsuffix false - {% if ENVIRONMENT_TYPE == 'sandbox' %} - - requestpath - /api/v1/messages - - {% else %} - - target.url - https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/messages - - {% endif %} + + requestpath + /api/v1/messages + %data.payload# diff --git a/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml b/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml index 358278336..ce54ec959 100644 --- a/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml +++ b/proxies/shared/policies/AssignMessage.Messages.GetSingle.Request.xml @@ -16,17 +16,10 @@ target.copy.pathsuffix false - {% if ENVIRONMENT_TYPE == 'sandbox' %} - - requestpath - - - {% else %} - - target.url - https://comms-apim.de-iaho3.communications.national.nhs.uk/api/v1/messages/{data.messageId} - - {% endif %} + + requestpath + +
{backendCorrelationId}
diff --git a/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml b/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml index 181ec442f..6d71f721a 100644 --- a/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml +++ b/proxies/shared/policies/AssignMessage.NhsAppAccounts.Get.Request.xml @@ -16,17 +16,10 @@ target.copy.pathsuffix false - {% if ENVIRONMENT_TYPE == 'sandbox' %} - - requestpath - /api/channels/nhsapp/accounts - - {% else %} - - target.url - https://comms-apim.de-iaho3.communications.national.nhs.uk/api/channels/nhsapp/accounts - - {% endif %} + + requestpath + /api/channels/nhsapp/accounts +
{backendCorrelationId}
From a72df372aa7fbbe732e2c64b23165501f0f06a02 Mon Sep 17 00:00:00 2001 From: Ian Hodges Date: Fri, 1 Aug 2025 13:47:29 +0100 Subject: [PATCH 10/10] CCM-10447: revert repoint backend to de-iaho3 --- proxies/live/apiproxy/targets/target.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/proxies/live/apiproxy/targets/target.xml b/proxies/live/apiproxy/targets/target.xml index 285ebe25c..c9c0bfdd3 100644 --- a/proxies/live/apiproxy/targets/target.xml +++ b/proxies/live/apiproxy/targets/target.xml @@ -21,6 +21,7 @@ + {requestpath} 29000