diff --git a/shared/types/submission.ts b/shared/types/submission.ts index 20363f3bc6..410b01ba9e 100644 --- a/shared/types/submission.ts +++ b/shared/types/submission.ts @@ -254,11 +254,13 @@ export type SubmissionPaymentMetadata = { email: string } | null -export type SubmissionMrfMetadata = { - workflowCurrentStepNumber: number - workflowNumTotalSteps: number - workflowStatus: WorkflowStatus | undefined // `undefined` is due to submissions before this PR not storing this value -} | null +export type SubmissionMrfMetadata = + | { + workflowCurrentStepNumber: number + workflowNumTotalSteps: number + workflowStatus: WorkflowStatus | undefined // `undefined` is due to submissions before this PR not storing this value + } + | undefined export type SubmissionMetadata = { number: number diff --git a/src/app/models/__tests__/multirespondent-submission.server.model.spec.ts b/src/app/models/__tests__/multirespondent-submission.server.model.spec.ts index 663326d672..63c855c9f1 100644 --- a/src/app/models/__tests__/multirespondent-submission.server.model.spec.ts +++ b/src/app/models/__tests__/multirespondent-submission.server.model.spec.ts @@ -3,7 +3,13 @@ import { ObjectId } from 'bson' import { pick, times } from 'lodash' import moment from 'moment-timezone' import mongoose from 'mongoose' -import { SubmissionMetadata, SubmissionType } from 'shared/types' +import { + BasicField, + SubmissionMetadata, + SubmissionType, + WorkflowStatus, + WorkflowType, +} from 'shared/types' import getSubmissionModel, { getEmailSubmissionModel, @@ -24,6 +30,34 @@ describe('Multirespondent Submission Model', () => { const MOCK_ENCRYPTED_SUBMISSION_SECRET_KEY = 'This is an encrypted secret key' const MOCK_ENCRYPTED_CONTENT = 'abcdefg encryptedContent' + const YES_NO_FIELD = { + _id: 'yes_no_field_id', + title: 'Yes or No', + description: '', + required: true, + disabled: false, + fieldType: BasicField.YesNo, + } + const WORKFLOW_STEP_1 = { + _id: 'step_1_id', + workflow_type: WorkflowType.Static, + emails: ['example@example.com'], + edit: [], + } + const WORKFLOW_STEP_2 = { + _id: 'step_2_id', + workflow_type: WorkflowType.Static, + emails: ['example@example.com'], + edit: [YES_NO_FIELD._id], + } + const WORKFLOW_APPROVAL_STEP = { + _id: 'approval_step_id', + workflow_type: WorkflowType.Static, + emails: ['example@example.com'], + edit: [YES_NO_FIELD._id], + approval_field: YES_NO_FIELD._id, + } + describe('Statics', () => { describe('findSingleMetadata', () => { it('should return submission metadata', async () => { @@ -34,15 +68,26 @@ describe('Multirespondent Submission Model', () => { const validSubmission = await MultirespondentSubmission.create({ form: validFormId, submissionType: SubmissionType.Multirespondent, - form_fields: [], + form_fields: [YES_NO_FIELD, WORKFLOW_APPROVAL_STEP], form_logics: [], - workflow: [], + workflow: [WORKFLOW_STEP_1, WORKFLOW_APPROVAL_STEP], submissionPublicKey: MOCK_SUBMISSION_PUBLIC_KEY, encryptedSubmissionSecretKey: MOCK_ENCRYPTED_SUBMISSION_SECRET_KEY, encryptedContent: MOCK_ENCRYPTED_CONTENT, version: 3, created: createdDate, - workflowStep: 0, + workflowStep: 1, + submittedSteps: [ + { + isApproval: false, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + { + isApproval: true, + status: WorkflowStatus.REJECTED, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + ], }) // Act @@ -59,6 +104,11 @@ describe('Multirespondent Submission Model', () => { submissionTime: moment(createdDate) .tz('Asia/Singapore') .format('Do MMM YYYY, h:mm:ss a'), + mrf: { + workflowCurrentStepNumber: 2, + workflowNumTotalSteps: 2, + workflowStatus: WorkflowStatus.REJECTED, + }, } expect(result).toEqual(expected) }) @@ -118,13 +168,19 @@ describe('Multirespondent Submission Model', () => { submissionType: SubmissionType.Multirespondent, form_fields: [], form_logics: [], - workflow: [], + workflow: [WORKFLOW_STEP_1], submissionPublicKey: MOCK_SUBMISSION_PUBLIC_KEY, encryptedSubmissionSecretKey: MOCK_ENCRYPTED_SUBMISSION_SECRET_KEY, encryptedContent: MOCK_ENCRYPTED_CONTENT, version: 3, created: MOCK_CREATED_DATES_ASC[idx], workflowStep: 0, + submittedSteps: [ + { + isApproval: false, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + ], }), ) const validSubmissions: IMultirespondentSubmissionSchema[] = @@ -146,6 +202,11 @@ describe('Multirespondent Submission Model', () => { submissionTime: moment(data.created) .tz('Asia/Singapore') .format('Do MMM YYYY, h:mm:ss a'), + mrf: { + workflowCurrentStepNumber: 1, + workflowNumTotalSteps: 1, + workflowStatus: WorkflowStatus.COMPLETED, + }, })) .reverse(), } @@ -161,13 +222,24 @@ describe('Multirespondent Submission Model', () => { submissionType: SubmissionType.Multirespondent, form_fields: [], form_logics: [], - workflow: [], + workflow: [WORKFLOW_STEP_1, WORKFLOW_APPROVAL_STEP], submissionPublicKey: MOCK_SUBMISSION_PUBLIC_KEY, encryptedSubmissionSecretKey: MOCK_ENCRYPTED_SUBMISSION_SECRET_KEY, encryptedContent: MOCK_ENCRYPTED_CONTENT, version: 3, created: MOCK_CREATED_DATES_ASC[idx], - workflowStep: 0, + workflowStep: 1, + submittedSteps: [ + { + isApproval: false, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + { + isApproval: true, + status: WorkflowStatus.APPROVED, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + ], }), ) const validSubmissions: IMultirespondentSubmissionSchema[] = @@ -194,6 +266,11 @@ describe('Multirespondent Submission Model', () => { submissionTime: moment(secondSubmission.created) .tz('Asia/Singapore') .format('Do MMM YYYY, h:mm:ss a'), + mrf: { + workflowCurrentStepNumber: 2, + workflowNumTotalSteps: 2, + workflowStatus: WorkflowStatus.APPROVED, + }, }, ], } @@ -209,13 +286,23 @@ describe('Multirespondent Submission Model', () => { submissionType: SubmissionType.Multirespondent, form_fields: [], form_logics: [], - workflow: [], + workflow: [WORKFLOW_STEP_1, WORKFLOW_STEP_2], submissionPublicKey: MOCK_SUBMISSION_PUBLIC_KEY, encryptedSubmissionSecretKey: MOCK_ENCRYPTED_SUBMISSION_SECRET_KEY, encryptedContent: MOCK_ENCRYPTED_CONTENT, version: 3, created: MOCK_CREATED_DATES_ASC[idx], - workflowStep: 0, + workflowStep: 1, + submittedSteps: [ + { + isApproval: false, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + { + isApproval: false, + submittedAt: '2024-01-02T00:00:00.000Z', + }, + ], }), ) const validSubmissions: IMultirespondentSubmissionSchema[] = @@ -242,6 +329,11 @@ describe('Multirespondent Submission Model', () => { submissionTime: moment(latestSubmission.created) .tz('Asia/Singapore') .format('Do MMM YYYY, h:mm:ss a'), + mrf: { + workflowCurrentStepNumber: 2, + workflowNumTotalSteps: 2, + workflowStatus: WorkflowStatus.COMPLETED, + }, }, ], } @@ -332,6 +424,8 @@ describe('Multirespondent Submission Model', () => { 'encryptedContent', 'submissionType', 'version', + 'submittedSteps', + 'workflowStep', ) // Native-ify arrays as mongoose documents contain a mongoose-specific array type. expectedSubmission.form_fields = JSON.parse( @@ -417,6 +511,7 @@ describe('Multirespondent Submission Model', () => { 'submissionType', 'version', 'workflowStep', + 'submittedSteps', ) expect(actual).not.toBeNull() expect(actual?.toJSON()).toEqual(expected) diff --git a/src/app/models/submission.server.model.ts b/src/app/models/submission.server.model.ts index dfc7ba013d..054b538629 100644 --- a/src/app/models/submission.server.model.ts +++ b/src/app/models/submission.server.model.ts @@ -818,7 +818,7 @@ const buildSubmissionMetadata = ( workflowStep: mrfMeta.workflowStep, submittedSteps: mrfMeta.submittedSteps, }) - : null, + : undefined, } } diff --git a/src/app/modules/submission/multirespondent-submission/__tests__/multirespondent-submission.utils.spec.ts b/src/app/modules/submission/multirespondent-submission/__tests__/multirespondent-submission.utils.spec.ts index 5b22c65008..e46ccb49b5 100644 --- a/src/app/modules/submission/multirespondent-submission/__tests__/multirespondent-submission.utils.spec.ts +++ b/src/app/modules/submission/multirespondent-submission/__tests__/multirespondent-submission.utils.spec.ts @@ -16,6 +16,7 @@ import { ShortTextResponseV3, SubmissionType, TableResponseV3, + WorkflowStatus, WorkflowType, } from 'shared/types' @@ -41,18 +42,38 @@ import { } from '../multirespondent-submission.utils' describe('multirespondent-submission.utils', () => { + const WORKFLOW_STEP_1 = { + _id: 'step_1_id', + workflow_type: WorkflowType.Static, + emails: ['example@example.com'], + edit: [], + } + describe('createMultirespondentSubmissionDto', () => { it('should create an encrypted submission DTO sucessfully', () => { // Arrange const createdDate = new Date() const submissionData = { + submissionType: SubmissionType.Multirespondent, _id: new ObjectId(), created: createdDate, submissionPublicKey: 'some public key', encryptedSubmissionSecretKey: 'some encrypted secret key', encryptedContent: 'some encrypted content', - submissionType: SubmissionType.Multirespondent, - } as MultirespondentSubmissionData + workflow: [WORKFLOW_STEP_1], + workflowStep: 0, + form_fields: [], + form_logics: [], + attachmentMetadata: {}, + version: 3, + mrfVersion: 3, + submittedSteps: [ + { + isApproval: false, + submittedAt: '2024-01-01T00:00:00.000Z', + }, + ], + } as unknown as MultirespondentSubmissionData const attachmentPresignedUrls = { someSubmissionId: 'some presigned url', } @@ -75,6 +96,17 @@ describe('multirespondent-submission.utils', () => { submissionData.encryptedSubmissionSecretKey, attachmentMetadata: attachmentPresignedUrls, submissionType: SubmissionType.Multirespondent, + workflow: submissionData.workflow, + form_fields: submissionData.form_fields, + form_logics: submissionData.form_logics, + version: submissionData.version, + workflowStep: submissionData.workflowStep, + mrfVersion: submissionData.mrfVersion, + mrfMeta: { + workflowCurrentStepNumber: 1, + workflowNumTotalSteps: 1, + workflowStatus: WorkflowStatus.COMPLETED, + }, }) }) })