@defra/forms-engine-plugin 4.12.0 → 4.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.server/server/plugins/engine/models/FormModel.d.ts +4 -0
- package/.server/server/plugins/engine/models/FormModel.js +14 -1
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +5 -5
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/routes/questions.js +1 -1
- package/.server/server/plugins/engine/routes/questions.js.map +1 -1
- package/.server/server/plugins/engine/views/file-upload.html +2 -1
- package/package.json +1 -1
- package/src/server/plugins/engine/models/FormModel.ts +20 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +13 -6
- package/src/server/plugins/engine/routes/questions.ts +5 -1
- package/src/server/plugins/engine/views/file-upload.html +2 -1
|
@@ -68,4 +68,8 @@ export declare class FormModel {
|
|
|
68
68
|
* @returns
|
|
69
69
|
*/
|
|
70
70
|
getConditionById(conditionId: string): ConditionWrapperV2 | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Checks that only one payment field exists (if any payments fields exist)
|
|
73
|
+
*/
|
|
74
|
+
moreThanOnePaymentQuestion(): boolean;
|
|
71
75
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, ConditionsModel, ControllerPath, ControllerType, SchemaVersion, convertConditionWrapperFromV2, formDefinitionSchema, formDefinitionV2Schema, generateConditionAlias, hasComponents, hasRepeater, isConditionWrapperV2, yesNoListId, yesNoListName } from '@defra/forms-model';
|
|
1
|
+
import { ComponentType, ConditionsModel, ControllerPath, ControllerType, SchemaVersion, convertConditionWrapperFromV2, formDefinitionSchema, formDefinitionV2Schema, generateConditionAlias, hasComponents, hasComponentsEvenIfNoNext, hasRepeater, isConditionWrapperV2, yesNoListId, yesNoListName } from '@defra/forms-model';
|
|
2
2
|
import { add, format } from 'date-fns';
|
|
3
3
|
import { Parser } from 'expr-eval-fork';
|
|
4
4
|
import joi from 'joi';
|
|
@@ -86,6 +86,11 @@ export class FormModel {
|
|
|
86
86
|
this.conditions = {};
|
|
87
87
|
this.services = services;
|
|
88
88
|
this.controllers = controllers;
|
|
89
|
+
|
|
90
|
+
// Assert that there is only one payment question (if any)
|
|
91
|
+
if (this.moreThanOnePaymentQuestion()) {
|
|
92
|
+
throw new Error('Invalid form definition: Only one payment question is allowed per form');
|
|
93
|
+
}
|
|
89
94
|
this.pageDefMap = new Map(def.pages.map(page => [page.path, page]));
|
|
90
95
|
this.listDefMap = new Map(def.lists.map(list => [list.name, list]));
|
|
91
96
|
this.listDefIdMap = new Map(def.lists.filter(list => list.id) // Skip lists without an ID
|
|
@@ -381,6 +386,14 @@ export class FormModel {
|
|
|
381
386
|
getConditionById(conditionId) {
|
|
382
387
|
return this.def.conditions.filter(isConditionWrapperV2).find(condition => condition.id === conditionId);
|
|
383
388
|
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Checks that only one payment field exists (if any payments fields exist)
|
|
392
|
+
*/
|
|
393
|
+
moreThanOnePaymentQuestion() {
|
|
394
|
+
const numOfPaymentFields = this.def.pages.flatMap(page => hasComponentsEvenIfNoNext(page) ? page.components : []).filter(comp => comp.type === ComponentType.PaymentField).length;
|
|
395
|
+
return numOfPaymentFields > 1;
|
|
396
|
+
}
|
|
384
397
|
}
|
|
385
398
|
|
|
386
399
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormModel.js","names":["ComponentType","ConditionsModel","ControllerPath","ControllerType","SchemaVersion","convertConditionWrapperFromV2","formDefinitionSchema","formDefinitionV2Schema","generateConditionAlias","hasComponents","hasRepeater","isConditionWrapperV2","yesNoListId","yesNoListName","add","format","Parser","joi","logger","hasListFormField","todayAsDateOnly","findPage","getError","getPage","setPageTitles","createPage","validationOptions","opts","defaultServices","FormAction","merge","FormModel","engine","schemaVersion","def","lists","sections","name","formId","values","basePath","ordnanceSurveyApiKey","conditions","pages","services","controllers","pageDefMap","listDefMap","listDefIdMap","componentDefMap","componentDefIdMap","pageMap","componentMap","constructor","options","schema","V1","warn","result","validate","abortEarly","error","structuredClone","value","push","id","title","type","items","text","Map","map","page","path","list","filter","flatMap","components","component","forEach","conditionDef","condition","makeCondition","pageDef","some","controller","Status","collection","makeFilteredSchema","relevantPages","object","required","concat","stateSchema","parser","operators","logical","Object","assign","functions","dateForComparison","timePeriod","timeUnit","displayName","expr","toConditionExpression","fn","evaluationState","ctx","toConditionContext","evaluate","context","conditionId","propertyName","V2","defineProperty","get","from","parse","toExpression","getList","nameOrId","find","getSection","section","getFormContext","request","state","errors","query","currentPath","startPath","getStartPath","isForceAccess","relevantState","payload","getFormDataFromState","paths","data","referenceNumber","getReferenceNumber","validateFormPayload","nextPage","initialiseContext","assignEvaluationState","assignRelevantState","pageStateIsInvalid","getNextPath","validateFormState","assignPaths","emptyState","freeze","getContextValueFromState","key","keys","listFields","fields","field","undefined","YesNoField","hasOptionalItems","item","length","fieldStateIsInvalid","validValues","fieldState","getFormValueFromState","isInvalid","isArray","Array","every","includes","href","getComponentById","componentId","getListById","listId","getConditionById","action","getFormParams","Validate","startsWith","External","update","CheckboxesField","formState","getStateFromValidForm","previousPages","relevantPage","model","stripUnknown","errorsState","details","$$__referenceNumber","Error"],"sources":["../../../../../src/server/plugins/engine/models/FormModel.ts"],"sourcesContent":["import {\n ComponentType,\n ConditionsModel,\n ControllerPath,\n ControllerType,\n SchemaVersion,\n convertConditionWrapperFromV2,\n formDefinitionSchema,\n formDefinitionV2Schema,\n generateConditionAlias,\n hasComponents,\n hasRepeater,\n isConditionWrapperV2,\n yesNoListId,\n yesNoListName,\n type ComponentDef,\n type ConditionWrapper,\n type ConditionWrapperV2,\n type ConditionsModelData,\n type DateUnits,\n type Engine,\n type FormDefinition,\n type List,\n type Page,\n type Section\n} from '@defra/forms-model'\nimport { add, format } from 'date-fns'\nimport { Parser, type Value } from 'expr-eval-fork'\nimport joi from 'joi'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport { type ListFormComponent } from '~/src/server/plugins/engine/components/ListFormComponent.js'\nimport {} from '~/src/server/plugins/engine/components/YesNoField.js'\nimport {\n hasListFormField,\n type Component\n} from '~/src/server/plugins/engine/components/helpers/components.js'\nimport { todayAsDateOnly } from '~/src/server/plugins/engine/date-helper.js'\nimport {\n findPage,\n getError,\n getPage,\n setPageTitles\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type ExecutableCondition } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n createPage,\n type PageControllerClass\n} from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport { validationOptions as opts } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormState,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { FormAction } from '~/src/server/routes/types.js'\nimport { merge } from '~/src/server/services/cacheService.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport class FormModel {\n /** The runtime engine that should be used */\n engine?: Engine\n\n schemaVersion: SchemaVersion\n\n /** the entire form JSON as an object */\n def: FormDefinition\n\n lists: FormDefinition['lists']\n sections: FormDefinition['sections'] = []\n name: string\n formId: string\n values: FormDefinition\n basePath: string\n ordnanceSurveyApiKey?: string\n conditions: Partial<Record<string, ExecutableCondition>>\n pages: PageControllerClass[]\n services: Services\n\n controllers?: Record<string, typeof PageController>\n pageDefMap: Map<string, Page>\n\n listDefMap: Map<string, List>\n listDefIdMap: Map<string, List>\n\n componentDefMap: Map<string, ComponentDef>\n componentDefIdMap: Map<string, ComponentDef>\n\n pageMap: Map<string, PageControllerClass>\n componentMap: Map<string, Component>\n\n constructor(\n def: typeof this.def,\n options: {\n basePath: string\n ordnanceSurveyApiKey?: string\n formId?: string\n },\n services: Services = defaultServices,\n controllers?: Record<string, typeof PageController>\n ) {\n let schema = formDefinitionV2Schema\n\n if (!def.schema || def.schema === SchemaVersion.V1) {\n logger.warn(\n `[DEPRECATION NOTICE] Form \"${def.name}\" constructed with legacy V1 schema. See https://defra.github.io/forms-engine-plugin/schemas/form-definition-schema.html.`\n )\n schema = formDefinitionSchema\n }\n\n const result = schema.validate(def, { abortEarly: false })\n\n if (result.error) {\n throw result.error\n }\n\n // Make a clone of the shallow copy returned\n // by joi so as not to change the source data.\n def = structuredClone(result.value)\n\n // Add default lists\n def.lists.push({\n id: def.schema === SchemaVersion.V1 ? yesNoListName : yesNoListId,\n name: '__yesNo',\n title: 'Yes/No',\n type: 'boolean',\n items: [\n {\n id: '02900d42-83d1-4c72-a719-c4e8228952fa',\n text: 'Yes',\n value: true\n },\n {\n id: 'f39000eb-c51b-4019-8f82-bbda0423f04d',\n text: 'No',\n value: false\n }\n ]\n })\n\n // Fix up page titles\n setPageTitles(def)\n\n this.engine = def.engine\n this.schemaVersion = def.schema ?? SchemaVersion.V1\n this.def = def\n this.lists = def.lists\n this.sections = def.sections\n this.name = def.name ?? ''\n this.formId = options.formId ?? ''\n this.values = result.value\n this.basePath = options.basePath\n this.ordnanceSurveyApiKey = options.ordnanceSurveyApiKey\n this.conditions = {}\n this.services = services\n this.controllers = controllers\n\n this.pageDefMap = new Map(def.pages.map((page) => [page.path, page]))\n this.listDefMap = new Map(def.lists.map((list) => [list.name, list]))\n this.listDefIdMap = new Map(\n def.lists\n .filter((list) => list.id) // Skip lists without an ID\n // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style\n .map((list) => [list.id as string, list])\n )\n this.componentDefMap = new Map(\n def.pages\n .filter(hasComponents)\n .flatMap((page) =>\n page.components.map((component) => [component.name, component])\n )\n )\n this.componentDefIdMap = new Map(\n def.pages.filter(hasComponents).flatMap((page) =>\n page.components\n .filter((component) => component.id) // Skip components without an ID\n .map((component) => {\n // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style\n return [component.id as string, component]\n })\n )\n )\n\n def.conditions.forEach((conditionDef) => {\n const condition = this.makeCondition(\n isConditionWrapperV2(conditionDef)\n ? convertConditionWrapperFromV2(conditionDef, this)\n : conditionDef\n )\n this.conditions[condition.name] = condition\n })\n\n this.pages = def.pages.map((pageDef) => createPage(this, pageDef))\n\n if (\n !def.pages.some(\n ({ controller }) =>\n // Check for user-provided status page (optional)\n controller === ControllerType.Status\n )\n ) {\n this.pages.push(\n createPage(this, {\n title: 'Form submitted',\n path: ControllerPath.Status,\n controller: ControllerType.Status\n })\n )\n }\n\n this.pageMap = new Map(this.pages.map((page) => [page.path, page]))\n this.componentMap = new Map(\n this.pages.flatMap((page) =>\n page.collection.components.map((component) => [\n component.name,\n component\n ])\n )\n )\n }\n\n /**\n * build the entire model schema from individual pages/sections and filter out answers\n * for pages which are no longer accessible due to an answer that has been changed\n */\n makeFilteredSchema(relevantPages: PageControllerClass[]) {\n // Build the entire model schema\n // from the individual pages/sections\n let schema = joi.object<FormSubmissionState>().required()\n\n relevantPages.forEach((page) => {\n schema = schema.concat(page.collection.stateSchema)\n })\n\n return schema\n }\n\n /**\n * Instantiates a Condition based on {@link ConditionWrapper}\n * @param condition\n */\n makeCondition(condition: ConditionWrapper): ExecutableCondition {\n const parser = new Parser({\n operators: {\n logical: true\n }\n })\n\n Object.assign(parser.functions, {\n dateForComparison(timePeriod: number, timeUnit: DateUnits) {\n // The time element must be stripped (hence using startOfDay() which has no time element),\n // then formatted as YYYY-MM-DD otherwise we can hit time element and BST issues giving the\n // wrong date to compare against.\n // Do not use .toISOString() to format the date as that introduces BST errors.\n return format(\n add(todayAsDateOnly(), { [timeUnit]: timePeriod }),\n 'yyyy-MM-dd'\n )\n }\n })\n\n const { name, displayName, value } = condition\n const expr = this.toConditionExpression(value, parser)\n\n const fn = (evaluationState: FormState) => {\n const ctx = this.toConditionContext(evaluationState, this.conditions)\n try {\n return expr.evaluate(ctx) as boolean\n } catch {\n return false\n }\n }\n\n return {\n name,\n displayName,\n value,\n expr,\n fn\n }\n }\n\n toConditionContext(\n evaluationState: FormState,\n conditions: Partial<Record<string, ExecutableCondition>>\n ) {\n const context = { ...evaluationState }\n\n for (const conditionId in conditions) {\n const propertyName =\n this.schemaVersion === SchemaVersion.V2\n ? generateConditionAlias(conditionId)\n : conditionId\n\n Object.defineProperty(context, propertyName, {\n get() {\n return conditions[conditionId]?.fn(evaluationState)\n }\n })\n }\n\n return context as Extract<Value, Record<string, Value>>\n }\n\n toConditionExpression(value: ConditionsModelData, parser: Parser) {\n const conditions = ConditionsModel.from(value)\n return parser.parse(conditions.toExpression())\n }\n\n getList(nameOrId: string): List | undefined {\n return this.schemaVersion === SchemaVersion.V1\n ? this.lists.find((list) => list.name === nameOrId)\n : this.lists.find((list) => list.id === nameOrId)\n }\n\n getSection(nameOrId: string): Section | undefined {\n return this.schemaVersion === SchemaVersion.V1\n ? this.sections.find((section) => section.name === nameOrId)\n : this.sections.find((section) => section.id === nameOrId)\n }\n\n /**\n * Form context for the current page\n */\n getFormContext(\n request: FormContextRequest,\n state: FormSubmissionState,\n errors?: FormSubmissionError[]\n ): FormContext {\n const { query } = request\n\n const page = getPage(this, request)\n\n // Determine form paths\n const currentPath = page.path\n const startPath = page.getStartPath()\n\n // Preview URL direct access is allowed\n const isForceAccess = 'force' in query\n\n let context: FormContext = {\n evaluationState: {},\n relevantState: {},\n relevantPages: [],\n payload: page.getFormDataFromState(request, state),\n state,\n paths: [],\n errors,\n isForceAccess,\n data: {},\n pageDefMap: this.pageDefMap,\n listDefMap: this.listDefMap,\n componentDefMap: this.componentDefMap,\n pageMap: this.pageMap,\n componentMap: this.componentMap,\n referenceNumber: getReferenceNumber(state)\n }\n\n // Validate current page\n context = validateFormPayload(request, page, context)\n\n // Find start page\n let nextPage = findPage(this, startPath)\n\n this.initialiseContext(context)\n\n // Walk form pages from start\n while (nextPage) {\n // Add page to context\n context.relevantPages.push(nextPage)\n\n this.assignEvaluationState(context, nextPage)\n\n this.assignRelevantState(context, nextPage)\n\n // Stop at current page\n if (\n this.pageStateIsInvalid(context, nextPage) ||\n nextPage.path === currentPath\n ) {\n break\n }\n\n // Apply conditions to determine next page\n nextPage = findPage(this, nextPage.getNextPath(context))\n }\n\n // Validate form state\n context = validateFormState(request, page, context)\n\n // Add paths for navigation\n this.assignPaths(context)\n\n return context\n }\n\n private initialiseContext(context: FormContext) {\n // Initialise `evaluationState` for all keys using empty state.\n // This is because the current condition evaluation library (eval-expr)\n // will throw if an expression uses a key that is undefined.\n const emptyState = Object.freeze({})\n\n for (const page of this.pages) {\n const { collection, pageDef } = page\n\n if (!hasRepeater(pageDef)) {\n Object.assign(\n context.evaluationState,\n collection.getContextValueFromState(emptyState)\n )\n }\n }\n }\n\n private assignEvaluationState(\n context: FormContext,\n page: PageControllerClass\n ) {\n const { collection, pageDef } = page\n // Skip evaluation state for repeater pages\n\n if (!hasRepeater(pageDef)) {\n Object.assign(\n context.evaluationState,\n collection.getContextValueFromState(context.state)\n )\n }\n }\n\n private assignRelevantState(context: FormContext, page: PageControllerClass) {\n // Copy relevant state by expected keys\n for (const key of page.keys) {\n if (typeof context.state[key] !== 'undefined') {\n context.relevantState[key] = context.state[key]\n }\n }\n }\n\n private pageStateIsInvalid(context: FormContext, page: PageControllerClass) {\n // Get any list-bound fields on the page\n const listFields = page.collection.fields.filter(hasListFormField)\n\n // For each list field that is bound to a list that contains any conditional items,\n // we need to check any answers are still valid. Do this by evaluating the conditions\n // and ensuring any current answers are all included in the set of valid answers\n for (const field of listFields) {\n const list = field.list\n\n // Filter out YesNo as they can't be conditional\n if (list !== undefined && field.type !== ComponentType.YesNoField) {\n const hasOptionalItems =\n list.items.filter((item) => item.condition).length > 0\n\n if (hasOptionalItems) {\n return this.fieldStateIsInvalid(context, field, list)\n }\n }\n }\n }\n\n private fieldStateIsInvalid(\n context: FormContext,\n field: ListFormComponent,\n list: List\n ) {\n const { evaluationState, state } = context\n\n const validValues = list.items\n .filter((item) =>\n item.condition\n ? this.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n .map((item) => item.value)\n\n // Get the field state\n const fieldState = field.getFormValueFromState(state)\n\n if (fieldState !== undefined) {\n let isInvalid = false\n const isArray = Array.isArray(fieldState)\n\n // Check if any saved state value(s) are still valid\n // and return true if any are invalid\n if (isArray) {\n isInvalid = !fieldState.every((item) => validValues.includes(item))\n } else {\n isInvalid = !validValues.includes(fieldState)\n }\n\n if (isInvalid) {\n context.errors ??= []\n\n const text =\n 'Options are different because you changed a previous answer'\n\n context.errors.push({\n text,\n name: field.name,\n href: `#${field.name}`,\n path: [`#${field.name}`]\n })\n }\n\n return isInvalid\n }\n }\n\n private assignPaths(context: FormContext) {\n for (const { keys, path } of context.relevantPages) {\n context.paths.push(path)\n\n // Stop at page with errors\n if (\n context.errors?.some(({ name, path }) => {\n return keys.includes(name) || keys.some((key) => path.includes(key))\n })\n ) {\n break\n }\n }\n }\n\n getComponentById(componentId: string): ComponentDef | undefined {\n return this.componentDefIdMap.get(componentId)\n }\n\n getListById(listId: string): List | undefined {\n return this.listDefIdMap.get(listId)\n }\n\n /**\n * Returns a condition by its ID. O(n) lookup time.\n * @param conditionId\n * @returns\n */\n getConditionById(conditionId: string): ConditionWrapperV2 | undefined {\n return this.def.conditions\n .filter(isConditionWrapperV2)\n .find((condition) => condition.id === conditionId)\n }\n}\n\n/**\n * Validate current page only\n */\nfunction validateFormPayload(\n request: FormContextRequest,\n page: PageControllerClass,\n context: FormContext\n): FormContext {\n const { collection } = page\n const { payload, state } = context\n\n const { action } = page.getFormParams(request)\n\n // Skip validation GET requests or other actions\n if (\n !request.payload ||\n (action &&\n action !== FormAction.Validate &&\n !action.startsWith(FormAction.External))\n ) {\n return context\n }\n\n // For checkbox fields missing in the payload (i.e. unchecked),\n // explicitly set their value to undefined so that any previously\n // stored value is cleared and required field validation is enforced.\n const update = { ...request.payload }\n collection.fields.forEach((field) => {\n if (\n field.type === ComponentType.CheckboxesField &&\n !(field.name in update)\n ) {\n update[field.name] = undefined\n }\n })\n\n const { value, errors } = collection.validate({\n ...payload,\n ...update\n })\n\n // Add sanitised payload (ready to save)\n const formState = page.getStateFromValidForm(request, state, value)\n\n return {\n ...context,\n payload: merge(payload, value),\n state: merge(state, formState),\n errors\n }\n}\n\n/**\n * Validate entire form state\n */\nfunction validateFormState(\n request: FormContextRequest,\n page: PageControllerClass,\n context: FormContext\n): FormContext {\n const { errors = [], relevantPages, relevantState } = context\n\n // Exclude current page\n const previousPages = relevantPages.filter(\n (relevantPage) => relevantPage !== page\n )\n\n // Validate relevant state\n const { error } = page.model\n .makeFilteredSchema(previousPages)\n .validate(relevantState, { ...opts, stripUnknown: true })\n\n // Add relevant state errors\n if (error) {\n const errorsState = error.details.map(getError)\n return { ...context, errors: errors.concat(errorsState) }\n }\n\n return context\n}\n\nfunction getReferenceNumber(state: FormSubmissionState): string {\n if (\n !state.$$__referenceNumber ||\n typeof state.$$__referenceNumber !== 'string'\n ) {\n throw Error('Reference number not found in form state')\n }\n\n return state.$$__referenceNumber\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FormModel.js","names":["ComponentType","ConditionsModel","ControllerPath","ControllerType","SchemaVersion","convertConditionWrapperFromV2","formDefinitionSchema","formDefinitionV2Schema","generateConditionAlias","hasComponents","hasComponentsEvenIfNoNext","hasRepeater","isConditionWrapperV2","yesNoListId","yesNoListName","add","format","Parser","joi","logger","hasListFormField","todayAsDateOnly","findPage","getError","getPage","setPageTitles","createPage","validationOptions","opts","defaultServices","FormAction","merge","FormModel","engine","schemaVersion","def","lists","sections","name","formId","values","basePath","ordnanceSurveyApiKey","conditions","pages","services","controllers","pageDefMap","listDefMap","listDefIdMap","componentDefMap","componentDefIdMap","pageMap","componentMap","constructor","options","schema","V1","warn","result","validate","abortEarly","error","structuredClone","value","push","id","title","type","items","text","moreThanOnePaymentQuestion","Error","Map","map","page","path","list","filter","flatMap","components","component","forEach","conditionDef","condition","makeCondition","pageDef","some","controller","Status","collection","makeFilteredSchema","relevantPages","object","required","concat","stateSchema","parser","operators","logical","Object","assign","functions","dateForComparison","timePeriod","timeUnit","displayName","expr","toConditionExpression","fn","evaluationState","ctx","toConditionContext","evaluate","context","conditionId","propertyName","V2","defineProperty","get","from","parse","toExpression","getList","nameOrId","find","getSection","section","getFormContext","request","state","errors","query","currentPath","startPath","getStartPath","isForceAccess","relevantState","payload","getFormDataFromState","paths","data","referenceNumber","getReferenceNumber","validateFormPayload","nextPage","initialiseContext","assignEvaluationState","assignRelevantState","pageStateIsInvalid","getNextPath","validateFormState","assignPaths","emptyState","freeze","getContextValueFromState","key","keys","listFields","fields","field","undefined","YesNoField","hasOptionalItems","item","length","fieldStateIsInvalid","validValues","fieldState","getFormValueFromState","isInvalid","isArray","Array","every","includes","href","getComponentById","componentId","getListById","listId","getConditionById","numOfPaymentFields","comp","PaymentField","action","getFormParams","Validate","startsWith","External","update","CheckboxesField","formState","getStateFromValidForm","previousPages","relevantPage","model","stripUnknown","errorsState","details","$$__referenceNumber"],"sources":["../../../../../src/server/plugins/engine/models/FormModel.ts"],"sourcesContent":["import {\n ComponentType,\n ConditionsModel,\n ControllerPath,\n ControllerType,\n SchemaVersion,\n convertConditionWrapperFromV2,\n formDefinitionSchema,\n formDefinitionV2Schema,\n generateConditionAlias,\n hasComponents,\n hasComponentsEvenIfNoNext,\n hasRepeater,\n isConditionWrapperV2,\n yesNoListId,\n yesNoListName,\n type ComponentDef,\n type ConditionWrapper,\n type ConditionWrapperV2,\n type ConditionsModelData,\n type DateUnits,\n type Engine,\n type FormDefinition,\n type List,\n type Page,\n type Section\n} from '@defra/forms-model'\nimport { add, format } from 'date-fns'\nimport { Parser, type Value } from 'expr-eval-fork'\nimport joi from 'joi'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport { type ListFormComponent } from '~/src/server/plugins/engine/components/ListFormComponent.js'\nimport {} from '~/src/server/plugins/engine/components/YesNoField.js'\nimport {\n hasListFormField,\n type Component\n} from '~/src/server/plugins/engine/components/helpers/components.js'\nimport { todayAsDateOnly } from '~/src/server/plugins/engine/date-helper.js'\nimport {\n findPage,\n getError,\n getPage,\n setPageTitles\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type ExecutableCondition } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n createPage,\n type PageControllerClass\n} from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport { validationOptions as opts } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormState,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { FormAction } from '~/src/server/routes/types.js'\nimport { merge } from '~/src/server/services/cacheService.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport class FormModel {\n /** The runtime engine that should be used */\n engine?: Engine\n\n schemaVersion: SchemaVersion\n\n /** the entire form JSON as an object */\n def: FormDefinition\n\n lists: FormDefinition['lists']\n sections: FormDefinition['sections'] = []\n name: string\n formId: string\n values: FormDefinition\n basePath: string\n ordnanceSurveyApiKey?: string\n conditions: Partial<Record<string, ExecutableCondition>>\n pages: PageControllerClass[]\n services: Services\n\n controllers?: Record<string, typeof PageController>\n pageDefMap: Map<string, Page>\n\n listDefMap: Map<string, List>\n listDefIdMap: Map<string, List>\n\n componentDefMap: Map<string, ComponentDef>\n componentDefIdMap: Map<string, ComponentDef>\n\n pageMap: Map<string, PageControllerClass>\n componentMap: Map<string, Component>\n\n constructor(\n def: typeof this.def,\n options: {\n basePath: string\n ordnanceSurveyApiKey?: string\n formId?: string\n },\n services: Services = defaultServices,\n controllers?: Record<string, typeof PageController>\n ) {\n let schema = formDefinitionV2Schema\n\n if (!def.schema || def.schema === SchemaVersion.V1) {\n logger.warn(\n `[DEPRECATION NOTICE] Form \"${def.name}\" constructed with legacy V1 schema. See https://defra.github.io/forms-engine-plugin/schemas/form-definition-schema.html.`\n )\n schema = formDefinitionSchema\n }\n\n const result = schema.validate(def, { abortEarly: false })\n\n if (result.error) {\n throw result.error\n }\n\n // Make a clone of the shallow copy returned\n // by joi so as not to change the source data.\n def = structuredClone(result.value)\n\n // Add default lists\n def.lists.push({\n id: def.schema === SchemaVersion.V1 ? yesNoListName : yesNoListId,\n name: '__yesNo',\n title: 'Yes/No',\n type: 'boolean',\n items: [\n {\n id: '02900d42-83d1-4c72-a719-c4e8228952fa',\n text: 'Yes',\n value: true\n },\n {\n id: 'f39000eb-c51b-4019-8f82-bbda0423f04d',\n text: 'No',\n value: false\n }\n ]\n })\n\n // Fix up page titles\n setPageTitles(def)\n\n this.engine = def.engine\n this.schemaVersion = def.schema ?? SchemaVersion.V1\n this.def = def\n this.lists = def.lists\n this.sections = def.sections\n this.name = def.name ?? ''\n this.formId = options.formId ?? ''\n this.values = result.value\n this.basePath = options.basePath\n this.ordnanceSurveyApiKey = options.ordnanceSurveyApiKey\n this.conditions = {}\n this.services = services\n this.controllers = controllers\n\n // Assert that there is only one payment question (if any)\n if (this.moreThanOnePaymentQuestion()) {\n throw new Error(\n 'Invalid form definition: Only one payment question is allowed per form'\n )\n }\n\n this.pageDefMap = new Map(def.pages.map((page) => [page.path, page]))\n this.listDefMap = new Map(def.lists.map((list) => [list.name, list]))\n this.listDefIdMap = new Map(\n def.lists\n .filter((list) => list.id) // Skip lists without an ID\n // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style\n .map((list) => [list.id as string, list])\n )\n this.componentDefMap = new Map(\n def.pages\n .filter(hasComponents)\n .flatMap((page) =>\n page.components.map((component) => [component.name, component])\n )\n )\n this.componentDefIdMap = new Map(\n def.pages.filter(hasComponents).flatMap((page) =>\n page.components\n .filter((component) => component.id) // Skip components without an ID\n .map((component) => {\n // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style\n return [component.id as string, component]\n })\n )\n )\n\n def.conditions.forEach((conditionDef) => {\n const condition = this.makeCondition(\n isConditionWrapperV2(conditionDef)\n ? convertConditionWrapperFromV2(conditionDef, this)\n : conditionDef\n )\n this.conditions[condition.name] = condition\n })\n\n this.pages = def.pages.map((pageDef) => createPage(this, pageDef))\n\n if (\n !def.pages.some(\n ({ controller }) =>\n // Check for user-provided status page (optional)\n controller === ControllerType.Status\n )\n ) {\n this.pages.push(\n createPage(this, {\n title: 'Form submitted',\n path: ControllerPath.Status,\n controller: ControllerType.Status\n })\n )\n }\n\n this.pageMap = new Map(this.pages.map((page) => [page.path, page]))\n this.componentMap = new Map(\n this.pages.flatMap((page) =>\n page.collection.components.map((component) => [\n component.name,\n component\n ])\n )\n )\n }\n\n /**\n * build the entire model schema from individual pages/sections and filter out answers\n * for pages which are no longer accessible due to an answer that has been changed\n */\n makeFilteredSchema(relevantPages: PageControllerClass[]) {\n // Build the entire model schema\n // from the individual pages/sections\n let schema = joi.object<FormSubmissionState>().required()\n\n relevantPages.forEach((page) => {\n schema = schema.concat(page.collection.stateSchema)\n })\n\n return schema\n }\n\n /**\n * Instantiates a Condition based on {@link ConditionWrapper}\n * @param condition\n */\n makeCondition(condition: ConditionWrapper): ExecutableCondition {\n const parser = new Parser({\n operators: {\n logical: true\n }\n })\n\n Object.assign(parser.functions, {\n dateForComparison(timePeriod: number, timeUnit: DateUnits) {\n // The time element must be stripped (hence using startOfDay() which has no time element),\n // then formatted as YYYY-MM-DD otherwise we can hit time element and BST issues giving the\n // wrong date to compare against.\n // Do not use .toISOString() to format the date as that introduces BST errors.\n return format(\n add(todayAsDateOnly(), { [timeUnit]: timePeriod }),\n 'yyyy-MM-dd'\n )\n }\n })\n\n const { name, displayName, value } = condition\n const expr = this.toConditionExpression(value, parser)\n\n const fn = (evaluationState: FormState) => {\n const ctx = this.toConditionContext(evaluationState, this.conditions)\n try {\n return expr.evaluate(ctx) as boolean\n } catch {\n return false\n }\n }\n\n return {\n name,\n displayName,\n value,\n expr,\n fn\n }\n }\n\n toConditionContext(\n evaluationState: FormState,\n conditions: Partial<Record<string, ExecutableCondition>>\n ) {\n const context = { ...evaluationState }\n\n for (const conditionId in conditions) {\n const propertyName =\n this.schemaVersion === SchemaVersion.V2\n ? generateConditionAlias(conditionId)\n : conditionId\n\n Object.defineProperty(context, propertyName, {\n get() {\n return conditions[conditionId]?.fn(evaluationState)\n }\n })\n }\n\n return context as Extract<Value, Record<string, Value>>\n }\n\n toConditionExpression(value: ConditionsModelData, parser: Parser) {\n const conditions = ConditionsModel.from(value)\n return parser.parse(conditions.toExpression())\n }\n\n getList(nameOrId: string): List | undefined {\n return this.schemaVersion === SchemaVersion.V1\n ? this.lists.find((list) => list.name === nameOrId)\n : this.lists.find((list) => list.id === nameOrId)\n }\n\n getSection(nameOrId: string): Section | undefined {\n return this.schemaVersion === SchemaVersion.V1\n ? this.sections.find((section) => section.name === nameOrId)\n : this.sections.find((section) => section.id === nameOrId)\n }\n\n /**\n * Form context for the current page\n */\n getFormContext(\n request: FormContextRequest,\n state: FormSubmissionState,\n errors?: FormSubmissionError[]\n ): FormContext {\n const { query } = request\n\n const page = getPage(this, request)\n\n // Determine form paths\n const currentPath = page.path\n const startPath = page.getStartPath()\n\n // Preview URL direct access is allowed\n const isForceAccess = 'force' in query\n\n let context: FormContext = {\n evaluationState: {},\n relevantState: {},\n relevantPages: [],\n payload: page.getFormDataFromState(request, state),\n state,\n paths: [],\n errors,\n isForceAccess,\n data: {},\n pageDefMap: this.pageDefMap,\n listDefMap: this.listDefMap,\n componentDefMap: this.componentDefMap,\n pageMap: this.pageMap,\n componentMap: this.componentMap,\n referenceNumber: getReferenceNumber(state)\n }\n\n // Validate current page\n context = validateFormPayload(request, page, context)\n\n // Find start page\n let nextPage = findPage(this, startPath)\n\n this.initialiseContext(context)\n\n // Walk form pages from start\n while (nextPage) {\n // Add page to context\n context.relevantPages.push(nextPage)\n\n this.assignEvaluationState(context, nextPage)\n\n this.assignRelevantState(context, nextPage)\n\n // Stop at current page\n if (\n this.pageStateIsInvalid(context, nextPage) ||\n nextPage.path === currentPath\n ) {\n break\n }\n\n // Apply conditions to determine next page\n nextPage = findPage(this, nextPage.getNextPath(context))\n }\n\n // Validate form state\n context = validateFormState(request, page, context)\n\n // Add paths for navigation\n this.assignPaths(context)\n\n return context\n }\n\n private initialiseContext(context: FormContext) {\n // Initialise `evaluationState` for all keys using empty state.\n // This is because the current condition evaluation library (eval-expr)\n // will throw if an expression uses a key that is undefined.\n const emptyState = Object.freeze({})\n\n for (const page of this.pages) {\n const { collection, pageDef } = page\n\n if (!hasRepeater(pageDef)) {\n Object.assign(\n context.evaluationState,\n collection.getContextValueFromState(emptyState)\n )\n }\n }\n }\n\n private assignEvaluationState(\n context: FormContext,\n page: PageControllerClass\n ) {\n const { collection, pageDef } = page\n // Skip evaluation state for repeater pages\n\n if (!hasRepeater(pageDef)) {\n Object.assign(\n context.evaluationState,\n collection.getContextValueFromState(context.state)\n )\n }\n }\n\n private assignRelevantState(context: FormContext, page: PageControllerClass) {\n // Copy relevant state by expected keys\n for (const key of page.keys) {\n if (typeof context.state[key] !== 'undefined') {\n context.relevantState[key] = context.state[key]\n }\n }\n }\n\n private pageStateIsInvalid(context: FormContext, page: PageControllerClass) {\n // Get any list-bound fields on the page\n const listFields = page.collection.fields.filter(hasListFormField)\n\n // For each list field that is bound to a list that contains any conditional items,\n // we need to check any answers are still valid. Do this by evaluating the conditions\n // and ensuring any current answers are all included in the set of valid answers\n for (const field of listFields) {\n const list = field.list\n\n // Filter out YesNo as they can't be conditional\n if (list !== undefined && field.type !== ComponentType.YesNoField) {\n const hasOptionalItems =\n list.items.filter((item) => item.condition).length > 0\n\n if (hasOptionalItems) {\n return this.fieldStateIsInvalid(context, field, list)\n }\n }\n }\n }\n\n private fieldStateIsInvalid(\n context: FormContext,\n field: ListFormComponent,\n list: List\n ) {\n const { evaluationState, state } = context\n\n const validValues = list.items\n .filter((item) =>\n item.condition\n ? this.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n .map((item) => item.value)\n\n // Get the field state\n const fieldState = field.getFormValueFromState(state)\n\n if (fieldState !== undefined) {\n let isInvalid = false\n const isArray = Array.isArray(fieldState)\n\n // Check if any saved state value(s) are still valid\n // and return true if any are invalid\n if (isArray) {\n isInvalid = !fieldState.every((item) => validValues.includes(item))\n } else {\n isInvalid = !validValues.includes(fieldState)\n }\n\n if (isInvalid) {\n context.errors ??= []\n\n const text =\n 'Options are different because you changed a previous answer'\n\n context.errors.push({\n text,\n name: field.name,\n href: `#${field.name}`,\n path: [`#${field.name}`]\n })\n }\n\n return isInvalid\n }\n }\n\n private assignPaths(context: FormContext) {\n for (const { keys, path } of context.relevantPages) {\n context.paths.push(path)\n\n // Stop at page with errors\n if (\n context.errors?.some(({ name, path }) => {\n return keys.includes(name) || keys.some((key) => path.includes(key))\n })\n ) {\n break\n }\n }\n }\n\n getComponentById(componentId: string): ComponentDef | undefined {\n return this.componentDefIdMap.get(componentId)\n }\n\n getListById(listId: string): List | undefined {\n return this.listDefIdMap.get(listId)\n }\n\n /**\n * Returns a condition by its ID. O(n) lookup time.\n * @param conditionId\n * @returns\n */\n getConditionById(conditionId: string): ConditionWrapperV2 | undefined {\n return this.def.conditions\n .filter(isConditionWrapperV2)\n .find((condition) => condition.id === conditionId)\n }\n\n /**\n * Checks that only one payment field exists (if any payments fields exist)\n */\n moreThanOnePaymentQuestion() {\n const numOfPaymentFields = this.def.pages\n .flatMap((page) =>\n hasComponentsEvenIfNoNext(page) ? page.components : []\n )\n .filter((comp) => comp.type === ComponentType.PaymentField).length\n return numOfPaymentFields > 1\n }\n}\n\n/**\n * Validate current page only\n */\nfunction validateFormPayload(\n request: FormContextRequest,\n page: PageControllerClass,\n context: FormContext\n): FormContext {\n const { collection } = page\n const { payload, state } = context\n\n const { action } = page.getFormParams(request)\n\n // Skip validation GET requests or other actions\n if (\n !request.payload ||\n (action &&\n action !== FormAction.Validate &&\n !action.startsWith(FormAction.External))\n ) {\n return context\n }\n\n // For checkbox fields missing in the payload (i.e. unchecked),\n // explicitly set their value to undefined so that any previously\n // stored value is cleared and required field validation is enforced.\n const update = { ...request.payload }\n collection.fields.forEach((field) => {\n if (\n field.type === ComponentType.CheckboxesField &&\n !(field.name in update)\n ) {\n update[field.name] = undefined\n }\n })\n\n const { value, errors } = collection.validate({\n ...payload,\n ...update\n })\n\n // Add sanitised payload (ready to save)\n const formState = page.getStateFromValidForm(request, state, value)\n\n return {\n ...context,\n payload: merge(payload, value),\n state: merge(state, formState),\n errors\n }\n}\n\n/**\n * Validate entire form state\n */\nfunction validateFormState(\n request: FormContextRequest,\n page: PageControllerClass,\n context: FormContext\n): FormContext {\n const { errors = [], relevantPages, relevantState } = context\n\n // Exclude current page\n const previousPages = relevantPages.filter(\n (relevantPage) => relevantPage !== page\n )\n\n // Validate relevant state\n const { error } = page.model\n .makeFilteredSchema(previousPages)\n .validate(relevantState, { ...opts, stripUnknown: true })\n\n // Add relevant state errors\n if (error) {\n const errorsState = error.details.map(getError)\n return { ...context, errors: errors.concat(errorsState) }\n }\n\n return context\n}\n\nfunction getReferenceNumber(state: FormSubmissionState): string {\n if (\n !state.$$__referenceNumber ||\n typeof state.$$__referenceNumber !== 'string'\n ) {\n throw Error('Reference number not found in form state')\n }\n\n return state.$$__referenceNumber\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -53,4 +53,4 @@ export declare class SummaryPageController extends QuestionPageController {
|
|
|
53
53
|
get postRouteOptions(): RouteOptions<FormRequestPayloadRefs>;
|
|
54
54
|
}
|
|
55
55
|
export declare function submitForm(context: FormContext, formMetadata: FormMetadata, request: FormRequestPayload, summaryViewModel: SummaryViewModel, model: FormModel, emailAddress: string): Promise<void>;
|
|
56
|
-
export declare function getFormSubmissionData(context: FormContext, details: Detail[]): DetailItem[];
|
|
56
|
+
export declare function getFormSubmissionData(context: FormContext, details: Detail[], model: FormModel): DetailItem[];
|
|
@@ -284,7 +284,7 @@ export async function submitForm(context, formMetadata, request, summaryViewMode
|
|
|
284
284
|
const formStatus = checkFormStatus(request.params);
|
|
285
285
|
const logTags = ['submit', 'submissionApi'];
|
|
286
286
|
request.logger.info(logTags, 'Preparing email', formStatus);
|
|
287
|
-
const items = getFormSubmissionData(summaryViewModel.context, summaryViewModel.details);
|
|
287
|
+
const items = getFormSubmissionData(summaryViewModel.context, summaryViewModel.details, model);
|
|
288
288
|
try {
|
|
289
289
|
request.logger.info(logTags, 'Submitting data');
|
|
290
290
|
const submitResponse = await submitData(model, items, emailAddress, request.yar.id);
|
|
@@ -347,7 +347,7 @@ function submitData(model, items, retrievalKey, sessionId) {
|
|
|
347
347
|
};
|
|
348
348
|
return submit(payload);
|
|
349
349
|
}
|
|
350
|
-
export function getFormSubmissionData(context, details) {
|
|
350
|
+
export function getFormSubmissionData(context, details, model) {
|
|
351
351
|
const items = context.relevantPages.map(({
|
|
352
352
|
href
|
|
353
353
|
}) => details.flatMap(({
|
|
@@ -355,7 +355,7 @@ export function getFormSubmissionData(context, details) {
|
|
|
355
355
|
}) => items.filter(({
|
|
356
356
|
page
|
|
357
357
|
}) => page.href === href))).flat();
|
|
358
|
-
const paymentItems = getPaymentFieldItems(context);
|
|
358
|
+
const paymentItems = getPaymentFieldItems(context, model);
|
|
359
359
|
return [...items, ...paymentItems];
|
|
360
360
|
}
|
|
361
361
|
|
|
@@ -363,9 +363,9 @@ export function getFormSubmissionData(context, details) {
|
|
|
363
363
|
* Gets DetailItems for PaymentField components
|
|
364
364
|
* PaymentField is excluded from summaryDetails for UI but needs to be in submission data
|
|
365
365
|
*/
|
|
366
|
-
function getPaymentFieldItems(context) {
|
|
366
|
+
function getPaymentFieldItems(context, model) {
|
|
367
367
|
const items = [];
|
|
368
|
-
for (const page of
|
|
368
|
+
for (const page of model.pages) {
|
|
369
369
|
for (const field of page.collection.fields) {
|
|
370
370
|
if (field instanceof PaymentField) {
|
|
371
371
|
items.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","StatusCodes","COMPONENT_STATE_ERROR","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkEmailAddressForLiveFormSubmission","checkFormStatus","createError","getCacheService","SummaryViewModel","QuestionPageController","InvalidComponentStateError","PaymentErrorTypes","PaymentPreAuthError","PaymentSubmissionError","buildMainRecords","buildRepeaterRecords","DEFAULT_PAYMENT_HELP_URL","formatCurrency","formatPaymentDate","FormAction","SummaryPageController","allowSaveAndExit","findPaymentField","model","pages","flatMap","page","collection","fields","find","field","constructor","pageDef","viewName","components","getSummaryViewModel","request","context","viewModel","query","payload","errors","state","paymentField","resolvedAmount","resolveAmount","options","paymentState","getPaymentStateFromState","amount","paymentDetails","buildPaymentDetails","paymentRequired","preAuth","status","paymentPreAuthorized","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","shouldShowSaveAndExit","server","rows","key","text","value","description","reference","createdAt","push","title","summaryList","makeGetRouteHandler","h","paymentComplete","handleFormSubmit","reconcilePaymentState","hasMissingNotificationEmail","view","cacheService","resetComponentStates","name","makePostRouteHandler","action","SaveAndExit","handleSaveAndExit","params","formsService","services","getFormMetadata","formMetadata","slug","notificationEmail","isPreview","submitForm","error","handleSubmissionError","setConfirmationState","confirmed","formId","referenceNumber","clearState","proceed","getStatusPath","handleInvalidComponentStateError","handlePaymentPreAuthError","handlePaymentSubmissionError","govukError","component","userMessage","yar","flash","getStateKeys","path","shouldResetState","errorType","PaymentExpired","PaymentIncomplete","redirect","getHref","code","SEE_OTHER","redirectPath","undefined","helpUrl","helpLink","helpLinkHtml","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","emailAddress","finaliseComponents","paymentWasCaptured","hasPaymentBeenCaptured","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","id","badRequest","outputService","submit","err","contact","online","url","capture","metadata","allFields","Set","relevantPages","filter","onSubmit","retrievalKey","sessionId","formSubmissionService","main","repeaters","map","href","flat","paymentItems","getPaymentFieldItems","label","getDisplayStringFromState"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type FormMetadata,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { StatusCodes } from 'http-status-codes'\n\nimport {\n COMPONENT_STATE_ERROR,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n createError,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n InvalidComponentStateError,\n PaymentErrorTypes,\n PaymentPreAuthError,\n PaymentSubmissionError\n} from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport {\n buildMainRecords,\n buildRepeaterRecords\n} from '~/src/server/plugins/engine/pageControllers/helpers/submission.js'\nimport {\n type FormConfirmationState,\n type FormContext,\n type FormContextRequest\n} from '~/src/server/plugins/engine/types.js'\nimport {\n DEFAULT_PAYMENT_HELP_URL,\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n allowSaveAndExit = true\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n /**\n * Finds the PaymentField component across all pages in the model.\n * Payment pages are skipped in the normal page walk\n */\n private findPaymentField(): PaymentField | undefined {\n return this.model.pages\n .flatMap((page) => page.collection.fields)\n .find((field): field is PaymentField => field instanceof PaymentField)\n }\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext\n ): SummaryViewModel {\n const viewModel = new SummaryViewModel(request, this, context)\n\n const { query } = request\n const { payload, errors, state } = context\n\n const paymentField = this.findPaymentField()\n\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n state\n )\n const paymentState = paymentField.getPaymentStateFromState(state)\n\n if (paymentState?.amount === resolvedAmount) {\n viewModel.paymentState = paymentState\n viewModel.paymentDetails = this.buildPaymentDetails(\n paymentField,\n paymentState\n )\n }\n\n if (resolvedAmount > 0) {\n viewModel.paymentRequired = true\n }\n if (\n paymentState &&\n paymentState.preAuth?.status === 'success' &&\n paymentState.amount === resolvedAmount\n ) {\n viewModel.paymentPreAuthorized = true\n }\n }\n\n const components = this.collection.getViewModel(payload, errors, query)\n\n viewModel.backLink = this.getBackLink(request, context)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndExit = this.shouldShowSaveAndExit(request.server)\n viewModel.errors = errors\n\n return viewModel\n }\n\n private buildPaymentDetails(\n paymentField: PaymentField,\n paymentState: NonNullable<\n ReturnType<PaymentField['getPaymentStateFromState']>\n >\n ) {\n const rows = [\n {\n key: { text: 'Payment for' },\n value: { text: paymentState.description }\n },\n {\n key: { text: 'Total amount' },\n value: { text: formatCurrency(paymentState.amount) }\n },\n {\n key: { text: 'Reference' },\n value: { text: paymentState.reference }\n }\n ]\n\n if (paymentState.preAuth?.createdAt) {\n rows.push({\n key: { text: 'Date of payment' },\n value: { text: formatPaymentDate(paymentState.preAuth.createdAt) }\n })\n }\n\n return {\n title: { text: 'Payment details' },\n summaryList: { rows }\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewName } = this\n\n // After GOV.UK Pay callback, auto-submit the form instead of\n // showing CYA again. The payment is already pre-authorized.\n if (request.query.paymentComplete === 'true') {\n return this.handleFormSubmit(\n request as unknown as FormRequestPayload,\n context,\n h\n )\n }\n\n await this.reconcilePaymentState(request, context)\n\n const viewModel = this.getSummaryViewModel(request, context)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Checks if the resolved payment amount has changed since pre-auth\n * and invalidates stale payment state if so.\n */\n private async reconcilePaymentState(\n request: FormRequest,\n context: FormContext\n ) {\n const paymentField = this.findPaymentField()\n\n if (!paymentField) {\n return\n }\n\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.state\n )\n const paymentState = paymentField.getPaymentStateFromState(context.state)\n\n if (paymentState && paymentState.amount !== resolvedAmount) {\n const cacheService = getCacheService(request.server)\n await cacheService.resetComponentStates(request, [paymentField.name])\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { action } = request.payload\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n return this.handleFormSubmit(request, context, h)\n }\n }\n\n async handleFormSubmit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const { model } = this\n const { params } = request\n\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const formMetadata = await getFormMetadata(params.slug)\n const { notificationEmail } = formMetadata\n const { isPreview } = checkFormStatus(request.params)\n\n checkEmailAddressForLiveFormSubmission(notificationEmail, isPreview)\n\n if (notificationEmail) {\n const viewModel = this.getSummaryViewModel(request, context)\n\n try {\n await submitForm(\n context,\n formMetadata,\n request,\n viewModel,\n model,\n notificationEmail\n )\n } catch (error) {\n return this.handleSubmissionError(error, request, h)\n }\n }\n\n await cacheService.setConfirmationState(request, {\n confirmed: true,\n formId: context.state.formId,\n referenceNumber: context.referenceNumber\n } as FormConfirmationState)\n\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n\n /**\n * Handles errors during form submission\n */\n private async handleSubmissionError(\n error: unknown,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n if (error instanceof InvalidComponentStateError) {\n return this.handleInvalidComponentStateError(error, request, h)\n }\n\n if (error instanceof PaymentPreAuthError) {\n return this.handlePaymentPreAuthError(error, request, h)\n }\n\n if (error instanceof PaymentSubmissionError) {\n return this.handlePaymentSubmissionError(error, request, h)\n }\n\n throw error\n }\n\n /**\n * Handles InvalidComponentStateError during submission\n */\n private async handleInvalidComponentStateError(\n error: InvalidComponentStateError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n const govukError = createError(error.component.name, error.userMessage)\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n return this.proceed(request, h, error.component.page?.path)\n }\n\n /**\n * Handles PaymentPreAuthError during submission\n */\n private async handlePaymentPreAuthError(\n error: PaymentPreAuthError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n if (error.shouldResetState) {\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n if (error.errorType === PaymentErrorTypes.PaymentExpired) {\n request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION, true, true)\n return this.proceed(request, h, error.component.page?.path)\n }\n }\n\n // Payment page is skipped in the page walk, so proceed() would redirect\n // to an earlier page. For PaymentIncomplete, redirect directly to the\n // payment page using its href.\n if (\n error.errorType === PaymentErrorTypes.PaymentIncomplete &&\n error.component.page\n ) {\n return h\n .redirect(error.component.page.getHref(error.component.page.path))\n .code(StatusCodes.SEE_OTHER)\n }\n\n const govukError = createError(error.component.name, error.userMessage)\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n const redirectPath = error.shouldResetState\n ? error.component.page?.path\n : undefined\n\n return this.proceed(request, h, redirectPath)\n }\n\n /**\n * Handles PaymentSubmissionError during submission\n */\n private handlePaymentSubmissionError(\n error: PaymentSubmissionError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const helpUrl = error.helpLink ?? DEFAULT_PAYMENT_HELP_URL\n const helpLinkHtml = ` or you can <a href=\"${helpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"govuk-link\">contact us (opens in new tab)</a> and quote your reference number to arrange a refund`\n\n const govukError = createError(\n 'submission',\n `There was a problem and your form was not submitted. Try submitting the form again${helpLinkHtml}.`\n )\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n return this.proceed(request, h)\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nexport async function submitForm(\n context: FormContext,\n formMetadata: FormMetadata,\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n emailAddress: string\n) {\n await finaliseComponents(request, formMetadata, context, model)\n\n const paymentWasCaptured = hasPaymentBeenCaptured(context, model)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details\n )\n\n try {\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n await model.services.outputService.submit(\n context,\n request,\n model,\n emailAddress,\n items,\n submitResponse,\n formMetadata\n )\n } catch (err) {\n if (paymentWasCaptured) {\n throw new PaymentSubmissionError(\n context.referenceNumber,\n formMetadata.contact?.online?.url\n )\n }\n throw err\n }\n}\n\n/**\n * Checks if any payment component has been captured\n */\nfunction hasPaymentBeenCaptured(\n context: FormContext,\n model: FormModel\n): boolean {\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n const paymentState = field.getPaymentStateFromState(context.state)\n if (paymentState?.capture?.status === 'success') {\n return true\n }\n }\n }\n }\n return false\n}\n\n/**\n * Finalises any components that need post-processing before form submission. Candidates usually involve\n * those that have external state.\n * Examples include:\n * - file uploads which are 'persisted' before submission\n * - payments which are 'captured' before submission\n */\nasync function finaliseComponents(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext,\n model: FormModel\n) {\n // Get fields from relevant pages (normal components)\n // plus PaymentField from all pages (payment page is skipped in the page walk)\n const allFields = new Set([\n ...context.relevantPages.flatMap((page) => page.collection.fields),\n ...model.pages\n .flatMap((page) => page.collection.fields)\n .filter((field) => field instanceof PaymentField)\n ])\n\n for (const component of allFields) {\n await component.onSubmit(request, metadata, context)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n main: buildMainRecords(items),\n repeaters: buildRepeaterRecords(items)\n }\n\n return submit(payload)\n}\n\nexport function getFormSubmissionData(context: FormContext, details: Detail[]) {\n const items = context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n\n const paymentItems = getPaymentFieldItems(context)\n\n return [...items, ...paymentItems]\n}\n\n/**\n * Gets DetailItems for PaymentField components\n * PaymentField is excluded from summaryDetails for UI but needs to be in submission data\n */\nfunction getPaymentFieldItems(context: FormContext): DetailItemField[] {\n const items: DetailItemField[] = []\n\n for (const page of context.relevantPages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n items.push({\n name: field.name,\n page,\n title: field.title,\n label: field.label,\n field,\n state: context.state,\n href: page.href,\n value: field.getDisplayStringFromState(context.state)\n })\n }\n }\n }\n\n return items\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","StatusCodes","COMPONENT_STATE_ERROR","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkEmailAddressForLiveFormSubmission","checkFormStatus","createError","getCacheService","SummaryViewModel","QuestionPageController","InvalidComponentStateError","PaymentErrorTypes","PaymentPreAuthError","PaymentSubmissionError","buildMainRecords","buildRepeaterRecords","DEFAULT_PAYMENT_HELP_URL","formatCurrency","formatPaymentDate","FormAction","SummaryPageController","allowSaveAndExit","findPaymentField","model","pages","flatMap","page","collection","fields","find","field","constructor","pageDef","viewName","components","getSummaryViewModel","request","context","viewModel","query","payload","errors","state","paymentField","resolvedAmount","resolveAmount","options","paymentState","getPaymentStateFromState","amount","paymentDetails","buildPaymentDetails","paymentRequired","preAuth","status","paymentPreAuthorized","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","shouldShowSaveAndExit","server","rows","key","text","value","description","reference","createdAt","push","title","summaryList","makeGetRouteHandler","h","paymentComplete","handleFormSubmit","reconcilePaymentState","hasMissingNotificationEmail","view","cacheService","resetComponentStates","name","makePostRouteHandler","action","SaveAndExit","handleSaveAndExit","params","formsService","services","getFormMetadata","formMetadata","slug","notificationEmail","isPreview","submitForm","error","handleSubmissionError","setConfirmationState","confirmed","formId","referenceNumber","clearState","proceed","getStatusPath","handleInvalidComponentStateError","handlePaymentPreAuthError","handlePaymentSubmissionError","govukError","component","userMessage","yar","flash","getStateKeys","path","shouldResetState","errorType","PaymentExpired","PaymentIncomplete","redirect","getHref","code","SEE_OTHER","redirectPath","undefined","helpUrl","helpLink","helpLinkHtml","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","emailAddress","finaliseComponents","paymentWasCaptured","hasPaymentBeenCaptured","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","id","badRequest","outputService","submit","err","contact","online","url","capture","metadata","allFields","Set","relevantPages","filter","onSubmit","retrievalKey","sessionId","formSubmissionService","main","repeaters","map","href","flat","paymentItems","getPaymentFieldItems","label","getDisplayStringFromState"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type FormMetadata,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { StatusCodes } from 'http-status-codes'\n\nimport {\n COMPONENT_STATE_ERROR,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n createError,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n InvalidComponentStateError,\n PaymentErrorTypes,\n PaymentPreAuthError,\n PaymentSubmissionError\n} from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport {\n buildMainRecords,\n buildRepeaterRecords\n} from '~/src/server/plugins/engine/pageControllers/helpers/submission.js'\nimport {\n type FormConfirmationState,\n type FormContext,\n type FormContextRequest\n} from '~/src/server/plugins/engine/types.js'\nimport {\n DEFAULT_PAYMENT_HELP_URL,\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n allowSaveAndExit = true\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n /**\n * Finds the PaymentField component across all pages in the model.\n * Payment pages are skipped in the normal page walk\n */\n private findPaymentField(): PaymentField | undefined {\n return this.model.pages\n .flatMap((page) => page.collection.fields)\n .find((field): field is PaymentField => field instanceof PaymentField)\n }\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext\n ): SummaryViewModel {\n const viewModel = new SummaryViewModel(request, this, context)\n\n const { query } = request\n const { payload, errors, state } = context\n\n const paymentField = this.findPaymentField()\n\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n state\n )\n const paymentState = paymentField.getPaymentStateFromState(state)\n\n if (paymentState?.amount === resolvedAmount) {\n viewModel.paymentState = paymentState\n viewModel.paymentDetails = this.buildPaymentDetails(\n paymentField,\n paymentState\n )\n }\n\n if (resolvedAmount > 0) {\n viewModel.paymentRequired = true\n }\n if (\n paymentState &&\n paymentState.preAuth?.status === 'success' &&\n paymentState.amount === resolvedAmount\n ) {\n viewModel.paymentPreAuthorized = true\n }\n }\n\n const components = this.collection.getViewModel(payload, errors, query)\n\n viewModel.backLink = this.getBackLink(request, context)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndExit = this.shouldShowSaveAndExit(request.server)\n viewModel.errors = errors\n\n return viewModel\n }\n\n private buildPaymentDetails(\n paymentField: PaymentField,\n paymentState: NonNullable<\n ReturnType<PaymentField['getPaymentStateFromState']>\n >\n ) {\n const rows = [\n {\n key: { text: 'Payment for' },\n value: { text: paymentState.description }\n },\n {\n key: { text: 'Total amount' },\n value: { text: formatCurrency(paymentState.amount) }\n },\n {\n key: { text: 'Reference' },\n value: { text: paymentState.reference }\n }\n ]\n\n if (paymentState.preAuth?.createdAt) {\n rows.push({\n key: { text: 'Date of payment' },\n value: { text: formatPaymentDate(paymentState.preAuth.createdAt) }\n })\n }\n\n return {\n title: { text: 'Payment details' },\n summaryList: { rows }\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewName } = this\n\n // After GOV.UK Pay callback, auto-submit the form instead of\n // showing CYA again. The payment is already pre-authorized.\n if (request.query.paymentComplete === 'true') {\n return this.handleFormSubmit(\n request as unknown as FormRequestPayload,\n context,\n h\n )\n }\n\n await this.reconcilePaymentState(request, context)\n\n const viewModel = this.getSummaryViewModel(request, context)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Checks if the resolved payment amount has changed since pre-auth\n * and invalidates stale payment state if so.\n */\n private async reconcilePaymentState(\n request: FormRequest,\n context: FormContext\n ) {\n const paymentField = this.findPaymentField()\n\n if (!paymentField) {\n return\n }\n\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.state\n )\n const paymentState = paymentField.getPaymentStateFromState(context.state)\n\n if (paymentState && paymentState.amount !== resolvedAmount) {\n const cacheService = getCacheService(request.server)\n await cacheService.resetComponentStates(request, [paymentField.name])\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { action } = request.payload\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n return this.handleFormSubmit(request, context, h)\n }\n }\n\n async handleFormSubmit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const { model } = this\n const { params } = request\n\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const formMetadata = await getFormMetadata(params.slug)\n const { notificationEmail } = formMetadata\n const { isPreview } = checkFormStatus(request.params)\n\n checkEmailAddressForLiveFormSubmission(notificationEmail, isPreview)\n\n if (notificationEmail) {\n const viewModel = this.getSummaryViewModel(request, context)\n\n try {\n await submitForm(\n context,\n formMetadata,\n request,\n viewModel,\n model,\n notificationEmail\n )\n } catch (error) {\n return this.handleSubmissionError(error, request, h)\n }\n }\n\n await cacheService.setConfirmationState(request, {\n confirmed: true,\n formId: context.state.formId,\n referenceNumber: context.referenceNumber\n } as FormConfirmationState)\n\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n\n /**\n * Handles errors during form submission\n */\n private async handleSubmissionError(\n error: unknown,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n if (error instanceof InvalidComponentStateError) {\n return this.handleInvalidComponentStateError(error, request, h)\n }\n\n if (error instanceof PaymentPreAuthError) {\n return this.handlePaymentPreAuthError(error, request, h)\n }\n\n if (error instanceof PaymentSubmissionError) {\n return this.handlePaymentSubmissionError(error, request, h)\n }\n\n throw error\n }\n\n /**\n * Handles InvalidComponentStateError during submission\n */\n private async handleInvalidComponentStateError(\n error: InvalidComponentStateError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n const govukError = createError(error.component.name, error.userMessage)\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n return this.proceed(request, h, error.component.page?.path)\n }\n\n /**\n * Handles PaymentPreAuthError during submission\n */\n private async handlePaymentPreAuthError(\n error: PaymentPreAuthError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n if (error.shouldResetState) {\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n if (error.errorType === PaymentErrorTypes.PaymentExpired) {\n request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION, true, true)\n return this.proceed(request, h, error.component.page?.path)\n }\n }\n\n // Payment page is skipped in the page walk, so proceed() would redirect\n // to an earlier page. For PaymentIncomplete, redirect directly to the\n // payment page using its href.\n if (\n error.errorType === PaymentErrorTypes.PaymentIncomplete &&\n error.component.page\n ) {\n return h\n .redirect(error.component.page.getHref(error.component.page.path))\n .code(StatusCodes.SEE_OTHER)\n }\n\n const govukError = createError(error.component.name, error.userMessage)\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n const redirectPath = error.shouldResetState\n ? error.component.page?.path\n : undefined\n\n return this.proceed(request, h, redirectPath)\n }\n\n /**\n * Handles PaymentSubmissionError during submission\n */\n private handlePaymentSubmissionError(\n error: PaymentSubmissionError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const helpUrl = error.helpLink ?? DEFAULT_PAYMENT_HELP_URL\n const helpLinkHtml = ` or you can <a href=\"${helpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"govuk-link\">contact us (opens in new tab)</a> and quote your reference number to arrange a refund`\n\n const govukError = createError(\n 'submission',\n `There was a problem and your form was not submitted. Try submitting the form again${helpLinkHtml}.`\n )\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n return this.proceed(request, h)\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nexport async function submitForm(\n context: FormContext,\n formMetadata: FormMetadata,\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n emailAddress: string\n) {\n await finaliseComponents(request, formMetadata, context, model)\n\n const paymentWasCaptured = hasPaymentBeenCaptured(context, model)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details,\n model\n )\n\n try {\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n await model.services.outputService.submit(\n context,\n request,\n model,\n emailAddress,\n items,\n submitResponse,\n formMetadata\n )\n } catch (err) {\n if (paymentWasCaptured) {\n throw new PaymentSubmissionError(\n context.referenceNumber,\n formMetadata.contact?.online?.url\n )\n }\n throw err\n }\n}\n\n/**\n * Checks if any payment component has been captured\n */\nfunction hasPaymentBeenCaptured(\n context: FormContext,\n model: FormModel\n): boolean {\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n const paymentState = field.getPaymentStateFromState(context.state)\n if (paymentState?.capture?.status === 'success') {\n return true\n }\n }\n }\n }\n return false\n}\n\n/**\n * Finalises any components that need post-processing before form submission. Candidates usually involve\n * those that have external state.\n * Examples include:\n * - file uploads which are 'persisted' before submission\n * - payments which are 'captured' before submission\n */\nasync function finaliseComponents(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext,\n model: FormModel\n) {\n // Get fields from relevant pages (normal components)\n // plus PaymentField from all pages (payment page is skipped in the page walk)\n const allFields = new Set([\n ...context.relevantPages.flatMap((page) => page.collection.fields),\n ...model.pages\n .flatMap((page) => page.collection.fields)\n .filter((field) => field instanceof PaymentField)\n ])\n\n for (const component of allFields) {\n await component.onSubmit(request, metadata, context)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n main: buildMainRecords(items),\n repeaters: buildRepeaterRecords(items)\n }\n return submit(payload)\n}\n\nexport function getFormSubmissionData(\n context: FormContext,\n details: Detail[],\n model: FormModel\n) {\n const items = context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n\n const paymentItems = getPaymentFieldItems(context, model)\n\n return [...items, ...paymentItems]\n}\n\n/**\n * Gets DetailItems for PaymentField components\n * PaymentField is excluded from summaryDetails for UI but needs to be in submission data\n */\nfunction getPaymentFieldItems(\n context: FormContext,\n model: FormModel\n): DetailItemField[] {\n const items: DetailItemField[] = []\n\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n items.push({\n name: field.name,\n page,\n title: field.title,\n label: field.label,\n field,\n state: context.state,\n href: page.href,\n value: field.getDisplayStringFromState(context.state)\n })\n }\n }\n }\n\n return items\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -19,7 +19,7 @@ async function handleHttpEvent(request, page, context, event, model, preparePage
|
|
|
19
19
|
// TODO: Update structured data POST payload with when helper
|
|
20
20
|
// is updated to removing the dependency on `SummaryViewModel` etc.
|
|
21
21
|
const viewModel = new SummaryViewModel(request, page, context);
|
|
22
|
-
const items = getFormSubmissionData(viewModel.context, viewModel.details);
|
|
22
|
+
const items = getFormSubmissionData(viewModel.context, viewModel.details, model);
|
|
23
23
|
|
|
24
24
|
// @ts-expect-error - function signature will be refactored in the next iteration of the formatter
|
|
25
25
|
const payload = format(context, items, model, undefined, undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"questions.js","names":["hasFormComponents","slugSchema","Boom","Joi","normalisePath","proceed","redirectPath","SummaryViewModel","format","getFormSubmissionData","dispatchHandler","redirectOrMakeHandler","actionSchema","crumbSchema","itemIdSchema","pathSchema","stateSchema","httpService","handleHttpEvent","request","page","context","event","model","preparePageEventRequestOptions","options","url","viewModel","items","details","payload","undefined","opts","timeout","response","postJson","Object","assign","data","makeGetHandler","onRequest","getHandler","h","params","path","events","app","notFound","onLoad","type","makeGetRouteHandler","makePostHandler","postHandler","query","pageDef","isForceAccess","href","makePostRouteHandler","onSave","isSuccessful","statusCode","isBoom","getRoutes","getRouteOptions","postRouteOptions","method","handler","validate","object","keys","slug","state","itemId","optional","crumb","action","unknown","required"],"sources":["../../../../../src/server/plugins/engine/routes/questions.ts"],"sourcesContent":["import { hasFormComponents, slugSchema, type Event } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport {\n type ResponseObject,\n type RouteOptions,\n type ServerRoute\n} from '@hapi/hapi'\nimport Joi from 'joi'\n\nimport {\n normalisePath,\n proceed,\n redirectPath\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport { format } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { getFormSubmissionData } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport {\n dispatchHandler,\n redirectOrMakeHandler\n} from '~/src/server/plugins/engine/routes/index.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type OnRequestCallback,\n type PreparePageEventRequestOptions\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n itemIdSchema,\n pathSchema,\n stateSchema\n} from '~/src/server/schemas/index.js'\nimport * as httpService from '~/src/server/services/httpService.js'\n\nasync function handleHttpEvent(\n request: AnyFormRequest,\n page: PageControllerClass,\n context: FormContext,\n event: Event,\n model: FormModel,\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n) {\n const { options } = event\n const { url } = options\n\n // TODO: Update structured data POST payload with when helper\n // is updated to removing the dependency on `SummaryViewModel` etc.\n const viewModel = new SummaryViewModel(request, page, context)\n const items = getFormSubmissionData(viewModel.context, viewModel.details)\n\n // @ts-expect-error - function signature will be refactored in the next iteration of the formatter\n const payload = format(context, items, model, undefined, undefined)\n const opts: httpService.RequestOptions = { payload, timeout: 5000 }\n\n if (preparePageEventRequestOptions) {\n preparePageEventRequestOptions(opts, event, page, context)\n }\n\n const { payload: response } = await httpService.postJson(url, opts)\n\n Object.assign(context.data, response)\n}\n\nexport function makeGetHandler(\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n) {\n return function getHandler(request: FormRequest, h: FormResponseToolkit) {\n const { params } = request\n\n if (normalisePath(params.path) === '') {\n return dispatchHandler(request, h)\n }\n\n return redirectOrMakeHandler(\n request,\n h,\n onRequest,\n async (page, context) => {\n // Check for a page onLoad HTTP event and if one exists,\n // call it and assign the response to the context data\n const { events } = page\n const { model } = request.app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n if (events?.onLoad?.type === 'http') {\n await handleHttpEvent(\n request,\n page,\n context,\n events.onLoad,\n model,\n preparePageEventRequestOptions\n )\n }\n\n return page.makeGetRouteHandler()(request, context, h)\n }\n )\n }\n}\n\nexport function makePostHandler(\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n) {\n return function postHandler(\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const { query } = request\n\n return redirectOrMakeHandler(\n request,\n h,\n onRequest,\n async (page, context) => {\n const { pageDef } = page\n const { isForceAccess } = context\n const { model } = request.app\n const { events } = page\n\n // Redirect to GET for preview URL direct access\n if (isForceAccess && !hasFormComponents(pageDef)) {\n return proceed(request, h, redirectPath(page.href, query))\n }\n\n if (!model) {\n throw Boom.notFound(`No model found for /${request.params.path}`)\n }\n\n const response = await page.makePostRouteHandler()(request, context, h)\n\n if (events?.onSave?.type === 'http' && isSuccessful(response)) {\n await handleHttpEvent(\n request,\n page,\n context,\n events.onSave,\n model,\n preparePageEventRequestOptions\n )\n }\n\n return response\n }\n )\n }\n}\n\nfunction isSuccessful(response: ResponseObject): boolean {\n const { statusCode } = response\n\n return !Boom.isBoom(response) && statusCode >= 200 && statusCode < 400\n}\n\nexport function getRoutes(\n getRouteOptions: RouteOptions<FormRequestRefs>,\n postRouteOptions: RouteOptions<FormRequestPayloadRefs>,\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n): (ServerRoute<FormRequestRefs> | ServerRoute<FormRequestPayloadRefs>)[] {\n return [\n {\n method: 'get',\n path: '/{slug}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema\n })\n }\n }\n },\n {\n method: 'get',\n path: '/preview/{state}/{slug}',\n handler: dispatchHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema\n })\n }\n }\n },\n {\n method: 'get',\n path: '/{slug}/{path}/{itemId?}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n },\n {\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n },\n {\n method: 'post',\n path: '/{slug}/{path}/{itemId?}',\n handler: makePostHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n },\n {\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: makePostHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n }\n ]\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"questions.js","names":["hasFormComponents","slugSchema","Boom","Joi","normalisePath","proceed","redirectPath","SummaryViewModel","format","getFormSubmissionData","dispatchHandler","redirectOrMakeHandler","actionSchema","crumbSchema","itemIdSchema","pathSchema","stateSchema","httpService","handleHttpEvent","request","page","context","event","model","preparePageEventRequestOptions","options","url","viewModel","items","details","payload","undefined","opts","timeout","response","postJson","Object","assign","data","makeGetHandler","onRequest","getHandler","h","params","path","events","app","notFound","onLoad","type","makeGetRouteHandler","makePostHandler","postHandler","query","pageDef","isForceAccess","href","makePostRouteHandler","onSave","isSuccessful","statusCode","isBoom","getRoutes","getRouteOptions","postRouteOptions","method","handler","validate","object","keys","slug","state","itemId","optional","crumb","action","unknown","required"],"sources":["../../../../../src/server/plugins/engine/routes/questions.ts"],"sourcesContent":["import { hasFormComponents, slugSchema, type Event } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport {\n type ResponseObject,\n type RouteOptions,\n type ServerRoute\n} from '@hapi/hapi'\nimport Joi from 'joi'\n\nimport {\n normalisePath,\n proceed,\n redirectPath\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport { format } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { getFormSubmissionData } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport {\n dispatchHandler,\n redirectOrMakeHandler\n} from '~/src/server/plugins/engine/routes/index.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type OnRequestCallback,\n type PreparePageEventRequestOptions\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n itemIdSchema,\n pathSchema,\n stateSchema\n} from '~/src/server/schemas/index.js'\nimport * as httpService from '~/src/server/services/httpService.js'\n\nasync function handleHttpEvent(\n request: AnyFormRequest,\n page: PageControllerClass,\n context: FormContext,\n event: Event,\n model: FormModel,\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n) {\n const { options } = event\n const { url } = options\n\n // TODO: Update structured data POST payload with when helper\n // is updated to removing the dependency on `SummaryViewModel` etc.\n const viewModel = new SummaryViewModel(request, page, context)\n const items = getFormSubmissionData(\n viewModel.context,\n viewModel.details,\n model\n )\n\n // @ts-expect-error - function signature will be refactored in the next iteration of the formatter\n const payload = format(context, items, model, undefined, undefined)\n const opts: httpService.RequestOptions = { payload, timeout: 5000 }\n\n if (preparePageEventRequestOptions) {\n preparePageEventRequestOptions(opts, event, page, context)\n }\n\n const { payload: response } = await httpService.postJson(url, opts)\n\n Object.assign(context.data, response)\n}\n\nexport function makeGetHandler(\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n) {\n return function getHandler(request: FormRequest, h: FormResponseToolkit) {\n const { params } = request\n\n if (normalisePath(params.path) === '') {\n return dispatchHandler(request, h)\n }\n\n return redirectOrMakeHandler(\n request,\n h,\n onRequest,\n async (page, context) => {\n // Check for a page onLoad HTTP event and if one exists,\n // call it and assign the response to the context data\n const { events } = page\n const { model } = request.app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n if (events?.onLoad?.type === 'http') {\n await handleHttpEvent(\n request,\n page,\n context,\n events.onLoad,\n model,\n preparePageEventRequestOptions\n )\n }\n\n return page.makeGetRouteHandler()(request, context, h)\n }\n )\n }\n}\n\nexport function makePostHandler(\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n) {\n return function postHandler(\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const { query } = request\n\n return redirectOrMakeHandler(\n request,\n h,\n onRequest,\n async (page, context) => {\n const { pageDef } = page\n const { isForceAccess } = context\n const { model } = request.app\n const { events } = page\n\n // Redirect to GET for preview URL direct access\n if (isForceAccess && !hasFormComponents(pageDef)) {\n return proceed(request, h, redirectPath(page.href, query))\n }\n\n if (!model) {\n throw Boom.notFound(`No model found for /${request.params.path}`)\n }\n\n const response = await page.makePostRouteHandler()(request, context, h)\n\n if (events?.onSave?.type === 'http' && isSuccessful(response)) {\n await handleHttpEvent(\n request,\n page,\n context,\n events.onSave,\n model,\n preparePageEventRequestOptions\n )\n }\n\n return response\n }\n )\n }\n}\n\nfunction isSuccessful(response: ResponseObject): boolean {\n const { statusCode } = response\n\n return !Boom.isBoom(response) && statusCode >= 200 && statusCode < 400\n}\n\nexport function getRoutes(\n getRouteOptions: RouteOptions<FormRequestRefs>,\n postRouteOptions: RouteOptions<FormRequestPayloadRefs>,\n preparePageEventRequestOptions?: PreparePageEventRequestOptions,\n onRequest?: OnRequestCallback\n): (ServerRoute<FormRequestRefs> | ServerRoute<FormRequestPayloadRefs>)[] {\n return [\n {\n method: 'get',\n path: '/{slug}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema\n })\n }\n }\n },\n {\n method: 'get',\n path: '/preview/{state}/{slug}',\n handler: dispatchHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema\n })\n }\n }\n },\n {\n method: 'get',\n path: '/{slug}/{path}/{itemId?}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n },\n {\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: makeGetHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n },\n {\n method: 'post',\n path: '/{slug}/{path}/{itemId?}',\n handler: makePostHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n },\n {\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: makePostHandler(preparePageEventRequestOptions, onRequest),\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n }\n ]\n}\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
formDefinitionV2Schema,
|
|
10
10
|
generateConditionAlias,
|
|
11
11
|
hasComponents,
|
|
12
|
+
hasComponentsEvenIfNoNext,
|
|
12
13
|
hasRepeater,
|
|
13
14
|
isConditionWrapperV2,
|
|
14
15
|
yesNoListId,
|
|
@@ -159,6 +160,13 @@ export class FormModel {
|
|
|
159
160
|
this.services = services
|
|
160
161
|
this.controllers = controllers
|
|
161
162
|
|
|
163
|
+
// Assert that there is only one payment question (if any)
|
|
164
|
+
if (this.moreThanOnePaymentQuestion()) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
'Invalid form definition: Only one payment question is allowed per form'
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
162
170
|
this.pageDefMap = new Map(def.pages.map((page) => [page.path, page]))
|
|
163
171
|
this.listDefMap = new Map(def.lists.map((list) => [list.name, list]))
|
|
164
172
|
this.listDefIdMap = new Map(
|
|
@@ -543,6 +551,18 @@ export class FormModel {
|
|
|
543
551
|
.filter(isConditionWrapperV2)
|
|
544
552
|
.find((condition) => condition.id === conditionId)
|
|
545
553
|
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Checks that only one payment field exists (if any payments fields exist)
|
|
557
|
+
*/
|
|
558
|
+
moreThanOnePaymentQuestion() {
|
|
559
|
+
const numOfPaymentFields = this.def.pages
|
|
560
|
+
.flatMap((page) =>
|
|
561
|
+
hasComponentsEvenIfNoNext(page) ? page.components : []
|
|
562
|
+
)
|
|
563
|
+
.filter((comp) => comp.type === ComponentType.PaymentField).length
|
|
564
|
+
return numOfPaymentFields > 1
|
|
565
|
+
}
|
|
546
566
|
}
|
|
547
567
|
|
|
548
568
|
/**
|
|
@@ -433,7 +433,8 @@ export async function submitForm(
|
|
|
433
433
|
|
|
434
434
|
const items = getFormSubmissionData(
|
|
435
435
|
summaryViewModel.context,
|
|
436
|
-
summaryViewModel.details
|
|
436
|
+
summaryViewModel.details,
|
|
437
|
+
model
|
|
437
438
|
)
|
|
438
439
|
|
|
439
440
|
try {
|
|
@@ -531,11 +532,14 @@ function submitData(
|
|
|
531
532
|
main: buildMainRecords(items),
|
|
532
533
|
repeaters: buildRepeaterRecords(items)
|
|
533
534
|
}
|
|
534
|
-
|
|
535
535
|
return submit(payload)
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
export function getFormSubmissionData(
|
|
538
|
+
export function getFormSubmissionData(
|
|
539
|
+
context: FormContext,
|
|
540
|
+
details: Detail[],
|
|
541
|
+
model: FormModel
|
|
542
|
+
) {
|
|
539
543
|
const items = context.relevantPages
|
|
540
544
|
.map(({ href }) =>
|
|
541
545
|
details.flatMap(({ items }) =>
|
|
@@ -544,7 +548,7 @@ export function getFormSubmissionData(context: FormContext, details: Detail[]) {
|
|
|
544
548
|
)
|
|
545
549
|
.flat()
|
|
546
550
|
|
|
547
|
-
const paymentItems = getPaymentFieldItems(context)
|
|
551
|
+
const paymentItems = getPaymentFieldItems(context, model)
|
|
548
552
|
|
|
549
553
|
return [...items, ...paymentItems]
|
|
550
554
|
}
|
|
@@ -553,10 +557,13 @@ export function getFormSubmissionData(context: FormContext, details: Detail[]) {
|
|
|
553
557
|
* Gets DetailItems for PaymentField components
|
|
554
558
|
* PaymentField is excluded from summaryDetails for UI but needs to be in submission data
|
|
555
559
|
*/
|
|
556
|
-
function getPaymentFieldItems(
|
|
560
|
+
function getPaymentFieldItems(
|
|
561
|
+
context: FormContext,
|
|
562
|
+
model: FormModel
|
|
563
|
+
): DetailItemField[] {
|
|
557
564
|
const items: DetailItemField[] = []
|
|
558
565
|
|
|
559
|
-
for (const page of
|
|
566
|
+
for (const page of model.pages) {
|
|
560
567
|
for (const field of page.collection.fields) {
|
|
561
568
|
if (field instanceof PaymentField) {
|
|
562
569
|
items.push({
|
|
@@ -59,7 +59,11 @@ async function handleHttpEvent(
|
|
|
59
59
|
// TODO: Update structured data POST payload with when helper
|
|
60
60
|
// is updated to removing the dependency on `SummaryViewModel` etc.
|
|
61
61
|
const viewModel = new SummaryViewModel(request, page, context)
|
|
62
|
-
const items = getFormSubmissionData(
|
|
62
|
+
const items = getFormSubmissionData(
|
|
63
|
+
viewModel.context,
|
|
64
|
+
viewModel.details,
|
|
65
|
+
model
|
|
66
|
+
)
|
|
63
67
|
|
|
64
68
|
// @ts-expect-error - function signature will be refactored in the next iteration of the formatter
|
|
65
69
|
const payload = format(context, items, model, undefined, undefined)
|