diff --git a/app/src/controllers/chefs.ts b/app/src/controllers/chefs.ts index bb22ac9f..e67a77df 100644 --- a/app/src/controllers/chefs.ts +++ b/app/src/controllers/chefs.ts @@ -6,36 +6,71 @@ import { IdentityProvider } from '../components/constants'; import type { JwtPayload } from 'jsonwebtoken'; import type { NextFunction, Request, Response } from '../interfaces/IExpress'; -import type { ChefsFormConfig, ChefsFormConfigData, ChefsSubmissionFormExport } from '../types'; +import type { ChefsFormConfig, ChefsFormConfigData, ChefsSubmissionForm, ChefsSubmissionFormExport } from '../types'; const controller = { getFormExport: async (req: Request, res: Response, next: NextFunction) => { try { const cfg = config.get('server.chefs.forms') as ChefsFormConfig; - let formData = new Array(); - // Get a JSON export of all form data merged into a single array - await Promise.all( + const exportData: Array> = await Promise.all( Object.values(cfg).map(async (x: ChefsFormConfigData) => { - const data = await chefsService.getFormExport(x.id); - data.forEach((d: ChefsSubmissionFormExport) => (d.form.id = x.id)); - formData = formData.concat(data); + return (await chefsService.getFormExport(x.id)).map((data: ChefsSubmissionFormExport) => { + const financiallySupportedValues = { + financiallySupportedBC: isTruthy(data.isBCHousingSupported), + financiallySupportedIndigenous: isTruthy(data.isIndigenousHousingProviderSupported), + financiallySupportedNonProfit: isTruthy(data.isNonProfitSupported), + financiallySupportedHousingCoop: isTruthy(data.isHousingCooperativeSupported) + }; + + return { + formId: x.id, + submissionId: data.form.submissionId, + confirmationId: data.form.confirmationId, + contactEmail: data.contactEmail, + contactPhoneNumber: data.contactPhoneNumber, + contactName: `${data.contactFirstName} ${data.contactLastName}`, + financiallySupported: Object.values(financiallySupportedValues).includes(true), + ...financiallySupportedValues, + intakeStatus: data.form.status, + latitude: data.latitude, + longitude: data.longitude, + naturalDisaster: data.naturalDisasterInd, + projectName: data.companyNameRegistered, + queuePriority: data.queuePriority, + singleFamilyUnits: data.singleFamilyUnits ?? data.multiFamilyUnits, + streetAddress: data.streetAddress, + submittedAt: data.form.createdAt, + submittedBy: data.form.username + }; + }); }) - ); + ).then((x) => x.filter((y) => y.length).flat()); + + // Get a list of all submission IDs + const result = await chefsService.searchSubmissions({ + submissionId: exportData.map((x) => x.submissionId as string) + }); + + // Overwrite export data with application data where possible + const mergedExportData = exportData.map((x: Partial) => ({ + ...x, + ...result.find((y) => y?.submissionId === x.submissionId) + })); /* * Filter Data source * IDIR users should be able to see all submissions * BCeID/Business should only see their own submissions */ - const filterData = (data: Array) => { + const filterData = (data: Array>) => { const tokenPayload = req.currentUser?.tokenPayload as JwtPayload; const filterToUser = tokenPayload && tokenPayload.identity_provider !== IdentityProvider.IDIR; if (isTruthy(filterToUser)) { return data.filter( - (x: { form: { username: string } }) => - x.form.username.toUpperCase().substring(0, x.form.username.indexOf('@')) === + (x: Partial) => + x.submittedBy?.toUpperCase().substring(0, x.submittedBy.indexOf('@')) === (req.currentUser?.tokenPayload as JwtPayload).bceid_username.toUpperCase() ); } else { @@ -43,7 +78,7 @@ const controller = { } }; - res.status(200).send(filterData(formData)); + res.status(200).send(filterData(mergedExportData)); } catch (e: unknown) { next(e); } diff --git a/app/src/services/chefs.ts b/app/src/services/chefs.ts index 9aef592a..711fe6aa 100644 --- a/app/src/services/chefs.ts +++ b/app/src/services/chefs.ts @@ -7,7 +7,7 @@ import prisma from '../db/dataConnection'; import { submission } from '../db/models'; import type { AxiosInstance, AxiosRequestConfig } from 'axios'; -import type { ChefsSubmissionForm } from '../types'; +import type { ChefsSubmissionForm, SubmissionSearchParameters } from '../types'; /** * @function chefsAxios @@ -105,6 +105,29 @@ const service = { } }, + /** + * @function searchSubmissions + * Search and filter for specific submission + * @param {string[]} [params.submissionId] Optional array of uuids representing the submission ID + * @returns {Promise} The result of running the findMany operation + */ + searchSubmissions: async (params: SubmissionSearchParameters) => { + const result = await prisma.submission.findMany({ + where: { + OR: [ + { + submissionId: { in: params.submissionId } + } + ] + }, + include: { + user: true + } + }); + + return result.map((x) => submission.fromDBModel(x)); + }, + updateSubmission: async (data: ChefsSubmissionForm) => { try { await prisma.submission.update({ diff --git a/app/src/services/user.ts b/app/src/services/user.ts index 8ff188a2..370436db 100644 --- a/app/src/services/user.ts +++ b/app/src/services/user.ts @@ -230,10 +230,10 @@ const service = { where: { OR: [ { - userId: { in: params.userId, mode: 'insensitive' } + userId: { in: params.userId } }, { - identityId: { in: params.identityId, mode: 'insensitive' } + identityId: { in: params.identityId } }, { idp: { in: params.idp, mode: 'insensitive' } diff --git a/app/src/types/ChefsSubmissionFormExport.ts b/app/src/types/ChefsSubmissionFormExport.ts index 8e2368e2..a9a48ec5 100644 --- a/app/src/types/ChefsSubmissionFormExport.ts +++ b/app/src/types/ChefsSubmissionFormExport.ts @@ -13,5 +13,27 @@ export type ChefsSubmissionFormExport = { assignee: string; assigneedEmail: string; }; - // Additional form field data will be added + + submissionId: string; + confirmationId: string; + contactEmail: string; + contactPhoneNumber: string; + contactFirstName: string; + contactLastName: string; + financiallySupported: boolean; + intakeStatus: string; + isBCHousingSupported: boolean; + isIndigenousHousingProviderSupported: boolean; + isNonProfitSupported: boolean; + isHousingCooperativeSupported: boolean; + latitude: number; + longitude: number; + naturalDisasterInd: boolean; + companyNameRegistered: string; + queuePriority: number; + singleFamilyUnits: string; + multiFamilyUnits: string; + streetAddress: string; + createdAt: string; + createdBy: string; }; diff --git a/app/src/types/SubmissionSearchParameters.ts b/app/src/types/SubmissionSearchParameters.ts new file mode 100644 index 00000000..6759c53d --- /dev/null +++ b/app/src/types/SubmissionSearchParameters.ts @@ -0,0 +1,3 @@ +export type SubmissionSearchParameters = { + submissionId?: Array; +}; diff --git a/app/src/types/index.ts b/app/src/types/index.ts index 5a317bab..89895d22 100644 --- a/app/src/types/index.ts +++ b/app/src/types/index.ts @@ -3,6 +3,7 @@ export type { ChefsSubmissionForm } from './ChefsSubmissionForm'; export type { ChefsSubmissionFormExport } from './ChefsSubmissionFormExport'; export type { CurrentUser } from './CurrentUser'; export type { IdentityProvider } from './IdentityProvider'; +export type { SubmissionSearchParameters } from './SubmissionSearchParameters'; export type { User } from './User'; export type { UserSearchParameters } from './UserSearchParameters'; export type { YRN } from './YRN'; diff --git a/frontend/src/types/ChefsSubmissionForm.ts b/frontend/src/types/ChefsSubmissionForm.ts index 1776c3e1..24e01639 100644 --- a/frontend/src/types/ChefsSubmissionForm.ts +++ b/frontend/src/types/ChefsSubmissionForm.ts @@ -1,6 +1,7 @@ import type { User } from './User'; export type ChefsSubmissionForm = { + formId?: string; submissionId: string; confirmationId: string; submittedAt: string; diff --git a/frontend/src/views/SubmissionsView.vue b/frontend/src/views/SubmissionsView.vue index 8c60042c..94467e4d 100644 --- a/frontend/src/views/SubmissionsView.vue +++ b/frontend/src/views/SubmissionsView.vue @@ -1,17 +1,19 @@