Skip to content

Commit 2cae454

Browse files
authored
Chore: [AEA-4156] - Address Sonar issues (#1929)
## Summary - Routine Change ### Details Clearing out the issues listed in [Sonar](https://sonarcloud.io/project/issues?impactSoftwareQualities=SECURITY&issueStatuses=OPEN%2CCONFIRMED&id=NHSDigital_prescriptionsforpatients)
1 parent 467a9e5 commit 2cae454

20 files changed

+449
-189
lines changed

packages/capabilityStatement/tests/test-handler.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import {expect, describe, it} from "@jest/globals"
2+
13
import {APIGatewayProxyEvent, APIGatewayProxyResult} from "aws-lambda"
4+
25
import {handler} from "../src/capabilityStatement"
3-
import {expect, describe, it} from "@jest/globals"
4-
import {helloworldContext} from "@prescriptionsforpatients_common/testing"
56
import capabilityStatement from "../examples/CapabilityStatement/apim-medicines-prescriptionsforpatients.json"
6-
import {mockAPIGatewayProxyEvent, test_append_trace_ids, test_mime_type} from "@prescriptionsforpatients_common/testing"
7+
import {
8+
mockAPIGatewayProxyEvent,
9+
helloworldContext,
10+
test_append_trace_ids,
11+
test_mime_type
12+
} from "@prescriptionsforpatients_common/testing"
713

814
const dummyContext = helloworldContext
915
const mockEvent: APIGatewayProxyEvent = mockAPIGatewayProxyEvent

packages/distanceSelling/src/distanceSelling.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,8 @@ export class DistanceSelling {
111111
}
112112

113113
addToTelecom(url: string, organisation: Organization) {
114-
if (!organisation.telecom) {
115-
organisation.telecom = []
116-
}
114+
organisation.telecom ??= []
115+
117116
const urlEntryAbsent: boolean = organisation.telecom.filter(entry => entry.system === "url").length === 0
118117
if (urlEntryAbsent) {
119118
const telecom: ContactPoint = {system: "url", use: "work", value: url}

packages/enrichPrescriptions/src/enrichPrescriptions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {Logger} from "@aws-lambda-powertools/logger"
22
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
33
import {LogLevel} from "@aws-lambda-powertools/logger/types"
4+
45
import middy from "@middy/core"
56
import inputOutputLogger from "@middy/input-output-logger"
67
import {Bundle} from "fhir/r4"
8+
79
import {
810
StatusUpdateRequest,
911
StatusUpdates,
@@ -41,13 +43,12 @@ export async function lambdaHandler(event: EnrichPrescriptionsEvent) {
4143
switch (updatesScenario) {
4244
case UpdatesScenario.Present: {
4345
logger.info("Applying status updates.")
44-
applyStatusUpdates(searchsetBundle, statusUpdates!)
46+
applyStatusUpdates(logger, searchsetBundle, statusUpdates!)
4547
break
4648
}
4749
case UpdatesScenario.ExpectedButAbsent: {
4850
logger.info("Call to get status updates was unsuccessful. Applying temporary status updates.")
49-
const statusUpdateRequest = event.statusUpdateData!
50-
applyTemporaryStatusUpdates(searchsetBundle, statusUpdateRequest)
51+
applyTemporaryStatusUpdates(logger, searchsetBundle, event.statusUpdateData)
5152
break
5253
}
5354
default: {

packages/enrichPrescriptions/src/fhirUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export function isolatePerformerReference(medicationRequests: Array<MedicationRe
4848
}
4949

5050
export function isolatePerformerOrganisation(reference: string, prescription: Bundle): Organization {
51-
const filter = (entry: Entry) => entry.fullUrl! === reference
51+
const filter = (entry: Entry) => (!!entry.fullUrl && entry.fullUrl === reference)
5252
return filterAndTypeBundleEntries<Organization>(prescription, filter)[0]
5353
}
5454

packages/enrichPrescriptions/src/statusUpdates.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
import {Logger} from "@aws-lambda-powertools/logger"
2+
13
import {Bundle, Extension, MedicationRequest} from "fhir/r4"
24
import moment, {Moment} from "moment"
5+
36
import {
47
isolateMedicationRequests,
58
isolatePerformerOrganisation,
69
isolatePerformerReference,
710
isolatePrescriptions
811
} from "./fhirUtils"
9-
import {logger} from "./enrichPrescriptions"
1012

1113
export const EXTENSION_URL = "https://fhir.nhs.uk/StructureDefinition/Extension-DM-PrescriptionStatusHistory"
1214
export const VALUE_CODING_SYSTEM = "https://fhir.nhs.uk/CodeSystem/task-businessStatus-nppt"
@@ -71,7 +73,7 @@ function determineStatus(updateItem: UpdateItem): MedicationRequestStatus {
7173
return updatedOverSevenDaysAgo ? "completed" : "active"
7274
}
7375

74-
function updateMedicationRequest(medicationRequest: MedicationRequest, updateItem: UpdateItem) {
76+
function updateMedicationRequest(logger: Logger, medicationRequest: MedicationRequest, updateItem: UpdateItem) {
7577
const status = determineStatus(updateItem)
7678
const relevantExtension = medicationRequest.extension?.find((ext) => ext.url === EXTENSION_URL)
7779
const statusCoding = relevantExtension?.extension?.find((innerExt) => innerExt.url === "status")?.valueCoding?.code
@@ -135,7 +137,7 @@ function statusHistoryExtensionReplacementIndex(medicationRequest: MedicationReq
135137
})
136138
}
137139

138-
export function applyStatusUpdates(searchsetBundle: Bundle, statusUpdates: StatusUpdates) {
140+
export function applyStatusUpdates(logger: Logger, searchsetBundle: Bundle, statusUpdates: StatusUpdates) {
139141
isolatePrescriptions(searchsetBundle).forEach((prescription) => {
140142
const medicationRequests = isolateMedicationRequests(prescription)
141143
const prescriptionID = medicationRequests![0].groupIdentifier!.value!.toUpperCase()
@@ -150,8 +152,8 @@ export function applyStatusUpdates(searchsetBundle: Bundle, statusUpdates: Statu
150152

151153
logger.info(`Applying updates for prescription ${prescriptionID}.`)
152154

153-
const prescriptionUpdate = statusUpdates.prescriptions.filter((p) => p.prescriptionID === prescriptionID)[0]
154-
if (!prescriptionUpdate || !prescriptionUpdate.onboarded) {
155+
const prescriptionUpdate = statusUpdates.prescriptions.find(p => p.prescriptionID === prescriptionID)
156+
if (!prescriptionUpdate?.onboarded) {
155157
logger.info(`Supplier of prescription ${prescriptionID} not onboarded. Applying default updates.`)
156158
medicationRequests?.forEach((medicationRequest) => {
157159
if (delayWithPharmacyStatus(medicationRequest)) {
@@ -169,10 +171,10 @@ export function applyStatusUpdates(searchsetBundle: Bundle, statusUpdates: Statu
169171
lastUpdateDateTime: moment().utc().toISOString(),
170172
latestStatus: APPROVED_STATUS
171173
}
172-
updateMedicationRequest(medicationRequest, update)
174+
updateMedicationRequest(logger, medicationRequest, update)
173175
return
174176
}
175-
updateMedicationRequest(medicationRequest, defaultUpdate(false))
177+
updateMedicationRequest(logger, medicationRequest, defaultUpdate(false))
176178
})
177179
return
178180
}
@@ -184,10 +186,10 @@ export function applyStatusUpdates(searchsetBundle: Bundle, statusUpdates: Statu
184186
const itemUpdates = prescriptionUpdate.items.filter((item) => item.itemId === medicationRequestID)
185187
if (itemUpdates.length > 0) {
186188
logger.info(`Update found for MedicationRequest with id ${medicationRequestID}. Applying.`)
187-
updateMedicationRequest(medicationRequest, itemUpdates[0])
189+
updateMedicationRequest(logger, medicationRequest, itemUpdates[0])
188190
} else {
189191
logger.info(`No update found for MedicationRequest with id ${medicationRequestID}. Applying default.`)
190-
updateMedicationRequest(medicationRequest, defaultUpdate())
192+
updateMedicationRequest(logger, medicationRequest, defaultUpdate())
191193
}
192194
})
193195
})
@@ -249,7 +251,11 @@ export function getUpdatesScenario(statusUpdates: StatusUpdates | undefined): Up
249251
return UpdatesScenario.NotExpected
250252
}
251253

252-
export function applyTemporaryStatusUpdates(searchsetBundle: Bundle, statusUpdateRequest: StatusUpdateRequest) {
254+
export function applyTemporaryStatusUpdates(
255+
logger: Logger,
256+
searchsetBundle: Bundle,
257+
statusUpdateRequest: StatusUpdateRequest
258+
) {
253259
const update: UpdateItem = {
254260
isTerminalState: false,
255261
lastUpdateDateTime: moment().utc().toISOString(),
@@ -269,7 +275,7 @@ export function applyTemporaryStatusUpdates(searchsetBundle: Bundle, statusUpdat
269275
)
270276
if (updates.length > 0) {
271277
logger.info(`Updates expected for medication requests in prescription ${prescriptionID}. Applying temporary.`)
272-
medicationRequests?.forEach((medicationRequest) => updateMedicationRequest(medicationRequest, update))
278+
medicationRequests?.forEach((medicationRequest) => updateMedicationRequest(logger, medicationRequest, update))
273279
}
274280
}
275281
})

packages/enrichPrescriptions/tests/testFhirUtils.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ describe("Unit tests for fhirUtils", function () {
99
const searchsetBundle = richRequestBundle()
1010
const result = isolatePrescriptions(searchsetBundle)
1111

12-
expect(result!.length).toEqual(3)
13-
result!.forEach(r =>
12+
expect(result.length).toEqual(3)
13+
result.forEach(r =>
1414
expect(r.resourceType).toEqual("Bundle")
1515
)
1616
})

packages/enrichPrescriptions/tests/testStatusUpdate.test.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ import {Logger} from "@aws-lambda-powertools/logger"
4040
import {isolateMedicationRequests, isolatePrescriptions} from "../src/fhirUtils"
4141

4242
describe("Unit tests for statusUpdate", function () {
43+
let logger: Logger
44+
4345
beforeEach(() => {
4446
jest.useFakeTimers().setSystemTime(SYSTEM_DATETIME)
47+
logger = new Logger({serviceName: "testStatusUpdate", logLevel: "INFO"})
4548
})
4649

4750
it("when no update is present for a prescription, the not-onboarded update is applied", async () => {
@@ -55,7 +58,7 @@ describe("Unit tests for statusUpdate", function () {
5558
medicationRequest.extension = defaultExtension(false)
5659
medicationRequest.status = "active"
5760

58-
applyStatusUpdates(requestBundle, statusUpdates)
61+
applyStatusUpdates(logger, requestBundle, statusUpdates)
5962

6063
expect(requestBundle).toEqual(expectedResponseBundle)
6164
})
@@ -71,7 +74,7 @@ describe("Unit tests for statusUpdate", function () {
7174
medicationRequest.extension = defaultExtension(false)
7275
medicationRequest.status = "active"
7376

74-
applyStatusUpdates(requestBundle, statusUpdates)
77+
applyStatusUpdates(logger, requestBundle, statusUpdates)
7578

7679
expect(requestBundle).toEqual(expectedResponseBundle)
7780
})
@@ -80,7 +83,7 @@ describe("Unit tests for statusUpdate", function () {
8083
const requestBundle = simpleRequestBundle()
8184
const statusUpdates = simpleStatusUpdatesPayload()
8285

83-
applyStatusUpdates(requestBundle, statusUpdates)
86+
applyStatusUpdates(logger, requestBundle, statusUpdates)
8487

8588
expect(requestBundle).toEqual(simpleResponseBundle())
8689
})
@@ -100,7 +103,7 @@ describe("Unit tests for statusUpdate", function () {
100103

101104
medicationRequest.extension![0].extension![1].valueDateTime = lessThanOneWeekAgo
102105

103-
applyStatusUpdates(requestBundle, statusUpdates)
106+
applyStatusUpdates(logger, requestBundle, statusUpdates)
104107

105108
expect(requestBundle).toEqual(expected)
106109
})
@@ -121,7 +124,7 @@ describe("Unit tests for statusUpdate", function () {
121124
medicationRequest.status = "completed"
122125
medicationRequest.extension![0].extension![1].valueDateTime = moreThanOneWeekAgo
123126

124-
applyStatusUpdates(requestBundle, statusUpdates)
127+
applyStatusUpdates(logger, requestBundle, statusUpdates)
125128

126129
expect(requestBundle).toEqual(expected)
127130
})
@@ -159,7 +162,7 @@ describe("Unit tests for statusUpdate", function () {
159162

160163
addExtensionToMedicationRequest(responseMedicationRequest, "Collected", moreThanOneWeekAgo)
161164

162-
applyStatusUpdates(requestBundle, statusUpdates)
165+
applyStatusUpdates(logger, requestBundle, statusUpdates)
163166

164167
expect(requestBundle).toEqual(expectedResponseBundle)
165168
})
@@ -191,7 +194,7 @@ describe("Unit tests for statusUpdate", function () {
191194
responseMedicationRequest.extension!.push(existingExtension)
192195
responseMedicationRequest.extension!.reverse()
193196

194-
applyStatusUpdates(requestBundle, statusUpdates)
197+
applyStatusUpdates(logger, requestBundle, statusUpdates)
195198

196199
expect(requestBundle).toEqual(expectedResponseBundle)
197200
})
@@ -211,7 +214,7 @@ describe("Unit tests for statusUpdate", function () {
211214
addExtensionToMedicationRequest(medicationRequest, status, "2023-09-11T10:11:12.000Z")
212215

213216
const statusUpdates = simpleStatusUpdatesPayload()
214-
applyStatusUpdates(requestBundle, statusUpdates)
217+
applyStatusUpdates(logger, requestBundle, statusUpdates)
215218

216219
// Check that the original extension is still present and unchanged
217220
expect(medicationRequest.extension![0].extension![0].valueCoding!.code).toEqual(expectedCode)
@@ -229,7 +232,7 @@ describe("Unit tests for statusUpdate", function () {
229232

230233
const responseBundle = JSON.parse(JSON.stringify(requestBundle))
231234

232-
applyStatusUpdates(requestBundle, statusUpdates)
235+
applyStatusUpdates(logger, requestBundle, statusUpdates)
233236

234237
expect(requestBundle).toEqual(responseBundle)
235238
})
@@ -244,7 +247,7 @@ describe("Unit tests for statusUpdate", function () {
244247
const medicationRequest = prescription.entry![3].resource as MedicationRequest
245248
medicationRequest.extension = defaultExtension()
246249

247-
applyStatusUpdates(requestBundle, statusUpdates)
250+
applyStatusUpdates(logger, requestBundle, statusUpdates)
248251

249252
expect(requestBundle).toEqual(expectedResponseBundle)
250253
})
@@ -260,7 +263,7 @@ describe("Unit tests for statusUpdate", function () {
260263
statusHistory!.reverse()
261264

262265
const statusUpdates = simpleStatusUpdatesPayload()
263-
applyStatusUpdates(requestBundle, statusUpdates)
266+
applyStatusUpdates(logger, requestBundle, statusUpdates)
264267

265268
expect(requestBundle).toEqual(simpleResponseBundle())
266269
expect(medicationRequest.extension[0].extension!.length).toEqual(2)
@@ -334,7 +337,7 @@ describe("Unit tests for statusUpdate", function () {
334337
addExtensionToMedicationRequest(medicationRequest, pfpStatus, updateTime)
335338

336339
if (npptUpdates) {
337-
applyStatusUpdates(requestBundle, npptUpdates)
340+
applyStatusUpdates(logger, requestBundle, npptUpdates)
338341
}
339342

340343
expect(medicationRequest.extension![0].extension![0].valueCoding!.code).toEqual(expectedStatus)
@@ -385,7 +388,7 @@ describe("Unit tests for statusUpdate", function () {
385388
const prescriptionID = medicationRequest.groupIdentifier!.value!.toUpperCase()
386389
const statusUpdateRequest = createStatusUpdateRequest([{odsCode: "FLM49", prescriptionID: prescriptionID}])
387390

388-
applyTemporaryStatusUpdates(requestBundle, statusUpdateRequest)
391+
applyTemporaryStatusUpdates(logger, requestBundle, statusUpdateRequest)
389392
const statusExtension = medicationRequest.extension![0].extension!.filter((e) => e.url === "status")[0]
390393

391394
expect(statusExtension.valueCoding!.code!).toEqual(TEMPORARILY_UNAVAILABLE_STATUS)
@@ -404,7 +407,7 @@ describe("Unit tests for statusUpdate", function () {
404407
{odsCode: "FLM49", prescriptionID: "NOPE"}
405408
])
406409

407-
applyTemporaryStatusUpdates(requestBundle, statusUpdateRequest)
410+
applyTemporaryStatusUpdates(logger, requestBundle, statusUpdateRequest)
408411
expect(medicationRequest.extension).toBeUndefined()
409412
})
410413

@@ -426,8 +429,8 @@ describe("Unit tests for statusUpdate", function () {
426429
const prescriptionID = medicationRequests![0].groupIdentifier!.value!.toUpperCase()
427430
const statusUpdateRequest = createStatusUpdateRequest([{odsCode: "FLM49", prescriptionID: prescriptionID}])
428431

429-
applyTemporaryStatusUpdates(requestBundle, statusUpdateRequest)
430-
const statusExtension = medicationRequest.extension![0].extension!.filter((e) => e.url === "status")[0]!
432+
applyTemporaryStatusUpdates(logger, requestBundle, statusUpdateRequest)
433+
const statusExtension = medicationRequest.extension![0].extension!.filter((e) => e.url === "status")[0]
431434

432435
expect(statusExtension.valueCoding!.code!).toEqual(shouldUpdate ? TEMPORARILY_UNAVAILABLE_STATUS : status)
433436
}
@@ -460,7 +463,7 @@ describe("Unit tests for statusUpdate", function () {
460463
{odsCode: "FEW08", prescriptionID: "16B2E0-A83008-81C13H"}
461464
])
462465

463-
applyTemporaryStatusUpdates(requestBundle, statusUpdateRequest)
466+
applyTemporaryStatusUpdates(logger, requestBundle, statusUpdateRequest)
464467

465468
const tempStatusUpdateFilter = (medicationRequest: MedicationRequest) => {
466469
const outerExtension = medicationRequest.extension?.filter(

packages/getMyPrescriptions/src/fhirUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function isolatePerformerReference(medicationRequests: Array<MedicationRe
4545
}
4646

4747
export function isolatePerformerOrganisation(reference: string, prescription: Bundle): Organization {
48-
const filter = (entry: Entry) => entry.fullUrl! === reference
48+
const filter = (entry: Entry) => (!!entry.fullUrl && entry.fullUrl === reference)
4949
return filterAndTypeBundleEntries<Organization>(prescription, filter)[0]
5050
}
5151

packages/getMyPrescriptions/src/getMyPrescriptions.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@ import {APIGatewayProxyResult as LambdaResult} from "aws-lambda"
22
import {Logger} from "@aws-lambda-powertools/logger"
33
import {injectLambdaContext} from "@aws-lambda-powertools/logger/middleware"
44
import {LogLevel} from "@aws-lambda-powertools/logger/types"
5+
56
import middy from "@middy/core"
67
import inputOutputLogger from "@middy/input-output-logger"
78
import httpHeaderNormalizer from "@middy/http-header-normalizer"
9+
810
import errorHandler from "@nhs/fhir-middy-error-handler"
11+
import type {Bundle} from "fhir/r4"
12+
913
import {createSpineClient} from "@NHSDigital/eps-spine-client"
10-
import {extractNHSNumber, NHSNumberValidationError} from "./extractNHSNumber"
14+
import {SpineClient} from "@NHSDigital/eps-spine-client/lib/spine-client"
15+
1116
import {DistanceSelling, ServicesCache} from "@prescriptionsforpatients/distanceSelling"
12-
import type {Bundle} from "fhir/r4"
1317
import {
1418
INVALID_NHS_NUMBER_RESPONSE,
1519
SPINE_CERT_NOT_CONFIGURED_RESPONSE,
@@ -18,9 +22,9 @@ import {
1822
TraceIDs,
1923
ResponseFunc
2024
} from "./responses"
25+
import {extractNHSNumber, NHSNumberValidationError} from "./extractNHSNumber"
2126
import {deepCopy, hasTimedOut, jobWithTimeout} from "./utils"
2227
import {buildStatusUpdateData, shouldGetStatusUpdates} from "./statusUpdate"
23-
import {SpineClient} from "@NHSDigital/eps-spine-client/lib/spine-client"
2428
import {isolateOperationOutcome} from "./fhirUtils"
2529

2630
const LOG_LEVEL = process.env.LOG_LEVEL as LogLevel
@@ -106,7 +110,7 @@ async function eventHandler(
106110
logger.error("Operation outcome returned from spine", {operationOutcome})
107111
})
108112

109-
const statusUpdateData = includeStatusUpdateData ? buildStatusUpdateData(searchsetBundle) : undefined
113+
const statusUpdateData = includeStatusUpdateData ? buildStatusUpdateData(logger, searchsetBundle) : undefined
110114

111115
const distanceSelling = new DistanceSelling(servicesCache, logger)
112116
const distanceSellingBundle = deepCopy(searchsetBundle)

0 commit comments

Comments
 (0)