Skip to content

Commit a3aa743

Browse files
committed
Merge branch 'feat/df-623-payment-2' of https://github.com/DEFRA/forms-engine-plugin into feat/df-623-payment-2
2 parents 7591d88 + 28c5566 commit a3aa743

7 files changed

Lines changed: 45 additions & 10 deletions

File tree

src/server/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export const FORM_PREFIX = ''
33
export const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD'
44
export const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE'
55
export const COMPONENT_STATE_ERROR = 'COMPONENT_STATE_ERROR'
6+
export const PAYMENT_EXPIRED_NOTIFICATION = 'PAYMENT_EXPIRED_NOTIFICATION'

src/server/plugins/engine/components/PaymentField.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ export class PaymentField extends FormComponent {
259259
throw new InvalidComponentStateError(
260260
this,
261261
'Your payment authorisation has expired. Please add your payment details again.',
262-
{ shouldResetState: true }
262+
{ shouldResetState: true, isPaymentExpired: true }
263263
)
264264
}
265265

src/server/plugins/engine/pageControllers/QuestionPageController.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import { type ValidationErrorItem } from 'joi'
1515
import {
1616
COMPONENT_STATE_ERROR,
1717
EXTERNAL_STATE_APPENDAGE,
18-
EXTERNAL_STATE_PAYLOAD
18+
EXTERNAL_STATE_PAYLOAD,
19+
PAYMENT_EXPIRED_NOTIFICATION
1920
} from '~/src/server/constants.js'
2021
import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
2122
import { optionalText } from '~/src/server/plugins/engine/components/constants.js'
@@ -439,6 +440,12 @@ export class QuestionPageController extends PageController {
439440

440441
viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)
441442

443+
const paymentExpiredFlash = request.yar.flash(
444+
PAYMENT_EXPIRED_NOTIFICATION
445+
)
446+
viewModel.showPaymentExpiredNotification =
447+
!Array.isArray(paymentExpiredFlash)
448+
442449
/**
443450
* Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it
444451
*/

src/server/plugins/engine/pageControllers/SummaryPageController.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import {
77
import Boom from '@hapi/boom'
88
import { type RouteOptions } from '@hapi/hapi'
99

10-
import { COMPONENT_STATE_ERROR } from '~/src/server/constants.js'
10+
import {
11+
COMPONENT_STATE_ERROR,
12+
PAYMENT_EXPIRED_NOTIFICATION
13+
} from '~/src/server/constants.js'
1114
import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
1215
import { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'
1316
import { getAnswer } from '~/src/server/plugins/engine/components/helpers/components.js'
@@ -228,6 +231,18 @@ export class SummaryPageController extends QuestionPageController {
228231
)
229232
} catch (error) {
230233
if (error instanceof InvalidComponentStateError) {
234+
if (error.shouldResetState) {
235+
await cacheService.resetComponentStates(
236+
request,
237+
error.getStateKeys()
238+
)
239+
240+
if (error.isPaymentExpired) {
241+
request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION, true, true)
242+
return this.proceed(request, h, error.component.page?.path)
243+
}
244+
}
245+
231246
const govukError = createError(
232247
error.component.name,
233248
error.userMessage
@@ -236,15 +251,9 @@ export class SummaryPageController extends QuestionPageController {
236251
request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)
237252

238253
if (error.shouldResetState) {
239-
// Reset state and redirect to component page (e.g., payment expired)
240-
await cacheService.resetComponentStates(
241-
request,
242-
error.getStateKeys()
243-
)
244254
return this.proceed(request, h, error.component.page?.path)
245255
}
246256

247-
// Stay on CYA page with error (e.g., capture failed, user can retry)
248257
return this.proceed(request, h)
249258
}
250259

src/server/plugins/engine/pageControllers/errors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ export interface InvalidComponentStateErrorOptions {
2424
* @default true
2525
*/
2626
shouldResetState?: boolean
27+
28+
/**
29+
* Whether this error is due to payment expiry.
30+
* When true, an "Important" notification banner will be shown on the payment page.
31+
* @default false
32+
*/
33+
isPaymentExpired?: boolean
2734
}
2835

2936
/**
@@ -38,6 +45,7 @@ export class InvalidComponentStateError extends Error {
3845
public readonly component: FormComponent
3946
public readonly userMessage: string
4047
public readonly shouldResetState: boolean
48+
public readonly isPaymentExpired: boolean
4149

4250
constructor(
4351
component: FormComponent,
@@ -50,6 +58,7 @@ export class InvalidComponentStateError extends Error {
5058
this.component = component
5159
this.userMessage = userMessage
5260
this.shouldResetState = options.shouldResetState ?? true
61+
this.isPaymentExpired = options.isPaymentExpired ?? false
5362
}
5463

5564
getStateKeys() {

src/server/plugins/engine/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ export interface FormPageViewModel extends PageViewModelBase {
334334
hasMissingNotificationEmail?: boolean
335335
allowSaveAndExit: boolean
336336
showSubmitButton?: boolean
337+
showPaymentExpiredNotification?: boolean
337338
}
338339

339340
export interface RepeaterSummaryPageViewModel extends PageViewModelBase {

src/server/plugins/engine/views/index.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% extends baseLayoutPath %}
22

33
{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
4+
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}
45
{% from "partials/components.html" import componentList with context %}
56

67
{% block content %}
@@ -10,7 +11,14 @@
1011
{% include "partials/preview-banner.html" %}
1112
{% endif %}
1213

13-
{% if errors | length %}
14+
{% if showPaymentExpiredNotification %}
15+
{{ govukNotificationBanner({
16+
titleText: "Important",
17+
html: '<h3 class="govuk-notification-banner__heading">Your payment has been cancelled</h3><p class="govuk-body">Your payment details were deleted because the form was inactive for 5 days.</p><p class="govuk-body">Add your payment details again.</p>'
18+
}) }}
19+
{% endif %}
20+
21+
{% if errors | length and not showPaymentExpiredNotification %}
1422
{{ govukErrorSummary({
1523
titleText: "There is a problem",
1624
errorList: checkErrorTemplates(errors)

0 commit comments

Comments
 (0)