Skip to content

Commit d8b9d45

Browse files
committed
feat: add gb flag
1 parent 9d429c0 commit d8b9d45

File tree

6 files changed

+139
-52
lines changed

6 files changed

+139
-52
lines changed

shared/constants/feature-flags.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,11 @@ export const featureFlags = {
2828
singpassMrf: 'singpass-mrf' as const,
2929
enableSaveDraftButtonFloating: 'enable-save-draft-button-floating' as const,
3030
enableSaveDraftButtonHeader: 'enable-save-draft-button-header' as const,
31+
adminEmailPdf: 'admin-email-pdf' as const,
3132
}
33+
34+
export enum AdminEmailPdfFeatureValue {
35+
OFF = 'OFF',
36+
SIGNATURES_ONLY = 'SIGNATURES_ONLY',
37+
ON = 'ON',
38+
}

src/app/modules/submission/encrypt-submission/encrypt-submission.controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ const _createSubmission = async ({
804804
emailFields,
805805
submissionAttachments,
806806
respondentEmails,
807+
growthbook: req.growthbook
807808
})
808809
}
809810

src/app/modules/submission/encrypt-submission/encrypt-submission.service.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import {
66
DateString,
77
FormResponseMode,
88
PaymentChannel,
9-
SubmissionType,
9+
SubmissionType
1010
} from '../../../../../shared/types'
1111
import {
1212
EmailAdminDataField,
1313
FieldResponse,
14+
FormFieldSchema,
1415
IEncryptedSubmissionSchema,
1516
IPopulatedEncryptedForm,
1617
IPopulatedForm,
@@ -44,10 +45,15 @@ import {
4445
} from '../submission.errors'
4546
import { sendEmailConfirmations } from '../submission.service'
4647
import { ProcessedFieldResponse } from '../submission.types'
47-
import { extractEmailConfirmationData } from '../submission.utils'
48+
import {
49+
extractEmailConfirmationData,
50+
isAdminEmailPdfEnabled,
51+
} from '../submission.utils'
4852

4953
import { CHARTS_MAX_SUBMISSION_RESULTS } from './encrypt-submission.constants'
5054
import { SaveEncryptSubmissionParams } from './encrypt-submission.types'
55+
import { GrowthBook } from '@growthbook/growthbook'
56+
import { isTest } from '../../../config/config'
5157

5258
const logger = createLoggerWithLabel(module)
5359
const EncryptSubmissionModel = getEncryptSubmissionModel(mongoose)
@@ -136,7 +142,17 @@ export const createEncryptSubmissionWithoutSave = ({
136142
})
137143
}
138144

