Skip to content

Commit

Permalink
Send email confirmation when SHAS/Enquiry confirmation page is displayed
Browse files Browse the repository at this point in the history
  • Loading branch information
sanjaytkbabu committed Jun 11, 2024
1 parent aa62bc7 commit 53b0da2
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/environments/values.dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config:
configMap:
FRONTEND_APIPATH: api/v1
FRONTEND_CHES_BCC: [email protected]
FRONTEND_CHES_CC: [email protected]
FRONTEND_COMS_APIPATH: https://coms-dev.api.gov.bc.ca/api/v1
FRONTEND_COMS_BUCKETID: 1f9e1451-c130-4804-aeb0-b78b5b109c47
FRONTEND_GEOCODER_APIPATH: https://geocoder.api.gov.bc.ca
Expand Down
1 change: 1 addition & 0 deletions .github/environments/values.prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config:
configMap:
FRONTEND_APIPATH: api/v1
FRONTEND_CHES_BCC: [email protected]
FRONTEND_CHES_CC: [email protected]
FRONTEND_COMS_APIPATH: https://coms.api.gov.bc.ca/api/v1
FRONTEND_COMS_BUCKETID: 0089d041-5aab-485e-842d-8875475d0ed6
FRONTEND_GEOCODER_APIPATH: https://geocoder.api.gov.bc.ca
Expand Down
1 change: 1 addition & 0 deletions .github/environments/values.test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config:
configMap:
FRONTEND_APIPATH: api/v1
FRONTEND_CHES_BCC: [email protected]
FRONTEND_CHES_CC: [email protected]
FRONTEND_COMS_APIPATH: https://coms-test.api.gov.bc.ca/api/v1
FRONTEND_COMS_BUCKETID: a9eabd1d-5f77-4c60-bf6b-83ffa0e21c59
FRONTEND_GEOCODER_APIPATH: https://geocoder.api.gov.bc.ca
Expand Down
3 changes: 2 additions & 1 deletion app/config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"frontend": {
"apiPath": "FRONTEND_APIPATH",
"ches": {
"bcc": "FRONTEND_CHES_BCC"
"bcc": "FRONTEND_CHES_BCC",
"cc": "FRONTEND_CHES_CC"
},
"coms": {
"apiPath": "FRONTEND_COMS_APIPATH",
Expand Down
17 changes: 14 additions & 3 deletions app/src/controllers/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
YES_NO_UNSURE
} from '../components/constants';
import { camelCaseToTitleCase, deDupeUnsure, getCurrentIdentity, isTruthy, toTitleCase } from '../components/utils';
import { activityService, submissionService, permitService, userService } from '../services';
import { activityService, emailService, submissionService, permitService, userService } from '../services';

import type { NextFunction, Request, Response } from '../interfaces/IExpress';
import type { ChefsFormConfig, ChefsFormConfigData, Submission, ChefsSubmissionExport, Permit } from '../types';
import type { ChefsFormConfig, ChefsFormConfigData, Email, Submission, ChefsSubmissionExport, Permit } from '../types';

const controller = {
checkAndStoreNewSubmissions: async () => {
Expand Down Expand Up @@ -299,7 +299,6 @@ const controller = {
// 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 });
} catch (e: unknown) {
next(e);
Expand Down Expand Up @@ -410,6 +409,18 @@ const controller = {
} catch (e: unknown) {
next(e);
}
},
/**
* @function emailConfirmation
* Send an email with the confirmation of submission
*/
emailConfirmation: async (req: Request<never, never, { emailData: Email }>, res: Response, next: NextFunction) => {
try {
const { data, status } = await emailService.email(req.body.emailData);
res.status(status).json(data);
} catch (e: unknown) {
next(e);
}
}
};

Expand Down
9 changes: 9 additions & 0 deletions app/src/routes/v1/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ router.put('/draft/:submissionId', (req: Request, res: Response, next: NextFunct
submissionController.updateDraft(req, res, next);
});

// Send an email with the confirmation of submission
router.put(
'/emailConfirmation',
submissionValidator.emailConfirmation,
(req: Request, res: Response, next: NextFunction): void => {
submissionController.emailConfirmation(req, res, next);
}
);

/** Creates a submission */
router.put('/', submissionValidator.createSubmission, (req: Request, res: Response, next: NextFunction): void => {
submissionController.createSubmission(req, res, next);
Expand Down
16 changes: 15 additions & 1 deletion app/src/validators/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ const schema = {
params: Joi.object({
submissionId: uuidv4.required()
})
},
emailConfirmation: {
body: Joi.object({
emailData: Joi.object().keys({
bcc: Joi.array().items(emailJoi).allow(null),
bodyType: Joi.string().required().allow(null),
body: Joi.string().required(),
cc: Joi.array().items(emailJoi),
from: emailJoi.required(),
subject: Joi.string().required(),
to: Joi.array().items(emailJoi).required()
})
})
}
};

Expand All @@ -104,5 +117,6 @@ export default {
deleteSubmission: validate(schema.deleteSubmission),
getStatistics: validate(schema.getStatistics),
getSubmission: validate(schema.getSubmission),
updateSubmission: validate(schema.updateSubmission)
updateSubmission: validate(schema.updateSubmission),
emailConfirmation: validate(schema.emailConfirmation)
};
1 change: 1 addition & 0 deletions charts/pcns/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ config:
configMap:
FRONTEND_APIPATH: api/v1
FRONTEND_CHES_BCC: ~
FRONTEND_CHES_CC: ~
FRONTEND_COMS_APIPATH: ~
FRONTEND_COMS_BUCKETID: ~
FRONTEND_GEOCODER_APIPATH: ~
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/components/housing/intake/ShasEnquiryForm.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { Form } from 'vee-validate';
import { onBeforeMount, ref, toRaw } from 'vue';
import { useRouter } from 'vue-router';
Expand All @@ -8,8 +9,10 @@ import { Dropdown, InputMask, RadioList, InputText, StepperNavigation, TextArea
import CollectionDisclaimer from '@/components/housing/intake/CollectionDisclaimer.vue';
import { Button, Card, Divider, Message, useConfirm, useToast } from '@/lib/primevue';
import { enquiryService, submissionService } from '@/services';
import { useConfigStore } from '@/store';
import { ContactPreferenceList, ProjectRelationshipList, Regex, RouteNames, YesNo } from '@/utils/constants';
import { BASIC_RESPONSES, INTAKE_FORM_CATEGORIES, INTAKE_STATUS_LIST } from '@/utils/enums';
import { confirmationTemplate } from '@/utils/templates';
import type { Ref } from 'vue';
Expand All @@ -24,6 +27,9 @@ const props = withDefaults(defineProps<Props>(), {
enquiryId: undefined
});
//Store
const { getConfig } = storeToRefs(useConfigStore());
// State
const assignedActivityId: Ref<string | undefined> = ref(undefined);
const editable: Ref<boolean> = ref(true);
Expand Down Expand Up @@ -156,6 +162,8 @@ async function onSubmit(data: any) {
assignedActivityId.value = enquiryResponse.data.activityId;
formRef.value?.setFieldValue('activityId', enquiryResponse.data.activityId);
formRef.value?.setFieldValue('enquiryId', enquiryResponse.data.enquiryId);
//send confirmation email
emailConfirmation(enquiryResponse.data.activityId);
} else {
throw new Error('Failed to retrieve correct enquiry draft data');
}
Expand Down Expand Up @@ -203,6 +211,24 @@ onBeforeMount(async () => {
}
};
});
async function emailConfirmation(activityId: string) {
const configCC = getConfig.value.ches?.cc;
const body = confirmationTemplate({
'{{ contactName }}': formRef.value?.values.applicant.firstName,
'{{ activityId }}': activityId
});
let applicantEmail = formRef.value?.values.applicant.email;
let emailData = {
from: configCC,
to: [applicantEmail],
cc: configCC,
subject: 'Confirmation of Submission', // eslint-disable-line quotes
bodyType: 'text',
body: body
};
await submissionService.emailConfirmation(emailData);
}
</script>

<template>
Expand Down
24 changes: 23 additions & 1 deletion frontend/src/components/housing/intake/ShasIntakeForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
useToast
} from '@/lib/primevue';
import { externalApiService, permitService, submissionService } from '@/services';
import { useTypeStore } from '@/store';
import { useConfigStore, useTypeStore } from '@/store';
import {
ContactPreferenceList,
NumResidentialUnits,
Expand All @@ -53,6 +53,7 @@ import {
PERMIT_STATUS,
PROJECT_LOCATION
} from '@/utils/enums';
import { confirmationTemplate } from '@/utils/templates';
import type { IInputEvent } from '@/interfaces';
import type { AutoCompleteCompleteEvent } from 'primevue/autocomplete';
Expand Down Expand Up @@ -84,6 +85,7 @@ const VALIDATION_BANNER_TEXT =
// Store
const typeStore = useTypeStore();
const { getPermitTypes } = storeToRefs(typeStore);
const { getConfig } = storeToRefs(useConfigStore());
// State
const activeStep: Ref<number> = ref(0);
Expand Down Expand Up @@ -225,6 +227,8 @@ async function onSubmit(data: any) {
if (response.data.activityId) {
assignedActivityId.value = response.data.activityId;
formRef.value?.setFieldValue('activityId', response.data.activityId);
//send confirmation email
emailConfirmation(response.data.activityId);
} else {
throw new Error('Failed to retrieve correct draft data');
}
Expand All @@ -235,6 +239,24 @@ async function onSubmit(data: any) {
}
}
async function emailConfirmation(activityId: string) {
const configCC = getConfig.value.ches?.cc;
const body = confirmationTemplate({
'{{ contactName }}': formRef.value?.values.applicant.firstName,
'{{ activityId }}': activityId
});
let applicantEmail = formRef.value?.values.applicant.email;
let emailData = {
from: configCC,
to: [applicantEmail],
cc: configCC,
subject: 'Confirmation of Submission', // eslint-disable-line quotes
bodyType: 'text',
body: body
};
await submissionService.emailConfirmation(emailData);
}
async function onRegisteredNameInput(e: AutoCompleteCompleteEvent) {
if (e?.query?.length >= 2) {
const results = (await externalApiService.searchOrgBook(e.query))?.data?.results ?? [];
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/services/submissionService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { appAxios } from './interceptors';
import { delimitEmails } from '@/utils/utils';

import type { Email } from '@/types';

export default {
/**
Expand Down Expand Up @@ -63,5 +66,20 @@ export default {
*/
updateSubmission(submissionId: string, data: any) {
return appAxios().put(`submission/${submissionId}`, data);
},

/**
* @function send
* Send an email with the submission confirmation data
* @returns {Promise} An axios response
*/
emailConfirmation(emailData: Email) {
if (emailData.to && !Array.isArray(emailData.to)) {
emailData.to = delimitEmails(emailData.to);
}
if (emailData.cc && !Array.isArray(emailData.cc)) {
emailData.cc = delimitEmails(emailData.cc);
}
return appAxios().put('submission/emailConfirmation', { emailData });
}
};
10 changes: 10 additions & 0 deletions frontend/src/utils/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,13 @@ const replacePlaceholders = (baseText: string, replacementConfig: { [key: string
}
return newText;
};

export const confirmationTemplate = (replaceConfig: { [key: string]: string | string[] | undefined }) => {
const baseTemplate =
'Dear {{ contactName }},\n\n' +
'The confirmation ID for your submission is: {{ activityId }}.\n\n' +
'A Housing Navigator will review your submission and contact you. Keep the Confirmation ID for future reference.\n\n' +

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (16.x)

This line has a length of 123. Maximum allowed is 120

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (18.x)

This line has a length of 123. Maximum allowed is 120

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (20.x)

This line has a length of 123. Maximum allowed is 120

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (16.x)

This line has a length of 123. Maximum allowed is 120

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (18.x)

This line has a length of 123. Maximum allowed is 120

Check warning on line 66 in frontend/src/utils/templates.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (Frontend) (20.x)

This line has a length of 123. Maximum allowed is 120
'Regards,\n\n' +
'Permit Connect Navigator Service';
return replacePlaceholders(baseTemplate, replaceConfig);
};

0 comments on commit 53b0da2

Please sign in to comment.