Skip to content

Commit cf07c92

Browse files
committed
Merge branch 'aea-6063-trigger-post-dated-prescriptions' into aea-0000-add-notifications-reporting-lambda
2 parents b6c9e7e + 64b2466 commit cf07c92

9 files changed

Lines changed: 29 additions & 81 deletions

File tree

.trivyignore.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ vulnerabilities:
22
- id: CVE-2026-25128
33
statement: fast-xml-parser vulnerability accepted as risk - dependency of aws-sdk/client-dynamodb
44
expired_at: 2026-03-01
5-
5+
- id: CVE-2026-25547
6+
paths:
7+
- "package-lock.json"
8+
statement: downstream dependency of @isaacs/brace-expansion
9+
expired_at: 2026-06-01

SAMtemplates/functions/main.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,6 @@ Resources:
596596
LOG_LEVEL: !Ref LogLevel
597597
NHS_NOTIFY_PRESCRIPTIONS_SQS_QUEUE_URL: !Ref NHSNotifyPrescriptionsSQSQueueUrl
598598
POST_DATED_PRESCRIPTIONS_SQS_QUEUE_URL: !Ref PostDatedNotificationsSQSQueueUrl
599-
POST_DATED_OVERRIDE: false
600-
POST_DATED_OVERRIDE_VALUE: false # By default, override never matures post dated prescriptions
601599
TABLE_NAME: !Ref PrescriptionStatusUpdatesTableName
602600
Events:
603601
ScheduleEvent:

packages/common/commonTypes/src/index.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,6 @@ export interface NotifyDataItem {
2828
PrescriptionID: string // Needed to query NPPTS
2929
}
3030

31-
/**
32-
* The structure of a single SQS message in a batch send.
33-
* I couldn't find this type exported from the SDK, and the Message type that IS exported is for receiving data,
34-
* not sending it.
35-
*
36-
* So, I've just done it myself. These are the core attrtibutes we use.
37-
*/
38-
export interface SQSBatchMessage {
39-
Id: string
40-
MessageBody: string
41-
MessageDeduplicationId: string
42-
MessageGroupId: string
43-
MessageAttributes: {[key: string]: {DataType: string; StringValue: string}}
44-
}
45-
4631
/**
4732
* The fields stored in the Notifications table potentially updated by the Notify callback.
4833
*/

packages/postDatedLambda/docs/mature_prescription_check.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ The business logic's `processMessage()` function accepts the SQS message for thi
44

