diff --git a/.github/workflows/stage-3-build.yaml b/.github/workflows/stage-3-build.yaml index a8441e7ff..766b9bfdd 100644 --- a/.github/workflows/stage-3-build.yaml +++ b/.github/workflows/stage-3-build.yaml @@ -161,7 +161,8 @@ jobs: --targetAccountGroup "nhs-notify-supplier-api-dev" \ --terraformAction "apply" \ --overrideProjectName "nhs" \ - --overrideRoleName "nhs-main-acct-supplier-api-github-deploy" + --overrideRoleName "nhs-main-acct-supplier-api-github-deploy" \ + --internalRef "feature/CCM-15148" artefact-proxies: name: "Build proxies" runs-on: ubuntu-latest diff --git a/infrastructure/terraform/components/api/README.md b/infrastructure/terraform/components/api/README.md index f1f278c5e..0e6b2dbec 100644 --- a/infrastructure/terraform/components/api/README.md +++ b/infrastructure/terraform/components/api/README.md @@ -34,7 +34,7 @@ No requirements. | [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | n/a | yes | | [kms\_deletion\_window](#input\_kms\_deletion\_window) | When a kms key is deleted, how long should it wait in the pending deletion state? | `string` | `"30"` | no | | [letter\_table\_ttl\_hours](#input\_letter\_table\_ttl\_hours) | Number of hours to set as TTL on letters table | `number` | `24` | no | -| [letter\_variant\_map](#input\_letter\_variant\_map) | n/a | `map(object({ supplierId = string, specId = string }))` |
{
"lv1": {
"specId": "spec1",
"supplierId": "supplier1"
},
"lv2": {
"specId": "spec2",
"supplierId": "supplier1"
},
"lv3": {
"specId": "spec3",
"supplierId": "supplier2"
}
}
| no | +| [letter\_variant\_map](#input\_letter\_variant\_map) | n/a | `map(object({ supplierId = string, specId = string, billingId = string }))` |
{
"lv1": {
"billingId": "billing1",
"specId": "spec1",
"supplierId": "supplier1"
},
"lv2": {
"billingId": "billing2",
"specId": "spec2",
"supplierId": "supplier1"
},
"lv3": {
"billingId": "billing3",
"specId": "spec3",
"supplierId": "supplier2"
}
}
| no | | [log\_level](#input\_log\_level) | The log level to be used in lambda functions within the component. Any log with a lower severity than the configured value will not be logged: https://docs.python.org/3/library/logging.html#levels | `string` | `"INFO"` | no | | [log\_retention\_in\_days](#input\_log\_retention\_in\_days) | The retention period in days for the Cloudwatch Logs events to be retained, default of 0 is indefinite | `number` | `0` | no | | [manually\_configure\_mtls\_truststore](#input\_manually\_configure\_mtls\_truststore) | Manually manage the truststore used for API Gateway mTLS (e.g. for prod environment) | `bool` | `false` | no | diff --git a/infrastructure/terraform/components/api/variables.tf b/infrastructure/terraform/components/api/variables.tf index 97169278e..d7faa9a81 100644 --- a/infrastructure/terraform/components/api/variables.tf +++ b/infrastructure/terraform/components/api/variables.tf @@ -136,11 +136,11 @@ variable "eventpub_control_plane_bus_arn" { } variable "letter_variant_map" { - type = map(object({ supplierId = string, specId = string })) + type = map(object({ supplierId = string, specId = string, billingId = string })) default = { - "lv1" = { supplierId = "supplier1", specId = "spec1" }, - "lv2" = { supplierId = "supplier1", specId = "spec2" }, - "lv3" = { supplierId = "supplier2", specId = "spec3" } + "lv1" = { supplierId = "supplier1", specId = "spec1", billingId = "billing1" }, + "lv2" = { supplierId = "supplier1", specId = "spec2", billingId = "billing2" }, + "lv3" = { supplierId = "supplier2", specId = "spec3", billingId = "billing3" } } } diff --git a/internal/datastore/src/__test__/letter-repository.test.ts b/internal/datastore/src/__test__/letter-repository.test.ts index 193c1c077..0f6149717 100644 --- a/internal/datastore/src/__test__/letter-repository.test.ts +++ b/internal/datastore/src/__test__/letter-repository.test.ts @@ -30,6 +30,7 @@ function createLetter( source: "/data-plane/letter-rendering/pdf", subject: `client/1/letter-request/${letterId}`, billingRef: "specification1", + specificationBillingId: "billing1", }; } diff --git a/internal/datastore/src/types.ts b/internal/datastore/src/types.ts index bb0843f82..62a3f6113 100644 --- a/internal/datastore/src/types.ts +++ b/internal/datastore/src/types.ts @@ -53,6 +53,7 @@ export const LetterSchema = LetterSchemaBase.extend({ source: z.string(), subject: z.string(), billingRef: z.string(), + specificationBillingId: z.string(), }).describe("Letter"); /** diff --git a/internal/events/package.json b/internal/events/package.json index d8b6626c9..cf2e4f0e4 100644 --- a/internal/events/package.json +++ b/internal/events/package.json @@ -37,5 +37,5 @@ "typecheck": "tsc --noEmit" }, "types": "dist/index.d.ts", - "version": "1.0.13" + "version": "1.0.14" } diff --git a/internal/events/src/domain/letter.ts b/internal/events/src/domain/letter.ts index 67ed8bbe8..c5aa00597 100644 --- a/internal/events/src/domain/letter.ts +++ b/internal/events/src/domain/letter.ts @@ -83,6 +83,13 @@ The identifier will be included as the origin domain in the subject of any corre examples: ["1y3q9v1zzzz"], }), + specificationBillingId: z.string().meta({ + title: "Specification Billing ID", + description: + "The billing ID from the letter specification which was used to produce a letter pack for this request.", + examples: ["1y3q9v1zzzz"], + }), + supplierId: z.string().meta({ title: "Supplier ID", description: "Supplier ID allocated to the letter during creation.", diff --git a/internal/events/src/events/__tests__/letter-mapper.test.ts b/internal/events/src/events/__tests__/letter-mapper.test.ts index c870dc91b..26ea6d00b 100644 --- a/internal/events/src/events/__tests__/letter-mapper.test.ts +++ b/internal/events/src/events/__tests__/letter-mapper.test.ts @@ -16,6 +16,7 @@ describe("letter-mapper", () => { updatedAt: "2025-11-24T15:55:18.000Z", source: "letter-rendering/source/test", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", } as Letter; const source = "/data-plane/supplier-api/nhs-supplier-api-dev/main/letters"; const event = mapLetterToCloudEvent(letter, source); @@ -35,6 +36,7 @@ describe("letter-mapper", () => { status: "PRINTED", specificationId: "spec1", billingRef: "spec1", + specificationBillingId: "billing123", supplierId: "supplier1", groupId: "group1", reasonCode: "R02", diff --git a/internal/events/src/events/__tests__/letter-status-change-events.test.ts b/internal/events/src/events/__tests__/letter-status-change-events.test.ts index 482155458..6ccd40205 100644 --- a/internal/events/src/events/__tests__/letter-status-change-events.test.ts +++ b/internal/events/src/events/__tests__/letter-status-change-events.test.ts @@ -40,6 +40,7 @@ describe("LetterStatus event validations", () => { billingRef: "1y3q9v1zzzz", groupId: "client_template", status, + specificationBillingId: "billing123", }), }), ); diff --git a/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-invalid-major-version.json b/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-invalid-major-version.json index 192ea5e2e..81d4ded6a 100644 --- a/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-invalid-major-version.json +++ b/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-invalid-major-version.json @@ -9,6 +9,7 @@ "source": "/data-plane/letter-rendering/prod/render-pdf", "subject": "client/00f3b388-bbe9-41c9-9e76-052d37ee8988/letter-request/0o5Fs0EELR0fUjHjbCnEtdUwQe4_0o5Fs0EELR0fUjHjbCnEtdUwQe5" }, + "specificationBillingId": "billing123", "specificationId": "1y3q9v1zzzz", "status": "ACCEPTED", "supplierId": "supplier1" diff --git a/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-missing-fields.json b/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-missing-fields.json index 54000422a..0f03dc39f 100644 --- a/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-missing-fields.json +++ b/internal/events/src/events/__tests__/testData/letter.ACCEPTED-with-missing-fields.json @@ -8,6 +8,7 @@ "event": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "source": "/data-plane/letter-rendering/prod/render-pdf" }, + "specificationBillingId": "billing123", "specificationId": "1y3q9v1zzzz", "status": "ACCEPTED", "supplierId": "supplier1" diff --git a/internal/events/src/events/__tests__/testData/letter.ACCEPTED.json b/internal/events/src/events/__tests__/testData/letter.ACCEPTED.json index 7ffac10f3..8182cc1fe 100644 --- a/internal/events/src/events/__tests__/testData/letter.ACCEPTED.json +++ b/internal/events/src/events/__tests__/testData/letter.ACCEPTED.json @@ -9,6 +9,7 @@ "source": "/data-plane/letter-rendering/prod/render-pdf", "subject": "client/00f3b388-bbe9-41c9-9e76-052d37ee8988/letter-request/0o5Fs0EELR0fUjHjbCnEtdUwQe4_0o5Fs0EELR0fUjHjbCnEtdUwQe5" }, + "specificationBillingId": "billing123", "specificationId": "1y3q9v1zzzz", "status": "ACCEPTED", "supplierId": "supplier1" diff --git a/internal/events/src/events/__tests__/testData/letter.FORWARDED.json b/internal/events/src/events/__tests__/testData/letter.FORWARDED.json index 28c6111f5..fe53b766e 100644 --- a/internal/events/src/events/__tests__/testData/letter.FORWARDED.json +++ b/internal/events/src/events/__tests__/testData/letter.FORWARDED.json @@ -11,6 +11,7 @@ }, "reasonCode": "RNIB", "reasonText": "RNIB", + "specificationBillingId": "billing123", "specificationId": "1y3q9v1zzzz", "status": "FORWARDED", "supplierId": "supplier1" diff --git a/internal/events/src/events/__tests__/testData/letter.RETURNED.json b/internal/events/src/events/__tests__/testData/letter.RETURNED.json index 07b28154e..f35440e42 100644 --- a/internal/events/src/events/__tests__/testData/letter.RETURNED.json +++ b/internal/events/src/events/__tests__/testData/letter.RETURNED.json @@ -11,6 +11,7 @@ }, "reasonCode": "R07", "reasonText": "No such address", + "specificationBillingId": "billing123", "specificationId": "1y3q9v1zzzz", "status": "RETURNED", "supplierId": "supplier1" diff --git a/internal/events/src/events/letter-mapper.ts b/internal/events/src/events/letter-mapper.ts index 91f72988a..4b6781e17 100644 --- a/internal/events/src/events/letter-mapper.ts +++ b/internal/events/src/events/letter-mapper.ts @@ -25,6 +25,7 @@ export function mapLetterToCloudEvent( status: letter.status, specificationId: letter.specificationId, billingRef: letter.billingRef, + specificationBillingId: letter.specificationBillingId, supplierId: letter.supplierId, groupId: letter.groupId, reasonCode: letter.reasonCode, diff --git a/lambdas/api-handler/src/mappers/__tests__/letter-mapper.test.ts b/lambdas/api-handler/src/mappers/__tests__/letter-mapper.test.ts index fa7f9f81e..d6440eee5 100644 --- a/lambdas/api-handler/src/mappers/__tests__/letter-mapper.test.ts +++ b/lambdas/api-handler/src/mappers/__tests__/letter-mapper.test.ts @@ -28,6 +28,7 @@ describe("letter-mapper", () => { ttl: 123, source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; const result: PatchLetterResponse = mapToPatchLetterResponse(letter); @@ -64,6 +65,7 @@ describe("letter-mapper", () => { reasonText: "Reason text", source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; const result: PatchLetterResponse = mapToPatchLetterResponse(letter); @@ -100,6 +102,7 @@ describe("letter-mapper", () => { ttl: 123, source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; const result: GetLetterResponse = mapToGetLetterResponse(letter); @@ -136,6 +139,7 @@ describe("letter-mapper", () => { reasonText: "Reason text", source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; const result: GetLetterResponse = mapToGetLetterResponse(letter); @@ -174,6 +178,7 @@ describe("letter-mapper", () => { reasonText: "Reason text", source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; const result: GetLettersResponse = mapToGetLettersResponse([ diff --git a/lambdas/api-handler/src/services/__tests__/letter-operations.test.ts b/lambdas/api-handler/src/services/__tests__/letter-operations.test.ts index 08e103ab0..be69387e1 100644 --- a/lambdas/api-handler/src/services/__tests__/letter-operations.test.ts +++ b/lambdas/api-handler/src/services/__tests__/letter-operations.test.ts @@ -41,6 +41,7 @@ function makeLetter(id: string, status: Letter["status"]): Letter { reasonText: "Reason text", source: "/data-plane/letter-rendering/pdf", subject: "letter-rendering/source/letter/letter-id", + specificationBillingId: "billing123", }; } diff --git a/lambdas/letter-updates-transformer/src/__tests__/letter-updates-transformer.test.ts b/lambdas/letter-updates-transformer/src/__tests__/letter-updates-transformer.test.ts index fd11de133..9a805f44e 100644 --- a/lambdas/letter-updates-transformer/src/__tests__/letter-updates-transformer.test.ts +++ b/lambdas/letter-updates-transformer/src/__tests__/letter-updates-transformer.test.ts @@ -339,6 +339,7 @@ function generateLetter(status: LetterStatus, id?: string): Letter { supplierStatus: `supplier1#${status}`, supplierStatusSk: "2025-12-10T11:12:54Z#1", ttl: 1_234_567_890, + specificationBillingId: "billing1", }; } diff --git a/lambdas/supplier-allocator/src/config/__tests__/deps.test.ts b/lambdas/supplier-allocator/src/config/__tests__/deps.test.ts index 6069dc07d..7c2767f11 100644 --- a/lambdas/supplier-allocator/src/config/__tests__/deps.test.ts +++ b/lambdas/supplier-allocator/src/config/__tests__/deps.test.ts @@ -7,6 +7,7 @@ describe("createDependenciesContainer", () => { lv1: { supplierId: "supplier1", specId: "spec1", + billingId: "billing1", }, }, }; diff --git a/lambdas/supplier-allocator/src/config/__tests__/env.test.ts b/lambdas/supplier-allocator/src/config/__tests__/env.test.ts index 1d8e3a1fc..d54c2c4f6 100644 --- a/lambdas/supplier-allocator/src/config/__tests__/env.test.ts +++ b/lambdas/supplier-allocator/src/config/__tests__/env.test.ts @@ -19,7 +19,8 @@ describe("lambdaEnv", () => { process.env.VARIANT_MAP = `{ "lv1": { "supplierId": "supplier1", - "specId": "spec1" + "specId": "spec1", + "billingId": "billing1" } }`; @@ -31,6 +32,7 @@ describe("lambdaEnv", () => { lv1: { supplierId: "supplier1", specId: "spec1", + billingId: "billing1", }, }, }); diff --git a/lambdas/supplier-allocator/src/config/env.ts b/lambdas/supplier-allocator/src/config/env.ts index 5d924430f..a3ef6bf0d 100644 --- a/lambdas/supplier-allocator/src/config/env.ts +++ b/lambdas/supplier-allocator/src/config/env.ts @@ -5,6 +5,7 @@ const LetterVariantSchema = z.record( z.object({ supplierId: z.string(), specId: z.string(), + billingId: z.string(), }), ); export type LetterVariant = z.infer; diff --git a/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts b/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts index b86ab5dd1..646a2d2fe 100644 --- a/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts +++ b/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts @@ -26,8 +26,16 @@ function makeDeps(overrides: Partial = {}): Deps { const env = { VARIANT_MAP: { - "variant-1": { supplierId: "supplier-1", specId: "spec-1" }, - "variant-2": { supplierId: "supplier-2", specId: "spec-2" }, + "variant-1": { + supplierId: "supplier-1", + specId: "spec-1", + billingId: "billing-1", + }, + "variant-2": { + supplierId: "supplier-2", + specId: "spec-2", + billingId: "billing-2", + }, }, }; diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index 401d12701..89f370804 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -17,7 +17,7 @@ import { } from "../services/supplier-config"; import { Deps } from "../config/deps"; -type SupplierSpec = { supplierId: string; specId: string }; +type SupplierSpec = { supplierId: string; specId: string; billingId: string }; type PreparedEvents = LetterRequestPreparedEventV2 | LetterRequestPreparedEvent; // small envelope that must exist in all inputs diff --git a/lambdas/update-letter-queue/src/__tests__/update-letter-queue.test.ts b/lambdas/update-letter-queue/src/__tests__/update-letter-queue.test.ts index 03f9ff720..f7475a8ce 100644 --- a/lambdas/update-letter-queue/src/__tests__/update-letter-queue.test.ts +++ b/lambdas/update-letter-queue/src/__tests__/update-letter-queue.test.ts @@ -46,6 +46,7 @@ function generateLetter(status: LetterStatus, id?: string): Letter { source: "test-source", subject: "test-subject", billingRef: "billing-ref-1", + specificationBillingId: "billing1", }; } diff --git a/lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts b/lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts index 6292de0f7..e32d47d96 100644 --- a/lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts +++ b/lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts @@ -97,6 +97,7 @@ function createSupplierStatusChangeEventWithoutSupplier( billingRef: "1y3q9v1zzzz", status: "RETURNED", supplierId: "", + specificationBillingId: "billing1", }, datacontenttype: "application/json", dataschema: @@ -151,6 +152,7 @@ function createSupplierStatusChangeEvent( billingRef: "1y3q9v1zzzz", status: "RETURNED", supplierId: "supplier1", + specificationBillingId: "billing1", }, datacontenttype: "application/json", dataschema: @@ -211,11 +213,19 @@ describe("createUpsertLetterHandler", () => { test("processes all records successfully and returns no batch failures", async () => { const v2message = { letterEvent: createPreparedV2Event(), - supplierSpec: { supplierId: "supplier1", specId: "spec1" }, + supplierSpec: { + supplierId: "supplier1", + specId: "spec1", + billingId: "billing1", + }, }; const v1message = { letterEvent: createPreparedV1Event(), - supplierSpec: { supplierId: "supplier1", specId: "spec1" }, + supplierSpec: { + supplierId: "supplier2", + specId: "spec2", + billingId: "billing2", + }, }; const evt: SQSEvent = createSQSEvent([ @@ -249,17 +259,19 @@ describe("createUpsertLetterHandler", () => { expect(insertedV2Letter.status).toBe("PENDING"); expect(insertedV2Letter.groupId).toBe("client1campaign1template1"); expect(insertedV2Letter.source).toBe("/data-plane/letter-rendering/test"); + expect(insertedV2Letter.specificationBillingId).toBe("billing1"); const insertedV1Letter = (mockedDeps.letterRepo.putLetter as jest.Mock).mock .calls[1][0]; expect(insertedV1Letter.id).toBe("letter1"); - expect(insertedV1Letter.supplierId).toBe("supplier1"); - expect(insertedV1Letter.specificationId).toBe("spec1"); - expect(insertedV1Letter.billingRef).toBe("spec1"); + expect(insertedV1Letter.supplierId).toBe("supplier2"); + expect(insertedV1Letter.specificationId).toBe("spec2"); + expect(insertedV1Letter.billingRef).toBe("spec2"); expect(insertedV1Letter.url).toBe("s3://letterDataBucket/letter1.pdf"); expect(insertedV1Letter.status).toBe("PENDING"); expect(insertedV1Letter.groupId).toBe("client1campaign1template1"); expect(insertedV1Letter.source).toBe("/data-plane/letter-rendering/test"); + expect(insertedV1Letter.specificationBillingId).toBe("billing2"); const updatedLetter = ( mockedDeps.letterRepo.updateLetterStatus as jest.Mock @@ -275,7 +287,12 @@ describe("createUpsertLetterHandler", () => { }); expect(mockMetrics.putMetric).toHaveBeenCalledWith( "MessagesProcessed", - 3, + 2, + "Count", + ); + expect(mockMetrics.putMetric).toHaveBeenCalledWith( + "MessagesProcessed", + 1, "Count", ); }); @@ -472,14 +489,22 @@ describe("createUpsertLetterHandler", () => { id: "7b9a03ca-342a-4150-b56b-989109c45615", domainId: "ok", }), - supplierSpec: { supplierId: "supplier1", specId: "spec1" }, + supplierSpec: { + supplierId: "supplier1", + specId: "spec1", + billingId: "billing1", + }, }; const message2 = { letterEvent: createPreparedV2Event({ id: "7b9a03ca-342a-4150-b56b-989109c45616", domainId: "fail", }), - supplierSpec: { supplierId: "supplier1", specId: "spec1" }, + supplierSpec: { + supplierId: "supplier1", + specId: "spec1", + billingId: "billing1", + }, }; const evt: SQSEvent = createSQSEvent([ createSqsRecord("ok-msg", JSON.stringify(message1)), diff --git a/lambdas/upsert-letter/src/handler/upsert-handler.ts b/lambdas/upsert-letter/src/handler/upsert-handler.ts index ada416ec2..e332096fb 100644 --- a/lambdas/upsert-letter/src/handler/upsert-handler.ts +++ b/lambdas/upsert-letter/src/handler/upsert-handler.ts @@ -16,12 +16,13 @@ import z from "zod"; import { MetricsLogger, Unit, metricScope } from "aws-embedded-metrics"; import { Deps } from "../config/deps"; -type SupplierSpec = { supplierId: string; specId: string }; +type SupplierSpec = { supplierId: string; specId: string; billingId: string }; type PreparedEvents = LetterRequestPreparedEventV2 | LetterRequestPreparedEvent; const SupplierSpecSchema = z.object({ supplierId: z.string().min(1), specId: z.string().min(1), + billingId: z.string().min(1), }); const PreparedEventUnionSchema = z.discriminatedUnion("type", [ @@ -63,6 +64,7 @@ function getOperationFromType(type: string): UpsertOperation { supplierSpec.supplierId, supplierSpec.specId, supplierSpec.specId, // use specId for now + supplierSpec.billingId, // use billingId for now ); await deps.letterRepo.putLetter(letterToInsert); @@ -99,6 +101,7 @@ function mapToInsertLetter( supplier: string, spec: string, billingRef: string, + billingId: string, ): InsertLetter { const now = new Date().toISOString(); return { @@ -117,6 +120,7 @@ function mapToInsertLetter( createdAt: now, updatedAt: now, billingRef, + specificationBillingId: billingId, }; } @@ -235,7 +239,11 @@ export default function createUpsertLetterHandler(deps: Deps): SQSHandler { await runUpsert( operation, letterEvent, - supplierSpec ?? { supplierId: "unknown", specId: "unknown" }, + supplierSpec ?? { + supplierId: "unknown", + specId: "unknown", + billingId: "unknown", + }, deps, ); diff --git a/package-lock.json b/package-lock.json index fc88f6af6..7724b6332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,7 +101,7 @@ }, "internal/events": { "name": "@nhsdigital/nhs-notify-event-schemas-supplier-api", - "version": "1.0.13", + "version": "1.0.14", "license": "MIT", "dependencies": { "@asyncapi/bundler": "^0.6.4", diff --git a/scripts/utilities/letter-test-data/README.md b/scripts/utilities/letter-test-data/README.md index 284268885..52ed66166 100644 --- a/scripts/utilities/letter-test-data/README.md +++ b/scripts/utilities/letter-test-data/README.md @@ -16,6 +16,7 @@ npm run cli -- create-letter \ --letter-id letter-id \ --group-id group-id \ --specification-id specification-id \ + --billing-id billing-id \ --status PENDING ``` @@ -26,6 +27,7 @@ npm run cli -- create-letter-batch \ --awsAccountId 820178564574 \ --group-id group-id \ --specification-id specification-id \ + --billing-id billing-id \ --status PENDING \ --count 10 ``` diff --git a/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts index 9f366d2dd..66af9c01a 100644 --- a/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts +++ b/scripts/utilities/letter-test-data/src/__test__/helpers/create-letter-helpers.test.ts @@ -29,6 +29,7 @@ describe("Create letter helpers", () => { const targetFilename = "targetFilename"; const groupId = "groupId"; const specificationId = "specificationId"; + const billingId = "billingId"; const status = "PENDING" as LetterStatusType; const testLetter = "test-letter-standard"; @@ -39,6 +40,7 @@ describe("Create letter helpers", () => { targetFilename, groupId, specificationId, + billingId, status, letterRepository: mockedLetterRepository, testLetter, @@ -62,6 +64,7 @@ describe("Create letter helpers", () => { source: "/data-plane/letter-rendering/letter-test-data", subject: "supplier-api/letter-test-data/letterId", billingRef: "specificationId", + specificationBillingId: "billingId", }); }); @@ -81,6 +84,7 @@ describe("Create letter helpers", () => { const targetFilename = "targetFilename"; const groupId = "groupId"; const specificationId = "specificationId"; + const billingId = "billingId"; const status = "PENDING" as LetterStatusType; const testLetter = "none"; @@ -91,6 +95,7 @@ describe("Create letter helpers", () => { targetFilename, groupId, specificationId, + billingId, status, letterRepository: mockedLetterRepository, testLetter, @@ -110,6 +115,7 @@ describe("Create letter helpers", () => { billingRef: "specificationId", source: "/data-plane/letter-rendering/letter-test-data", subject: "supplier-api/letter-test-data/letterId", + specificationBillingId: "billingId", }); }); @@ -121,6 +127,7 @@ describe("Create letter helpers", () => { letterId: "testLetterId", supplierId: "testSupplierId", specificationId: "testSpecId", + billingId: "testBillingId", groupId: "testGroupId", status: "PENDING" as LetterStatusType, url: "s3://bucket/testSupplierId/testLetter.pdf", @@ -140,6 +147,7 @@ describe("Create letter helpers", () => { source: "/data-plane/letter-rendering/letter-test-data", subject: "supplier-api/letter-test-data/testLetterId", billingRef: "testSpecId", + specificationBillingId: "testBillingId", }); }); }); diff --git a/scripts/utilities/letter-test-data/src/cli/index.ts b/scripts/utilities/letter-test-data/src/cli/index.ts index 131fe224e..982e9e4ee 100644 --- a/scripts/utilities/letter-test-data/src/cli/index.ts +++ b/scripts/utilities/letter-test-data/src/cli/index.ts @@ -44,6 +44,10 @@ async function main() { type: "string", demandOption: false, }, + "billing-id": { + type: "string", + demandOption: false, + }, "ttl-hours": { type: "number", demandOption: false, @@ -83,6 +87,7 @@ async function main() { const targetFilename = `${letterId}.pdf`; const groupId = argv.groupId ?? randomUUID(); const specificationId = argv.specificationId ?? randomUUID(); + const billingId = argv.billingId ?? randomUUID(); const { status } = argv; const { environment } = argv; const { ttlHours } = argv; @@ -96,6 +101,7 @@ async function main() { targetFilename, groupId, specificationId, + billingId, status: status as LetterStatusType, letterRepository, testLetter, @@ -130,6 +136,10 @@ async function main() { type: "string", demandOption: false, }, + "billing-id": { + type: "string", + demandOption: false, + }, "ttl-hours": { type: "number", demandOption: false, @@ -174,6 +184,7 @@ async function main() { const { supplierId } = argv; const groupId = argv.groupId ?? randomUUID(); const specificationId = argv.specificationId ?? randomUUID(); + const billingId = argv.billingId ?? randomUUID(); const { status } = argv; const { environment } = argv; const { ttlHours } = argv; @@ -206,6 +217,7 @@ async function main() { supplierId, groupId, specificationId, + billingId, status: status as LetterStatusType, url, }), diff --git a/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts index 20131b56c..6278dbbe7 100644 --- a/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts +++ b/scripts/utilities/letter-test-data/src/helpers/create-letter-helpers.ts @@ -11,12 +11,14 @@ export async function createLetter(params: { supplierId: string; targetFilename: string; specificationId: string; + billingId: string; groupId: string; status: LetterStatusType; letterRepository: LetterRepository; testLetter: string; }) { const { + billingId, bucketName, groupId, letterId, @@ -49,6 +51,7 @@ export async function createLetter(params: { source: "/data-plane/letter-rendering/letter-test-data", subject: `supplier-api/letter-test-data/${letterId}`, billingRef: specificationId, + specificationBillingId: billingId, }; const letterRecord = await letterRepository.putLetter(letter); @@ -59,12 +62,20 @@ export function createLetterDto(params: { letterId: string; supplierId: string; specificationId: string; + billingId: string; groupId: string; status: LetterStatusType; url: string; }) { - const { groupId, letterId, specificationId, status, supplierId, url } = - params; + const { + billingId, + groupId, + letterId, + specificationId, + status, + supplierId, + url, + } = params; const letter: Omit = { id: letterId, @@ -78,6 +89,7 @@ export function createLetterDto(params: { source: "/data-plane/letter-rendering/letter-test-data", subject: `supplier-api/letter-test-data/${letterId}`, billingRef: specificationId, + specificationBillingId: billingId, }; return letter;