From 8bf6d88763fee33e41515e5c838cd06d4ee79d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Janin?= Date: Mon, 9 Sep 2024 11:02:45 -0400 Subject: [PATCH] feat: update new Status#CreatedAt field when changing Status in DynamoDB Vault entries --- .../[id]/responses/[statusFilter]/actions.ts | 1 + app/api/id/[form]/submission/report/route.ts | 16 +++++++----- lib/vault.ts | 26 +++++++++++++------ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/app/(gcforms)/[locale]/(form administration)/form-builder/[id]/responses/[statusFilter]/actions.ts b/app/(gcforms)/[locale]/(form administration)/form-builder/[id]/responses/[statusFilter]/actions.ts index 2e83c3caf3..3c6173f6d4 100644 --- a/app/(gcforms)/[locale]/(form administration)/form-builder/[id]/responses/[statusFilter]/actions.ts +++ b/app/(gcforms)/[locale]/(form administration)/form-builder/[id]/responses/[statusFilter]/actions.ts @@ -285,6 +285,7 @@ export const getSubmissionsByFormat = async ({ return { id: item.name, status: item.status, + createdAt: item.createdAt, }; }); diff --git a/app/api/id/[form]/submission/report/route.ts b/app/api/id/[form]/submission/report/route.ts index c752d745ab..64ea18607a 100644 --- a/app/api/id/[form]/submission/report/route.ts +++ b/app/api/id/[form]/submission/report/route.ts @@ -16,12 +16,12 @@ async function getSubmissionsFromSubmissionNames( formId: string, submissionNames: string[] ): Promise<{ - submissionsToReport: { name: string; confirmationCode: string }[]; + submissionsToReport: { name: string; createdAt: number; confirmationCode: string }[]; submissionNamesAlreadyUsed: string[]; submissionNamesNotFound: string[]; }> { const accumulatedSubmissions: { - [name: string]: { status: VaultStatus; confirmationCode: string }; + [name: string]: { status: VaultStatus; createdAt: number; confirmationCode: string }; } = {}; let requestedKeys = submissionNames.map((name) => { @@ -33,7 +33,7 @@ async function getSubmissionsFromSubmissionNames( RequestItems: { Vault: { Keys: requestedKeys, - ProjectionExpression: "#name,#status,ConfirmationCode", + ProjectionExpression: "#name,#status,ConfirmationCode,CreatedAt", ExpressionAttributeNames: { "#name": "Name", "#status": "Status", @@ -49,6 +49,7 @@ async function getSubmissionsFromSubmissionNames( response.Responses.Vault.forEach((record) => { accumulatedSubmissions[record["Name"]] = { status: record["Status"], + createdAt: record["CreatedAt"], confirmationCode: record["ConfirmationCode"], }; }); @@ -75,13 +76,14 @@ async function getSubmissionsFromSubmissionNames( } else { acc.submissionsToReport.push({ name: currentSubmissionName, + createdAt: submission.createdAt, confirmationCode: submission.confirmationCode, }); } return acc; }, { - submissionsToReport: Array<{ name: string; confirmationCode: string }>(), + submissionsToReport: Array<{ name: string; createdAt: number; confirmationCode: string }>(), submissionNamesAlreadyUsed: Array(), submissionNamesNotFound: Array(), } @@ -90,7 +92,7 @@ async function getSubmissionsFromSubmissionNames( async function report( formId: string, - submissionsToReport: { name: string; confirmationCode: string }[] + submissionsToReport: { name: string; createdAt: number; confirmationCode: string }[] ): Promise { const request = new TransactWriteCommand({ TransactItems: submissionsToReport.flatMap((submission) => { @@ -103,12 +105,14 @@ async function report( NAME_OR_CONF: `NAME#${submission.name}`, }, UpdateExpression: - "SET #status = :status, ProblemTimestamp = :problemTimestamp REMOVE RemovalDate", + "SET #status = :status, #statusCreatedAtKey = :statusCreatedAtValue, ProblemTimestamp = :problemTimestamp REMOVE RemovalDate", ExpressionAttributeNames: { "#status": "Status", + "#statusCreatedAtKey": "Status#CreatedAt", }, ExpressionAttributeValues: { ":status": "Problem", + ":statusCreatedAtValue": `Problem#${submission.createdAt}`, ":problemTimestamp": Date.now(), }, }, diff --git a/lib/vault.ts b/lib/vault.ts index b369ef27a2..6cf6b2eba0 100644 --- a/lib/vault.ts +++ b/lib/vault.ts @@ -386,7 +386,7 @@ export async function retrieveSubmissions( * @param email Email address of the user downloading the Submission */ export async function updateLastDownloadedBy( - responses: Array<{ id: string; status: string }>, + responses: Array<{ id: string; status: string; createdAt: number }>, formID: string, email: string ) { @@ -404,16 +404,22 @@ export async function updateLastDownloadedBy( NAME_OR_CONF: `NAME#${response.id}`, }, UpdateExpression: "SET LastDownloadedBy = :email, DownloadedAt = :downloadedAt".concat( - isNewResponse ? ", #status = :statusUpdate" : "" + isNewResponse + ? ", #status = :statusUpdate, #statusCreatedAtKey = :statusCreatedAtValue" + : "" ), ExpressionAttributeValues: { ":email": email, ":downloadedAt": Date.now(), - ...(isNewResponse && { ":statusUpdate": "Downloaded" }), + ...(isNewResponse && { + ":statusUpdate": "Downloaded", + ":statusCreatedAtValue": `Downloaded#${response.createdAt}`, + }), }, ...(isNewResponse && { ExpressionAttributeNames: { "#status": "Status", + "#statusCreatedAtKey": "Status#CreatedAt", }, }), }, @@ -574,7 +580,7 @@ async function getSubmissionsFromConfirmationCodes( formId: string, confirmationCodes: string[] ): Promise<{ - submissionsToConfirm: { name: string; confirmationCode: string }[]; + submissionsToConfirm: { name: string; createdAt: number; confirmationCode: string }[]; confirmationCodesAlreadyUsed: string[]; confirmationCodesNotFound: string[]; }> { @@ -591,7 +597,7 @@ async function getSubmissionsFromConfirmationCodes( }); const accumulatedSubmissions: { - [confCode: string]: { name: string; removalDate?: number }; + [confCode: string]: { name: string; createdAt: number; removalDate?: number }; } = {}; let requestedKeys = confirmationCodes.map((code) => { @@ -603,7 +609,7 @@ async function getSubmissionsFromConfirmationCodes( RequestItems: { Vault: { Keys: requestedKeys, - ProjectionExpression: "#name,ConfirmationCode,RemovalDate", + ProjectionExpression: "#name,CreatedAt,ConfirmationCode,RemovalDate", ExpressionAttributeNames: { "#name": "Name", }, @@ -618,6 +624,7 @@ async function getSubmissionsFromConfirmationCodes( response.Responses.Vault.forEach((record) => { accumulatedSubmissions[record["ConfirmationCode"]] = { name: record["Name"], + createdAt: record["CreatedAt"], removalDate: record["RemovalDate"], }; }); @@ -644,13 +651,14 @@ async function getSubmissionsFromConfirmationCodes( } else { acc.submissionsToConfirm.push({ name: submission.name, + createdAt: submission.createdAt, confirmationCode: currentConfirmationCode, }); } return acc; }, { - submissionsToConfirm: Array<{ name: string; confirmationCode: string }>(), + submissionsToConfirm: Array<{ name: string; createdAt: number; confirmationCode: string }>(), confirmationCodesAlreadyUsed: Array(), confirmationCodesNotFound: Array(), } @@ -721,12 +729,14 @@ export const confirmResponses = async ( NAME_OR_CONF: `NAME#${submission.name}`, }, UpdateExpression: - "SET #status = :status, ConfirmTimestamp = :confirmTimestamp, RemovalDate = :removalDate", + "SET #status = :status, #statusCreatedAtKey = :statusCreatedAtValue, ConfirmTimestamp = :confirmTimestamp, RemovalDate = :removalDate", ExpressionAttributeNames: { "#status": "Status", + "#statusCreatedAtKey": "Status#CreatedAt", }, ExpressionAttributeValues: { ":status": "Confirmed", + ":statusCreatedAtValue": `Confirmed#${submission.createdAt}`, ":confirmTimestamp": confirmationTimestamp, ":removalDate": removalDate, },