139-
const checkIfAdminPdfIsRequired = (isPaymentEnabled: boolean): boolean => {
145+
const checkIfAdminPdfIsRequired = (
146+
isPaymentEnabled: boolean,
147+
formFields: FormFieldSchema[],
148+
growthbook?: GrowthBook,
149+
): boolean => {
150+
const isGbFlagEnabled =
151+
isAdminEmailPdfEnabled({ growthbook, formFields }) || isTest
152+
153+
if (!isGbFlagEnabled) {
154+
return false
155+
}
140156
return !isPaymentEnabled
141157
}
142158

@@ -159,14 +175,20 @@ const generatePdfAttachmentIfRequired = ({
159175
submission,
160176
form,
161177
responsesData,
178+
growthbook,
162179
}: {
163180
isPaymentEnabled: boolean
164181
autoReplyMailDatas: AutoReplyMailData[]
165182
submission: IEncryptedSubmissionSchema
166183
form: IPopulatedEncryptedForm
167184
responsesData: EmailAdminDataField[]
185+
growthbook?: GrowthBook
168186
}): ResultAsync<Mail.Attachment | undefined, AutoreplyPdfGenerationError> => {
169-
const isAdminPdfRequired = checkIfAdminPdfIsRequired(isPaymentEnabled)
187+
const isAdminPdfRequired = checkIfAdminPdfIsRequired(
188+
isPaymentEnabled,
189+
form.form_fields,
190+
growthbook,
191+
)
170192
const isRespondentCopyPdfRequired = checkIfRespondentFormSummaryIsRequired({
171193
isPaymentEnabled,
172194
autoReplyMailDatas,
@@ -229,12 +251,14 @@ export const performEncryptPostSubmissionActions = ({
229251
emailFields,
230252
submissionAttachments,
231253
respondentEmails,
254+
growthbook,
232255
}: {
233256
submission: IEncryptedSubmissionSchema
234257
responses: FieldResponse[]
235258
emailFields: ProcessedFieldResponse[]
236259
submissionAttachments?: Mail.Attachment[]
237260
respondentEmails?: string[]
261+
growthbook?: GrowthBook
238262
}): ResultAsync<
239263
true,
240264
| FormNotFoundError
@@ -304,6 +328,7 @@ export const performEncryptPostSubmissionActions = ({
304328
submission,
305329
form,
306330
responsesData: formData,
331+
growthbook,
307332
}).orElse(() => okAsync(undefined))
308333

309334
return pdfAttachmentResult.andThen((pdfAttachment) => {
@@ -319,7 +344,11 @@ export const performEncryptPostSubmissionActions = ({
319344
submissionAttachments,
320345
formData,
321346
dataCollationData: formattedDataCollationData,
322-
pdfAttachment: checkIfAdminPdfIsRequired(isPaymentEnabled)
347+
pdfAttachment: checkIfAdminPdfIsRequired(
348+
isPaymentEnabled,
349+
form.form_fields,
350+
growthbook,
351+
)
323352
? pdfAttachment
324353
: undefined,
325354
}).mapErr((error) => {

src/app/modules/submission/multirespondent-submission/multirespondent-submission.controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ const submitMultirespondentForm = async (
139139
encryptedPayload,
140140
logMeta,
141141
attachments: req.formsg.unencryptedAttachments,
142+
growthbook: req.growthbook,
142143
})
143144
}
144145

@@ -234,6 +235,7 @@ const updateMultirespondentSubmission = async (
234235
encryptedPayload,
235236
logMeta,
236237
attachments: req.formsg.unencryptedAttachments,
238+
growthbook: req.growthbook,
237239
})
238240
}
239241

src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts

Lines changed: 66 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
MultirespondentSubmissionDto,
2727
SnapshottedFormDef,
2828
} from '../../../../types/api'
29-
import config from '../../../config/config'
29+
import config, { isTest } from '../../../config/config'
3030
import {
3131
createLoggerWithLabel,
3232
CustomLoggerParams,
@@ -55,7 +55,10 @@ import {
5555
} from '../submission.errors'
5656
import { uploadAttachments } from '../submission.service'
5757
import { AttachmentMetadata } from '../submission.types'
58-
import { getMrfSubmissionWorkflowStatus } from '../submission.utils'
58+
import {
59+
getMrfSubmissionWorkflowStatus,
60+
isAdminEmailPdfEnabled,
61+
} from '../submission.utils'
5962
import { reportSubmissionResponseTime } from '../submissions.statsd-client'
6063

6164
import { MultirespondentSubmissionContent } from './multirespondent-submission.types'
@@ -66,6 +69,7 @@ import {
6669
getResponsesDataFromMrfResponses,
6770
retrieveWorkflowStepEmailAddresses,
6871
} from './multirespondent-submission.utils'
72+
import { GrowthBook } from '@growthbook/growthbook'
6973

7074
const logger = createLoggerWithLabel(module)
7175
const MultirespondentSubmission = getMultirespondentSubmissionModel(mongoose)
@@ -798,6 +802,7 @@ interface CheckIsWorkflowCompletionEmailPdfRequiredArgs {
798802
responses: FieldResponsesV3
799803
isRejected: boolean
800804
submissionId: string
805+
growthbook?: GrowthBook
801806
}
802807

803808
const checkIsWorkflowCompletionEmailPdfRequired = ({
@@ -806,7 +811,16 @@ const checkIsWorkflowCompletionEmailPdfRequired = ({
806811
responses,
807812
isRejected,
808813
submissionId,
814+
growthbook,
809815
}: CheckIsWorkflowCompletionEmailPdfRequiredArgs) => {
816+
const isGbFlagEnabled = isAdminEmailPdfEnabled({
817+
growthbook,
818+
formFields: form.form_fields as FormFieldSchema[],
819+
}) || isTest
820+
821+
if (!isGbFlagEnabled) {
822+
return false
823+
}
810824
const isWorkflowCompleted = checkIsWorkflowCompleted({
811825
currentStepNumber,
812826
form,
@@ -834,37 +848,14 @@ type CheckIsPdfGenerationRequiredArgs = Omit<
834848
> &
835849
CheckIsWorkflowCompletionEmailPdfRequiredArgs
836850

837-
const checkIsPdfGenerationRequired = ({
838-
responses,
839-
form,
840-
currentStepActiveFields,
841-
currentStepNumber,
842-
isRejected,
843-
submissionId,
844-
}: CheckIsPdfGenerationRequiredArgs): boolean => {
845-
return (
846-
checkIfRespondentFormSummaryIsRequired({
847-
responses,
848-
formFields: form.form_fields,
849-
currentStepActiveFields,
850-
}) ||
851-
checkIsWorkflowCompletionEmailPdfRequired({
852-
currentStepNumber,
853-
form,
854-
responses,
855-
isRejected,
856-
submissionId,
857-
})
858-
)
859-
}
860-
861851
const generatePdfAttachmentIfRequired = ({
862852
submission,
863853
form,
864854
responses,
865855
currentStepActiveFields,
866856
currentStepNumber,
867857
isRejected,
858+
growthbook,
868859
}: CheckIsPdfGenerationRequiredArgs & {
869860
submission: IMultirespondentSubmissionSchema
870861
form: Pick<
@@ -893,6 +884,7 @@ const generatePdfAttachmentIfRequired = ({
893884
responses,
894885
isRejected,
895886
submissionId,
887+
growthbook,
896888
})
897889

898890
if (!isRespondentCopyPdfRequired && !isWorkflowCompletionEmailPdfRequired) {
@@ -945,13 +937,15 @@ export const performMultiRespondentPostSubmissionCreateActions = ({
945937
encryptedPayload,
946938
logMeta,
947939
attachments,
940+
growthbook,
948941
}: {
949942
submission: IMultirespondentSubmissionSchema
950943
submissionId: string
951944
form: IPopulatedMultirespondentForm
952945
encryptedPayload: MultirespondentSubmissionDto
953946
logMeta: CustomLoggerParams['meta']
954947
attachments?: IAttachmentInfo[]
948+
growthbook?: GrowthBook
955949
}): ResultAsync<boolean, InvalidWorkflowTypeError | MailSendError> => {
956950
const { submissionSecretKey, responses } = encryptedPayload
957951
const currentStepNumber = 0
@@ -974,14 +968,33 @@ export const performMultiRespondentPostSubmissionCreateActions = ({
974968
submissionId,
975969
})
976970

971+
const sendMrfRespondentCopyEmailsPdfResult = checkIfRespondentFormSummaryIsRequired({
972+
responses,
973+
formFields: form.form_fields,
974+
currentStepActiveFields: form.workflow[currentStepNumber]?.edit ?? [],
975+
})
976+
? pdfResult
977+
: okAsync(undefined)
978+
979+
const sendMrfOutcomeEmailsPdfResult = checkIsWorkflowCompletionEmailPdfRequired({
980+
currentStepNumber,
981+
form,
982+
responses,
983+
isRejected: false,
984+
submissionId,
985+
growthbook,
986+
})
987+
? pdfResult
988+
: okAsync(undefined)
989+
977990
sendMrfRespondentCopyEmails({
978991
form,
979992
responses,
980993
submission,
981994
attachments,
982995
formFields: form.form_fields,
983996
currentStepActiveFields: form.workflow[currentStepNumber]?.edit ?? [],
984-
pdfResult,
997+
pdfResult: sendMrfRespondentCopyEmailsPdfResult,
985998
}).mapErr((error) => {
986999
logger.error({
9871000
message: 'Send multirespondent respondent copy email error',
@@ -1040,7 +1053,7 @@ export const performMultiRespondentPostSubmissionCreateActions = ({
10401053
responses,
10411054
submissionId,
10421055
attachments,
1043-
pdfResult,
1056+
pdfResult: sendMrfOutcomeEmailsPdfResult,
10441057
})
10451058
})
10461059
.mapErr((error) => {
@@ -1208,6 +1221,7 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
12081221
encryptedPayload,
12091222
logMeta,
12101223
attachments,
1224+
growthbook,
12111225
}: {
12121226
submission: IMultirespondentSubmissionSchema
12131227
submissionId: string
@@ -1216,6 +1230,7 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
12161230
encryptedPayload: MultirespondentSubmissionDto
12171231
logMeta: CustomLoggerParams['meta']
12181232
attachments?: IAttachmentInfo[]
1233+
growthbook?: GrowthBook
12191234
}): ResultAsync<
12201235
boolean,
12211236
| InvalidWorkflowTypeError
@@ -1290,6 +1305,26 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
12901305
snapshottedFormDef.workflow[currentStepNumber]?.edit ?? [],
12911306
})
12921307

1308+
const sendMrfRespondentCopyEmailsPdfResult = checkIfRespondentFormSummaryIsRequired({
1309+
responses,
1310+
formFields: snapshottedFormDef.form_fields,
1311+
currentStepActiveFields:
1312+
snapshottedFormDef.workflow[currentStepNumber]?.edit ?? [],
1313+
})
1314+
? pdfResult
1315+
: okAsync(undefined)
1316+
1317+
const sendMrfOutcomeEmailsPdfResult = checkIsWorkflowCompletionEmailPdfRequired({
1318+
currentStepNumber,
1319+
form: snapshottedFormDef,
1320+
responses,
1321+
isRejected: isStepRejected,
1322+
submissionId,
1323+
growthbook,
1324+
})
1325+
? pdfResult
1326+
: okAsync(undefined)
1327+
12931328
sendMrfRespondentCopyEmails({
12941329
form: snapshottedFormDef,
12951330
responses,
@@ -1298,14 +1333,7 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
12981333
formFields: snapshottedFormDef.form_fields,
12991334
currentStepActiveFields:
13001335
snapshottedFormDef.workflow[currentStepNumber]?.edit ?? [],
1301-
pdfResult: checkIfRespondentFormSummaryIsRequired({
1302-
responses,
1303-
formFields: snapshottedFormDef.form_fields,
1304-
currentStepActiveFields:
1305-
snapshottedFormDef.workflow[currentStepNumber]?.edit ?? [],
1306-
})
1307-
? pdfResult
1308-
: okAsync(undefined),
1336+
pdfResult: sendMrfRespondentCopyEmailsPdfResult,
13091337
}).mapErr((error) => {
13101338
logger.error({
13111339
message: 'Send multirespondent respondent copy email error',
@@ -1323,7 +1351,7 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
13231351
isApproval: true,
13241352
isRejected: true,
13251353
attachments: attachments,
1326-
pdfResult: pdfResult,
1354+
pdfResult: sendMrfOutcomeEmailsPdfResult,
13271355
}).mapErr((error) => {
13281356
logger.error({
13291357
message: 'Send mrf outcome email error',
@@ -1340,15 +1368,7 @@ export const performMultiRespondentPostSubmissionUpdateActions = ({
13401368
submissionId,
13411369
isApproval: checkIsFormApproval(snapshottedFormDef),
13421370
attachments: attachments,
1343-
pdfResult: checkIsWorkflowCompletionEmailPdfRequired({
1344-
currentStepNumber,
1345-
form: snapshottedFormDef,
1346-
responses,
1347-
isRejected: isStepRejected,
1348-
submissionId,
1349-
})
1350-
? pdfResult
1351-
: okAsync(undefined),
1371+
pdfResult: sendMrfOutcomeEmailsPdfResult,
13521372
})
13531373
.mapErr((error) => {
13541374
logger.error({

0 commit comments

Comments
 (0)