@defra/forms-engine-plugin 4.21.2 → 4.23.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.
@@ -287,7 +287,7 @@ export async function submitForm(context, formMetadata, request, summaryViewMode
287
287
  const items = getFormSubmissionData(summaryViewModel.context, summaryViewModel.details, model);
288
288
  try {
289
289
  request.logger.info(logTags, 'Submitting data');
290
- const submitResponse = await submitData(model, items, emailAddress, request.yar.id);
290
+ const submitResponse = await submitData(model, items, emailAddress, request.yar.id, summaryViewModel.context.referenceNumber);
291
291
  if (submitResponse === undefined) {
292
292
  throw Boom.badRequest('Unexpected empty response from submit api');
293
293
  }
@@ -332,7 +332,7 @@ async function finaliseComponents(request, metadata, context, model) {
332
332
  await component.onSubmit(request, metadata, context);
333
333
  }
334
334
  }
335
- function submitData(model, items, retrievalKey, sessionId) {
335
+ function submitData(model, items, retrievalKey, sessionId, referenceNumber) {
336
336
  const {
337
337
  formSubmissionService
338
338
  } = model.services;
@@ -342,6 +342,7 @@ function submitData(model, items, retrievalKey, sessionId) {
342
342
  const payload = {
343
343
  sessionId,
344
344
  retrievalKey,
345
+ referenceNumber,
345
346
  main: buildMainRecords(items),
346
347
  repeaters: buildRepeaterRecords(items)
347
348
  };
@@ -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","summaryLabel","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.summaryLabel,\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","summaryLabel","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 summaryViewModel.context.referenceNumber\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 referenceNumber: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n referenceNumber,\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.summaryLabel,\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/forms-engine-plugin",
3
- "version": "4.21.2",
3
+ "version": "4.23.0",
4
4
  "description": "Defra forms engine",
5
5
  "type": "module",
6
6
  "files": [
@@ -443,7 +443,8 @@ export async function submitForm(
443
443
  model,
444
444
  items,
445
445
  emailAddress,
446
- request.yar.id
446
+ request.yar.id,
447
+ summaryViewModel.context.referenceNumber
447
448
  )
448
449
 
449
450
  if (submitResponse === undefined) {
@@ -521,7 +522,8 @@ function submitData(
521
522
  model: FormModel,
522
523
  items: DetailItem[],
523
524
  retrievalKey: string,
524
- sessionId: string
525
+ sessionId: string,
526
+ referenceNumber: string
525
527
  ) {
526
528
  const { formSubmissionService } = model.services
527
529
  const { submit } = formSubmissionService
@@ -529,6 +531,7 @@ function submitData(
529
531
  const payload: SubmitPayload = {
530
532
  sessionId,
531
533
  retrievalKey,
534
+ referenceNumber,
532
535
  main: buildMainRecords(items),
533
536
  repeaters: buildRepeaterRecords(items)
534
537
  }