55
```mermaid
66
flowchart TD
7-
A["Start `processMessage()`"] --> C{"POST_DATED_OVERRIDE?"}
8-
C -- Yes --> D["Log override + return override value"]
9-
C -- No --> E{"existingRecords empty?"}
7+
A["Start `processMessage()`"] --> E{"existingRecords empty?"}
108
E -- Yes --> F["Log error + return IGNORE"]
119
E -- No --> G["Fetch most recently submitted NPPTS record"]
1210
G --> H{"PostDatedLastModifiedSetAt present?"}

packages/postDatedLambda/src/businessLogic.ts

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,6 @@ import {PSUDataItem} from "@psu-common/commonTypes"
44

55
import {PostDatedSQSMessageWithExistingRecords, PostDatedProcessingResult} from "./types"
66

7-
// defaults to false
8-
const POST_DATED_OVERRIDE = process.env.POST_DATED_OVERRIDE === "true"
9-
10-
// set from environment variable POST_DATED_OVERRIDE_VALUE
11-
const POST_DATED_OVERRIDE_VALUE_ENV = process.env.POST_DATED_OVERRIDE_VALUE ?? "ignore"
12-
let POST_DATED_OVERRIDE_VALUE: PostDatedProcessingResult
13-
switch (POST_DATED_OVERRIDE_VALUE_ENV.toLowerCase()) {
14-
case "matured":
15-
POST_DATED_OVERRIDE_VALUE = PostDatedProcessingResult.MATURED
16-
break
17-
case "immature":
18-
POST_DATED_OVERRIDE_VALUE = PostDatedProcessingResult.IMMATURE
19-
break
20-
default:
21-
POST_DATED_OVERRIDE_VALUE = PostDatedProcessingResult.IGNORE
22-
break
23-
}
24-
257
export function getMostRecentRecord(
268
existingRecords: Array<PSUDataItem>
279
): PSUDataItem {
@@ -53,12 +35,6 @@ export function processMessage(
5335
prescriptionData: message.prescriptionData,
5436
existingRecords: message.existingRecords
5537
})
56-
if (POST_DATED_OVERRIDE) {
57-
logger.info("Post-dated override is enabled, returning override value", {
58-
overrideValue: POST_DATED_OVERRIDE_VALUE
59-
})
60-
return POST_DATED_OVERRIDE_VALUE
61-
}
6238

6339
// The existingRecords array contains all records from the DynamoDB table
6440
// that match this prescription's PrescriptionID
@@ -141,7 +117,7 @@ export function computeTimeUntilMaturity(
141117
}
142118

143119
const lastModified = new Date(prescriptionRecord.LastModified)
144-
const currentTime = new Date()
120+
const currentTime = Date.now()
145121

146-
return (lastModified.getTime() - currentTime.getTime()) / 1000
122+
return (lastModified.getTime() - currentTime) / 1000
147123
}

packages/postDatedLambda/src/databaseClient.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,30 @@ export async function getExistingRecordsByPrescriptionID(
4646
let lastEvaluatedKey
4747
let items: Array<PSUDataItem> = []
4848

49+
logger.info("Querying DynamoDB for existing prescription records", {
50+
prescriptionID: normalizedPrescriptionID,
51+
tableName,
52+
indexName: pharmacyPrescriptionIndexName
53+
})
54+
4955
try {
50-
do {
56+
while (true) {
5157
if (lastEvaluatedKey) {
5258
query.ExclusiveStartKey = lastEvaluatedKey
5359
}
5460

55-
logger.info("Querying DynamoDB for existing prescription records", {
56-
prescriptionID: normalizedPrescriptionID,
57-
tableName,
58-
indexName: pharmacyPrescriptionIndexName
59-
})
60-
6161
const result = await client.send(new QueryCommand(query))
6262

6363
if (result.Items) {
64-
const parsedItems = result.Items.map((item) => unmarshall(item) as PSUDataItem)
65-
items = items.concat(parsedItems)
64+
const parsedItems: Array<PSUDataItem> = result.Items.map((item) => unmarshall(item) as PSUDataItem)
65+
items.push(...parsedItems)
6666
}
6767

6868
lastEvaluatedKey = result.LastEvaluatedKey
69-
} while (lastEvaluatedKey)
69+
if (!lastEvaluatedKey) {
70+
break
71+
}
72+
}
7073

7174
logger.info("Retrieved existing prescription records from DynamoDB", {
7275
prescriptionID: normalizedPrescriptionID,

packages/postDatedLambda/src/sqs.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import {
55
ChangeMessageVisibilityBatchCommand,
66
GetQueueAttributesCommand,
77
SendMessageBatchCommand,
8+
SendMessageBatchRequestEntry,
89
Message
910
} from "@aws-sdk/client-sqs"
1011
import {Logger} from "@aws-lambda-powertools/logger"
1112

12-
import {NotifyDataItem, SQSBatchMessage} from "@psu-common/commonTypes"
13+
import {NotifyDataItem} from "@psu-common/commonTypes"
1314

1415
import {BatchProcessingResult, PostDatedSQSMessage} from "./types"
1516

@@ -35,7 +36,7 @@ function chunkArray<T>(arr: Array<T>, size: number): Array<Array<T>> {
3536
function buildNotificationBatchEntries(
3637
messages: Array<PostDatedSQSMessage>,
3738
logger: Logger
38-
): Array<SQSBatchMessage> {
39+
): Array<SendMessageBatchRequestEntry> {
3940
return messages.map((message, idx) => {
4041
const {prescriptionData} = message
4142

@@ -70,7 +71,7 @@ function buildNotificationBatchEntries(
7071
}
7172

7273
async function sendEntriesToQueue(
73-
entries: Array<SQSBatchMessage>,
74+
entries: Array<SendMessageBatchRequestEntry>,
7475
queueUrl: string,
7576
logger: Logger
7677
): Promise<Array<string>> {

packages/postDatedLambda/tests/testBusinessLogic.test.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,6 @@ describe("businessLogic", () => {
142142
})
143143

144144
describe("processMessage", () => {
145-
it("should return the override value when override mode is enabled", async () => {
146-
const {processMessage} = await loadBusinessLogic({
147-
POST_DATED_OVERRIDE: "true",
148-
POST_DATED_OVERRIDE_VALUE: "immature"
149-
})
150-
const logger = new Logger({serviceName: "post-dated-tests"})
151-
152-
const result = processMessage(logger, createMessage())
153-
154-
expect(result).toBe(PostDatedProcessingResult.IMMATURE)
155-
})
156-
157145
it("should ignore messages that have no existing records", async () => {
158146
const {processMessage} = await loadBusinessLogic()
159147
const logger = new Logger({serviceName: "post-dated-tests"})

packages/updatePrescriptionStatus/src/utils/sqsClient.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import {Logger} from "@aws-lambda-powertools/logger"
2-
import {SQSClient, SendMessageBatchCommand} from "@aws-sdk/client-sqs"
2+
import {SQSClient, SendMessageBatchCommand, SendMessageBatchRequestEntry} from "@aws-sdk/client-sqs"
33
import {getSecret} from "@aws-lambda-powertools/parameters/secrets"
44

55
import {createHmac} from "node:crypto"
66

7-
import {
8-
NotifyDataItem,
9-
PSUDataItem,
10-
PSUDataItemWithPrevious,
11-
SQSBatchMessage
12-
} from "@psu-common/commonTypes"
7+
import {NotifyDataItem, PSUDataItem, PSUDataItemWithPrevious} from "@psu-common/commonTypes"
138

149
import {checkSiteOrSystemIsNotifyEnabled} from "../validation/notificationSiteAndSystemFilters"
1510

@@ -43,7 +38,7 @@ function buildSqsBatchEntries(
4338
items: Array<PSUDataItem>,
4439
requestId: string,
4540
sqsSalt: string
46-
): Array<SQSBatchMessage> {
41+
): Array<SendMessageBatchRequestEntry> {
4742
return items.map((item, idx) => ({
4843
Id: idx.toString(),
4944
MessageBody: JSON.stringify(item as NotifyDataItem),
@@ -67,7 +62,7 @@ function buildSqsBatchEntries(
6762
* @returns An array of the created MessageIds
6863
*/
6964
async function sendEntriesToQueue(
70-
entries: Array<SQSBatchMessage>,
65+
entries: Array<SendMessageBatchRequestEntry>,
7166
queueUrl: string,
7267
requestId: string,
7368
logger: Logger

0 commit comments

Comments
 (0)