From 533a645d64d1a9c5038d56d829b062d2b0959508 Mon Sep 17 00:00:00 2001 From: Kyle Morel Date: Thu, 3 Oct 2024 11:54:10 -0700 Subject: [PATCH 1/2] Changes to Submission/Enquiry draft saving endpoints --- app/src/controllers/enquiry.ts | 62 +++--- app/src/controllers/submission.ts | 178 ++++++++++-------- app/src/routes/v1/enquiry.ts | 34 +--- app/src/routes/v1/submission.ts | 13 +- app/src/validators/enquiry.ts | 17 +- .../housing/enquiry/EnquiryIntakeForm.vue | 171 +++++++++-------- .../submission/SubmissionIntakeForm.vue | 53 +++--- frontend/src/services/enquiryService.ts | 20 +- frontend/src/services/submissionService.ts | 20 +- .../housing/enquiry/EnquiryIntakeView.vue | 6 +- .../submission/SubmissionIntakeView.vue | 6 +- 11 files changed, 308 insertions(+), 272 deletions(-) diff --git a/app/src/controllers/enquiry.ts b/app/src/controllers/enquiry.ts index d413e03c..321f489c 100644 --- a/app/src/controllers/enquiry.ts +++ b/app/src/controllers/enquiry.ts @@ -78,22 +78,6 @@ const controller = { }; }, - createDraft: async (req: Request, res: Response, next: NextFunction) => { - try { - const enquiry = await controller.generateEnquiryData(req); - - // Create new enquiry - const result = await enquiryService.createEnquiry({ - ...enquiry, - ...generateCreateStamps(req.currentContext) - }); - - res.status(201).json({ activityId: result.activityId, enquiryId: result.enquiryId }); - } catch (e: unknown) { - next(e); - } - }, - deleteEnquiry: async (req: Request<{ enquiryId: string }>, res: Response, next: NextFunction) => { try { const response = await enquiryService.deleteEnquiry(req.params.enquiryId); @@ -137,6 +121,32 @@ const controller = { } }, + submitDraft: async (req: Request, res: Response, next: NextFunction) => { + try { + const update = req.body.activityId && req.body.enquiryId; + + const enquiry = await controller.generateEnquiryData(req); + + let result; + if (update) { + result = await enquiryService.updateEnquiry({ + ...enquiry, + ...generateUpdateStamps(req.currentContext) + } as Enquiry); + } else { + // Create new enquiry + result = await enquiryService.createEnquiry({ + ...enquiry, + ...generateCreateStamps(req.currentContext) + }); + } + + res.status(201).json({ activityId: result.activityId, enquiryId: result.enquiryId }); + } catch (e: unknown) { + next(e); + } + }, + updateEnquiry: async (req: Request, res: Response, next: NextFunction) => { try { const result = await enquiryService.updateEnquiry({ @@ -152,13 +162,23 @@ const controller = { updateDraft: async (req: Request, res: Response, next: NextFunction) => { try { + const update = req.body.activityId && req.body.enquiryId; + const enquiry = await controller.generateEnquiryData(req); - // Update enquiry - const result = await enquiryService.updateEnquiry({ - ...(enquiry as Enquiry), - ...generateUpdateStamps(req.currentContext) - }); + let result; + if (update) { + result = await enquiryService.updateEnquiry({ + ...enquiry, + ...generateUpdateStamps(req.currentContext) + } as Enquiry); + } else { + // Create new enquiry + result = await enquiryService.createEnquiry({ + ...enquiry, + ...generateCreateStamps(req.currentContext) + }); + } res.status(200).json({ activityId: result.activityId, enquiryId: result.enquiryId }); } catch (e: unknown) { diff --git a/app/src/controllers/submission.ts b/app/src/controllers/submission.ts index 06986cbe..d54359aa 100644 --- a/app/src/controllers/submission.ts +++ b/app/src/controllers/submission.ts @@ -29,6 +29,40 @@ import type { } from '../types'; const controller = { + /** + * @function assignPriority + * Assigns a priority level to a submission based on given criteria + * Criteria defined below + */ + assignPriority: (submission: Partial) => { + const matchesPriorityOneCriteria = // Priority 1 Criteria: + submission.singleFamilyUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || // 1. More than 50 units (any) + submission.singleFamilyUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || + submission.multiFamilyUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || + submission.multiFamilyUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || + submission.otherUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || + submission.otherUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || + submission.hasRentalUnits === 'Yes' || // 2. Supports Rental Units + submission.financiallySupportedBC === 'Yes' || // 3. Social Housing + submission.financiallySupportedIndigenous === 'Yes'; // 4. Indigenous Led + + const matchesPriorityTwoCriteria = // Priority 2 Criteria: + submission.singleFamilyUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 1. Single Family >= 10 Units + submission.multiFamilyUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 2. Has 1 or more MultiFamily Units + submission.multiFamilyUnits === NumResidentialUnits.ONE_TO_NINE || + submission.otherUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 3. Has 1 or more Other Units + submission.otherUnits === NumResidentialUnits.ONE_TO_NINE; + + if (matchesPriorityOneCriteria) { + submission.queuePriority = 1; + } else if (matchesPriorityTwoCriteria) { + submission.queuePriority = 2; + } else { + // Prioriy 3 Criteria: + submission.queuePriority = 3; // Everything Else + } + }, + checkAndStoreNewSubmissions: async () => { const cfg = config.get('server.chefs.forms') as ChefsFormConfig; @@ -308,35 +342,26 @@ const controller = { return submissionData; }, - getActivityIds: async (req: Request, res: Response, next: NextFunction) => { + /** + * @function emailConfirmation + * Send an email with the confirmation of submission + */ + emailConfirmation: async (req: Request, res: Response, next: NextFunction) => { try { - let response = await submissionService.getSubmissions(); - if (req.currentAuthorization?.attributes.includes('scope:self')) { - response = response.filter((x: Submission) => x?.submittedBy === getCurrentUsername(req.currentContext)); - } - res.status(200).json(response.map((x) => x.activityId)); + const { data, status } = await emailService.email(req.body); + res.status(status).json(data); } catch (e: unknown) { next(e); } }, - createDraft: async (req: Request, res: Response, next: NextFunction) => { + getActivityIds: async (req: Request, res: Response, next: NextFunction) => { try { - const { submission, appliedPermits, investigatePermits } = await controller.generateSubmissionData( - req, - req.body.submit ? IntakeStatus.SUBMITTED : IntakeStatus.DRAFT - ); - - // Create new submission - const result = await submissionService.createSubmission({ - ...submission, - ...generateCreateStamps(req.currentContext) - }); - - // Create each permit - await Promise.all(appliedPermits.map(async (x: Permit) => await permitService.createPermit(x))); - await Promise.all(investigatePermits.map(async (x: Permit) => await permitService.createPermit(x))); - res.status(201).json({ activityId: result.activityId, submissionId: result.submissionId }); + let response = await submissionService.getSubmissions(); + if (req.currentAuthorization?.attributes.includes('scope:self')) { + response = response.filter((x: Submission) => x?.submittedBy === getCurrentUsername(req.currentContext)); + } + res.status(200).json(response.map((x) => x.activityId)); } catch (e: unknown) { next(e); } @@ -443,18 +468,68 @@ const controller = { } }, + submitDraft: async (req: Request, res: Response, next: NextFunction) => { + try { + const update = req.body.activityId && req.body.submissionId; + + const { submission, appliedPermits, investigatePermits } = await controller.generateSubmissionData( + req, + IntakeStatus.SUBMITTED + ); + + let result; + + if (update) { + // Update submission + result = await submissionService.updateSubmission({ + ...submission, + ...generateUpdateStamps(req.currentContext) + }); + } else { + // Create new submission + result = await submissionService.createSubmission({ + ...submission, + ...generateCreateStamps(req.currentContext) + }); + } + + // Remove already existing permits for this activity + await permitService.deletePermitsByActivity(submission.activityId); + + // Create each permit + await Promise.all(appliedPermits.map(async (x: Permit) => await permitService.createPermit(x))); + await Promise.all(investigatePermits.map(async (x: Permit) => await permitService.createPermit(x))); + + res.status(200).json({ activityId: result.activityId, submissionId: result.submissionId }); + } catch (e: unknown) { + next(e); + } + }, + updateDraft: async (req: Request, res: Response, next: NextFunction) => { try { + const update = req.body.activityId && req.body.submissionId; + const { submission, appliedPermits, investigatePermits } = await controller.generateSubmissionData( req, - req.body.submit ? IntakeStatus.SUBMITTED : IntakeStatus.DRAFT + IntakeStatus.DRAFT ); - // Update submission - const result = await submissionService.updateSubmission({ - ...submission, - ...generateUpdateStamps(req.currentContext) - }); + let result; + + if (update) { + // Update submission + result = await submissionService.updateSubmission({ + ...submission, + ...generateUpdateStamps(req.currentContext) + }); + } else { + // Create new submission + result = await submissionService.createSubmission({ + ...submission, + ...generateCreateStamps(req.currentContext) + }); + } // Remove already existing permits for this activity await permitService.deletePermitsByActivity(submission.activityId); @@ -496,53 +571,6 @@ const controller = { } catch (e: unknown) { next(e); } - }, - - /** - * @function emailConfirmation - * Send an email with the confirmation of submission - */ - emailConfirmation: async (req: Request, res: Response, next: NextFunction) => { - try { - const { data, status } = await emailService.email(req.body); - res.status(status).json(data); - } catch (e: unknown) { - next(e); - } - }, - - /** - * @function assignPriority - * Assigns a priority level to a submission based on given criteria - * Criteria defined below - */ - assignPriority: (submission: Partial) => { - const matchesPriorityOneCriteria = // Priority 1 Criteria: - submission.singleFamilyUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || // 1. More than 50 units (any) - submission.singleFamilyUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || - submission.multiFamilyUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || - submission.multiFamilyUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || - submission.otherUnits === NumResidentialUnits.GREATER_THAN_FIVE_HUNDRED || - submission.otherUnits === NumResidentialUnits.FIFTY_TO_FIVE_HUNDRED || - submission.hasRentalUnits === 'Yes' || // 2. Supports Rental Units - submission.financiallySupportedBC === 'Yes' || // 3. Social Housing - submission.financiallySupportedIndigenous === 'Yes'; // 4. Indigenous Led - - const matchesPriorityTwoCriteria = // Priority 2 Criteria: - submission.singleFamilyUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 1. Single Family >= 10 Units - submission.multiFamilyUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 2. Has 1 or more MultiFamily Units - submission.multiFamilyUnits === NumResidentialUnits.ONE_TO_NINE || - submission.otherUnits === NumResidentialUnits.TEN_TO_FOURTY_NINE || // 3. Has 1 or more Other Units - submission.otherUnits === NumResidentialUnits.ONE_TO_NINE; - - if (matchesPriorityOneCriteria) { - submission.queuePriority = 1; - } else if (matchesPriorityTwoCriteria) { - submission.queuePriority = 2; - } else { - // Prioriy 3 Criteria: - submission.queuePriority = 3; // Everything Else - } } }; diff --git a/app/src/routes/v1/enquiry.ts b/app/src/routes/v1/enquiry.ts index 78f20648..08eeb0d4 100644 --- a/app/src/routes/v1/enquiry.ts +++ b/app/src/routes/v1/enquiry.ts @@ -8,25 +8,12 @@ import { Action, Resource } from '../../utils/enums/application'; import { enquiryValidator } from '../../validators'; import type { NextFunction, Request, Response } from 'express'; -import type { Enquiry, EnquiryIntake, Middleware } from '../../types'; +import type { Enquiry, EnquiryIntake } from '../../types'; const router = express.Router(); router.use(requireSomeAuth); router.use(requireSomeGroup); -const decideValidation = (validator: Middleware) => { - return (req: Request, _res: Response, next: NextFunction) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const body: any = req.body; - - if (body.submit) { - return validator(req, _res, next); - } else { - return next(); - } - }; -}; - /** Gets a list of enquiries */ router.get( '/', @@ -61,24 +48,23 @@ router.delete( } ); -/** Creates an enquiry with Draft status */ +/** Creates or updates an intake and set status to Draft */ router.put( - '/draft', + '/draft/', hasAuthorization(Resource.ENQUIRY, Action.CREATE), - decideValidation(enquiryValidator.createDraft), + enquiryValidator.createOrUpdateDraft, (req: Request, res: Response, next: NextFunction): void => { - enquiryController.createDraft(req, res, next); + enquiryController.updateDraft(req, res, next); } ); -/** Updates an enquiry with Draft status */ +/** Creates or updates an intake and set status to Submitted */ router.put( - '/draft/:enquiryId', - hasAuthorization(Resource.ENQUIRY, Action.UPDATE), - hasAccess('enquiryId'), - decideValidation(enquiryValidator.updateDraft), + '/draft/submit', + hasAuthorization(Resource.ENQUIRY, Action.CREATE), + enquiryValidator.createOrUpdateDraft, (req: Request, res: Response, next: NextFunction): void => { - enquiryController.updateDraft(req, res, next); + enquiryController.submitDraft(req, res, next); } ); diff --git a/app/src/routes/v1/submission.ts b/app/src/routes/v1/submission.ts index 5e84b9a2..3807929f 100644 --- a/app/src/routes/v1/submission.ts +++ b/app/src/routes/v1/submission.ts @@ -52,22 +52,21 @@ router.get( } ); -/** Creates a submission with Draft status */ +/** Creates or updates an intake and set status to Draft */ router.put( '/draft', hasAuthorization(Resource.SUBMISSION, Action.CREATE), (req: Request, res: Response, next: NextFunction): void => { - submissionController.createDraft(req, res, next); + submissionController.updateDraft(req, res, next); } ); -/** Updates a submission with Draft status */ +/** Creates or updates an intake and set status to Submitted */ router.put( - '/draft/:submissionId', - hasAuthorization(Resource.SUBMISSION, Action.UPDATE), - hasAccess('submissionId'), + '/draft/submit', + hasAuthorization(Resource.SUBMISSION, Action.CREATE), (req: Request, res: Response, next: NextFunction): void => { - submissionController.updateDraft(req, res, next); + submissionController.submitDraft(req, res, next); } ); diff --git a/app/src/validators/enquiry.ts b/app/src/validators/enquiry.ts index a1d2e597..7f67e291 100644 --- a/app/src/validators/enquiry.ts +++ b/app/src/validators/enquiry.ts @@ -8,11 +8,12 @@ import { YES_NO_LIST } from '../utils/constants/application'; import { APPLICATION_STATUS_LIST, INTAKE_STATUS_LIST } from '../utils/constants/housing'; const schema = { - createDraft: { + createOrUpdateDraft: { body: Joi.object({ applicant: applicant, basic: basicEnquiry, - submit: Joi.boolean() + activityId: Joi.string(), + enquiryId: Joi.string() }) }, deleteEnquiry: { @@ -20,15 +21,6 @@ const schema = { enquiryId: uuidv4.required() }) }, - updateDraft: { - body: Joi.object({ - applicant: applicant, - basic: basicEnquiry, - submit: Joi.boolean(), - enquiryId: Joi.string().required(), - activityId: Joi.string().required() - }) - }, updateIsDeletedFlag: { params: Joi.object({ enquiryId: uuidv4.required() @@ -73,9 +65,8 @@ const schema = { }; export default { - createDraft: validate(schema.createDraft), + createOrUpdateDraft: validate(schema.createOrUpdateDraft), deleteEnquiry: validate(schema.deleteEnquiry), - updateDraft: validate(schema.updateDraft), updateIsDeletedFlag: validate(schema.updateIsDeletedFlag), updateEnquiry: validate(schema.updateEnquiry) }; diff --git a/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue b/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue index 9e614333..2442ac00 100644 --- a/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue +++ b/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue @@ -125,6 +125,64 @@ function confirmSubmit(data: any) { }); } +async function emailConfirmation(activityId: string, enquiryId: string) { + const configCC = getConfig.value.ches?.submission?.cc; + + // Get the first two sentences of the enquiry description + // If there are more than two sentences in enquiryDescription, add '..' to the end + const enquiryDescription = formRef.value?.values.basic.enquiryDescription || ''; + let firstTwoSentences = enquiryDescription.split('.').slice(0, 2).join('.') + '.'; + const sentences = enquiryDescription.split('.').filter((sentence: string) => sentence.trim().length > 0); + firstTwoSentences = sentences.length > 2 ? firstTwoSentences.concat('..') : firstTwoSentences; + + const body = confirmationTemplateEnquiry({ + '{{ contactName }}': formRef.value?.values.applicant.contactFirstName, + '{{ activityId }}': activityId, + '{{ enquiryDescription }}': firstTwoSentences.trim(), + '{{ enquiryId }}': enquiryId + }); + let applicantEmail = formRef.value?.values.applicant.contactEmail; + let emailData = { + from: configCC, + to: [applicantEmail], + cc: configCC, + subject: 'Confirmation of Submission', // eslint-disable-line quotes + bodyType: 'html', + body: body + }; + await submissionService.emailConfirmation(emailData); +} + +async function loadEnquiry() { + try { + if (enquiryId) { + const formVal = (await enquiryService.getEnquiry(enquiryId as string)).data; + editable.value = formVal.intakeStatus === IntakeStatus.DRAFT; + + initialFormValues.value = { + activityId: formVal?.activityId, + enquiryId: formVal?.enquiryId, + applicant: { + contactFirstName: formVal?.contactFirstName, + contactLastName: formVal?.contactLastName, + contactPhoneNumber: formVal?.contactPhoneNumber, + contactEmail: formVal?.contactEmail, + contactApplicantRelationship: formVal?.contactApplicantRelationship, + contactPreference: formVal?.contactPreference + }, + basic: { + isRelated: formVal?.isRelated, + relatedActivityId: formVal?.relatedActivityId, + enquiryDescription: formVal?.enquiryDescription, + applyForPermitConnect: formVal?.applyForPermitConnect + } + }; + } + } catch (e: any) { + router.replace({ name: RouteName.HOUSING_ENQUIRY_INTAKE }); + } +} + function onInvalidSubmit(e: any) { validationErrors.value = Array.from(new Set(e.errors ? Object.keys(e.errors).map((x) => x.split('.')[0]) : [])); document.getElementById('form')?.scrollIntoView({ behavior: 'smooth' }); @@ -134,16 +192,20 @@ async function onSaveDraft(data: any, isAutoSave = false) { editable.value = false; try { - let response; - if (data.enquiryId) { - response = await enquiryService.updateDraft(data.enquiryId, data); - } else { - response = await enquiryService.createDraft(data); - } + let response = await enquiryService.updateDraft(data); - if (response.data.enquiryId && response.data.activityId) { - formRef.value?.setFieldValue('enquiryId', response.data.enquiryId); + if (response.data.activityId && response.data.enquiryId) { formRef.value?.setFieldValue('activityId', response.data.activityId); + formRef.value?.setFieldValue('enquiryId', response.data.enquiryId); + + // Update route query for refreshing + router.replace({ + name: RouteName.HOUSING_ENQUIRY_INTAKE, + query: { + activityId: response.data.activityId, + enquiryId: response.data.enquiryId + } + }); } else { throw new Error('Failed to retrieve correct draft data'); } @@ -160,6 +222,12 @@ async function onSaveDraft(data: any, isAutoSave = false) { } } +function onRelatedActivityInput(e: IInputEvent) { + filteredProjectActivityIds.value = projectActivityIds.value.filter((id) => + id.toUpperCase().includes(e.target.value.toUpperCase()) + ); +} + async function onSubmit(data: any) { editable.value = false; @@ -170,7 +238,7 @@ async function onSubmit(data: any) { try { // Need to first create the submission to relate to if asking to apply if (data.basic.applyForPermitConnect === BasicResponse.YES) { - submissionResponse = await submissionService.createDraft({ applicant: data.applicant }); + submissionResponse = await submissionService.submitDraft({ applicant: data.applicant }); if (submissionResponse.data.activityId) { formRef.value?.setFieldValue('basic.relatedActivityId', submissionResponse.data.activityId); } else { @@ -178,17 +246,22 @@ async function onSubmit(data: any) { } } - if (data.enquiryId) { - enquiryResponse = await enquiryService.updateDraft(data.enquiryId, { ...data, submit: true }); - } else { - enquiryResponse = await enquiryService.createDraft({ ...data, submit: true }); - } + enquiryResponse = await enquiryService.submitDraft(data); - if (enquiryResponse.data.activityId) { + if (enquiryResponse.data.activityId && enquiryResponse.data.enquiryId) { assignedActivityId.value = enquiryResponse.data.activityId; formRef.value?.setFieldValue('activityId', enquiryResponse.data.activityId); formRef.value?.setFieldValue('enquiryId', enquiryResponse.data.enquiryId); + // Update route query for refreshing + router.replace({ + name: RouteName.HOUSING_ENQUIRY_INTAKE, + query: { + activityId: enquiryResponse.data.activityId, + enquiryId: enquiryResponse.data.enquiryId + } + }); + // Send confirmation email emailConfirmation(enquiryResponse.data.activityId, enquiryResponse.data.enquiryId); } else { @@ -211,77 +284,11 @@ async function onSubmit(data: any) { } } -async function loadEnquiry() { - try { - let response; - - if (enquiryId) { - response = (await enquiryService.getEnquiry(enquiryId as string)).data; - editable.value = response.intakeStatus === IntakeStatus.DRAFT; - } - - initialFormValues.value = { - activityId: response?.activityId, - enquiryId: response?.enquiryId, - applicant: { - contactFirstName: response?.contactFirstName, - contactLastName: response?.contactLastName, - contactPhoneNumber: response?.contactPhoneNumber, - contactEmail: response?.contactEmail, - contactApplicantRelationship: response?.contactApplicantRelationship, - contactPreference: response?.contactPreference - }, - basic: { - isRelated: response?.isRelated, - relatedActivityId: response?.relatedActivityId, - enquiryDescription: response?.enquiryDescription, - applyForPermitConnect: response?.applyForPermitConnect - } - }; - } catch (e: any) { - router.replace({ name: RouteName.HOUSING_ENQUIRY_INTAKE }); - } -} - -function onRelatedActivityInput(e: IInputEvent) { - filteredProjectActivityIds.value = projectActivityIds.value.filter((id) => - id.toUpperCase().includes(e.target.value.toUpperCase()) - ); -} - onBeforeMount(async () => { loadEnquiry(); projectActivityIds.value = filteredProjectActivityIds.value = (await submissionService.getActivityIds()).data; submissions.value = (await submissionService.getSubmissions()).data; }); - -async function emailConfirmation(activityId: string, enquiryId: string) { - const configCC = getConfig.value.ches?.submission?.cc; - - // Get the first two sentences of the enquiry description - // If there are more than two sentences in enquiryDescription, add '..' to the end - const enquiryDescription = formRef.value?.values.basic.enquiryDescription || ''; - let firstTwoSentences = enquiryDescription.split('.').slice(0, 2).join('.') + '.'; - const sentences = enquiryDescription.split('.').filter((sentence: string) => sentence.trim().length > 0); - firstTwoSentences = sentences.length > 2 ? firstTwoSentences.concat('..') : firstTwoSentences; - - const body = confirmationTemplateEnquiry({ - '{{ contactName }}': formRef.value?.values.applicant.contactFirstName, - '{{ activityId }}': activityId, - '{{ enquiryDescription }}': firstTwoSentences.trim(), - '{{ enquiryId }}': enquiryId - }); - let applicantEmail = formRef.value?.values.applicant.contactEmail; - let emailData = { - from: configCC, - to: [applicantEmail], - cc: configCC, - subject: 'Confirmation of Submission', // eslint-disable-line quotes - bodyType: 'html', - body: body - }; - await submissionService.emailConfirmation(emailData); -}