diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index fe0456e5ff..2b5362bbce 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -13,7 +13,7 @@ "@airbrake/node": "^2.1.8", "@aws-sdk/client-s3": "^3.696.0", "@aws-sdk/s3-request-presigner": "^3.701.0", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#29b4851", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#6c6f308", "@types/isomorphic-fetch": "^0.0.36", "adm-zip": "^0.5.10", "axios": "^1.7.4", diff --git a/api.planx.uk/pnpm-lock.yaml b/api.planx.uk/pnpm-lock.yaml index 88eaf57dac..9efddd776a 100644 --- a/api.planx.uk/pnpm-lock.yaml +++ b/api.planx.uk/pnpm-lock.yaml @@ -21,8 +21,8 @@ dependencies: specifier: ^3.701.0 version: 3.701.0 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#29b4851 - version: github.com/theopensystemslab/planx-core/29b4851 + specifier: git+https://github.com/theopensystemslab/planx-core#6c6f308 + version: github.com/theopensystemslab/planx-core/6c6f308 '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -7306,8 +7306,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/29b4851: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/29b4851} + github.com/theopensystemslab/planx-core/6c6f308: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/6c6f308} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/api.planx.uk/tests/mocks/inviteToPayData.ts b/api.planx.uk/tests/mocks/inviteToPayData.ts index 7b7958794d..31c7fc069a 100644 --- a/api.planx.uk/tests/mocks/inviteToPayData.ts +++ b/api.planx.uk/tests/mocks/inviteToPayData.ts @@ -62,6 +62,16 @@ export const paymentRequestResponse: Partial = { payeeEmail: payee.email, paymentAmount: paymentAmountPence, sessionPreviewData: sessionPreviewData, + feeBreakdown: { + amount: { + payable: 123.45, + calculated: 123.45, + vat: 0, + reduction: 0, + }, + reductions: [], + exemptions: [], + }, }; export const validPaymentRequest = { diff --git a/api.planx.uk/tests/mocks/inviteToPayMocks.ts b/api.planx.uk/tests/mocks/inviteToPayMocks.ts index f3d15c2b20..963a1d07f8 100644 --- a/api.planx.uk/tests/mocks/inviteToPayMocks.ts +++ b/api.planx.uk/tests/mocks/inviteToPayMocks.ts @@ -134,6 +134,16 @@ export const createPaymentRequestQueryMock = { { key: "paidViaInviteToPay", value: true }, { key: "flow", value: validSession.flow.slug }, ], + feeBreakdown: { + amount: { + payable: 123.45, + calculated: 123.45, + vat: 0, + reduction: 0, + }, + reductions: [], + exemptions: [], + }, }, }; diff --git a/e2e/tests/api-driven/package.json b/e2e/tests/api-driven/package.json index 606a64005e..8abcf222a1 100644 --- a/e2e/tests/api-driven/package.json +++ b/e2e/tests/api-driven/package.json @@ -7,7 +7,7 @@ "packageManager": "pnpm@8.6.6", "dependencies": { "@cucumber/cucumber": "^9.3.0", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#29b4851", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#6c6f308", "axios": "^1.7.4", "dotenv": "^16.3.1", "dotenv-expand": "^10.0.0", diff --git a/e2e/tests/api-driven/pnpm-lock.yaml b/e2e/tests/api-driven/pnpm-lock.yaml index e9f30826e1..0d0d014d9c 100644 --- a/e2e/tests/api-driven/pnpm-lock.yaml +++ b/e2e/tests/api-driven/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#29b4851 - version: github.com/theopensystemslab/planx-core/29b4851 + specifier: git+https://github.com/theopensystemslab/planx-core#6c6f308 + version: github.com/theopensystemslab/planx-core/6c6f308 axios: specifier: ^1.7.4 version: 1.7.4 @@ -2810,8 +2810,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/29b4851: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/29b4851} + github.com/theopensystemslab/planx-core/6c6f308: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/6c6f308} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/e2e/tests/ui-driven/package.json b/e2e/tests/ui-driven/package.json index 514b990987..d9f193e968 100644 --- a/e2e/tests/ui-driven/package.json +++ b/e2e/tests/ui-driven/package.json @@ -8,7 +8,7 @@ "postinstall": "./install-dependencies.sh" }, "dependencies": { - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#29b4851", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#6c6f308", "axios": "^1.7.4", "dotenv": "^16.3.1", "eslint": "^8.56.0", diff --git a/e2e/tests/ui-driven/pnpm-lock.yaml b/e2e/tests/ui-driven/pnpm-lock.yaml index 4552b235fd..5b3262a182 100644 --- a/e2e/tests/ui-driven/pnpm-lock.yaml +++ b/e2e/tests/ui-driven/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#29b4851 - version: github.com/theopensystemslab/planx-core/29b4851 + specifier: git+https://github.com/theopensystemslab/planx-core#6c6f308 + version: github.com/theopensystemslab/planx-core/6c6f308 axios: specifier: ^1.7.4 version: 1.7.4 @@ -2599,8 +2599,8 @@ packages: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false - github.com/theopensystemslab/planx-core/29b4851: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/29b4851} + github.com/theopensystemslab/planx-core/6c6f308: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/6c6f308} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/e2e/tests/ui-driven/src/invite-to-pay/helpers.ts b/e2e/tests/ui-driven/src/invite-to-pay/helpers.ts index b7a21b667d..40009b5b90 100644 --- a/e2e/tests/ui-driven/src/invite-to-pay/helpers.ts +++ b/e2e/tests/ui-driven/src/invite-to-pay/helpers.ts @@ -69,6 +69,7 @@ export async function getPaymentRequestBySessionId({ paymentAmount: payment_amount applicantName: applicant_name paidAt: paid_at + feeBreakdown: fee_breakdown } } `, diff --git a/e2e/tests/ui-driven/src/invite-to-pay/mocks.ts b/e2e/tests/ui-driven/src/invite-to-pay/mocks.ts index 0006a617a5..4cbc0a5beb 100644 --- a/e2e/tests/ui-driven/src/invite-to-pay/mocks.ts +++ b/e2e/tests/ui-driven/src/invite-to-pay/mocks.ts @@ -18,6 +18,16 @@ export const mockPaymentRequest: Partial = { }, paymentAmount: 12345, applicantName: "Mr Agent (Agency Ltd)", + feeBreakdown: { + amount: { + calculated: 123.45, + payable: 123.45, + vat: 0, + reduction: 0, + }, + reductions: [], + exemptions: [], + }, }; export const mockSessionData: Omit = { diff --git a/e2e/tests/ui-driven/src/invite-to-pay/nominee.spec.ts b/e2e/tests/ui-driven/src/invite-to-pay/nominee.spec.ts index 97631a2ff1..4904a13d0c 100644 --- a/e2e/tests/ui-driven/src/invite-to-pay/nominee.spec.ts +++ b/e2e/tests/ui-driven/src/invite-to-pay/nominee.spec.ts @@ -60,6 +60,8 @@ test.describe("Nominee journey @regression", async () => { "Add a verandah or deck and changes to internal walls or layout"; await expect(page.getByText(formattedProjectType)).toBeVisible(); + await expect(page.getByText("Fee breakdown")).toBeVisible(); + const payButton = page.getByRole("button", { name: "Pay using GOV.UK Pay", }); diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index d81643d9a0..cac75f510d 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -15,7 +15,7 @@ "@mui/material": "^5.15.10", "@mui/utils": "^5.15.11", "@opensystemslab/map": "1.0.0-alpha.4", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#29b4851", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#6c6f308", "@tiptap/core": "^2.4.0", "@tiptap/extension-bold": "^2.0.3", "@tiptap/extension-bubble-menu": "^2.1.13", diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index c683e55797..4de4064176 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -48,8 +48,8 @@ dependencies: specifier: 1.0.0-alpha.4 version: 1.0.0-alpha.4 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#29b4851 - version: github.com/theopensystemslab/planx-core/29b4851(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#6c6f308 + version: github.com/theopensystemslab/planx-core/6c6f308(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -14466,9 +14466,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/29b4851(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/29b4851} - id: github.com/theopensystemslab/planx-core/29b4851 + github.com/theopensystemslab/planx-core/6c6f308(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/6c6f308} + id: github.com/theopensystemslab/planx-core/6c6f308 name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/FeeBreakdown.tsx b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/FeeBreakdown.tsx index ae545d4098..958f617c9a 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/FeeBreakdown.tsx +++ b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/FeeBreakdown.tsx @@ -7,6 +7,7 @@ import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import Typography from "@mui/material/Typography"; +import type { FeeBreakdown as IFeeBreakdown } from "@opensystemslab/planx-core/types"; import React from "react"; import { FONT_WEIGHT_SEMI_BOLD } from "theme"; @@ -122,8 +123,9 @@ const Total: React.FC<{ amount: number }> = ({ amount }) => ( ); -export const FeeBreakdown: React.FC = () => { - const breakdown = useFeeBreakdown(); +export const FeeBreakdown: React.FC<{ inviteToPayFeeBreakdown?: IFeeBreakdown }> = ({ inviteToPayFeeBreakdown }) => { + const passportFeeBreakdown = useFeeBreakdown(); + const breakdown = passportFeeBreakdown || inviteToPayFeeBreakdown; if (!breakdown) return null; const { amount, reductions, exemptions } = breakdown; @@ -131,7 +133,7 @@ export const FeeBreakdown: React.FC = () => { return ( - Fee breakdown + Fee {DESCRIPTION} diff --git a/editor.planx.uk/src/pages/Pay/MakePayment.tsx b/editor.planx.uk/src/pages/Pay/MakePayment.tsx index f6b686dab3..f5b888d569 100644 --- a/editor.planx.uk/src/pages/Pay/MakePayment.tsx +++ b/editor.planx.uk/src/pages/Pay/MakePayment.tsx @@ -8,8 +8,10 @@ import { type PaymentRequest, PaymentStatus, } from "@opensystemslab/planx-core/types"; +import { FeeBreakdown } from "@planx/components/Pay/Public/FeeBreakdown/FeeBreakdown"; import axios from "axios"; import { format } from "date-fns"; +import { hasFeatureFlag } from "lib/featureFlags"; import { getExpiryDateForPaymentRequest } from "lib/pay"; import { useStore } from "pages/FlowEditor/lib/store"; import React, { useEffect, useState } from "react"; @@ -63,6 +65,7 @@ export default function MakePayment({ govPayPaymentId, paymentAmount, paidAt, + feeBreakdown, }: PaymentRequest) { const { address, rawProjectTypes } = parseSessionPreviewData(sessionPreviewData); @@ -170,14 +173,10 @@ export default function MakePayment({ ); - const PaymentDetails = () => { + const PaymentDetails: React.FC<{ hasFeeBreakdown: boolean}> = ({ hasFeeBreakdown }) => { const projectType = formatRawProjectTypes(rawProjectTypes); const data = [ { term: "Application type", details: flowName }, - { - term: "Fee", - details: formattedPriceWithCurrencySymbol(toDecimal(paymentAmount)), - }, { term: "Property address", details: address, @@ -188,6 +187,13 @@ export default function MakePayment({ }, ]; + if (!hasFeeBreakdown) { + data.splice(1, 0, { + term: "Fee", + details: formattedPriceWithCurrencySymbol(toDecimal(paymentAmount)) + }); + }; + // Handle payments completed before page load if (paidAt) { data.push({ @@ -220,19 +226,26 @@ export default function MakePayment({ ) : ( <>
- + {(currentState === States.Ready || currentState === States.Reset || currentState === States.ReadyToRetry) && !isLoading && ( - + <> + {hasFeatureFlag("FEE_BREAKDOWN") && ( + + + + )} + + )} ); @@ -247,9 +260,8 @@ async function fetchPayment({ govPayPaymentId?: string; }): Promise { if (!govPayPaymentId) return Promise.resolve(null); - const paymentURL = `${ - import.meta.env.VITE_APP_API_URL - }/payment-request/${paymentRequestId}/payment/${govPayPaymentId}`; + const paymentURL = `${import.meta.env.VITE_APP_API_URL + }/payment-request/${paymentRequestId}/payment/${govPayPaymentId}`; const response = await axios.get(paymentURL); return response.data; } @@ -258,11 +270,10 @@ async function fetchPayment({ async function startNewPayment( paymentRequestId: string, ): Promise { - const paymentURL = `${ - import.meta.env.VITE_APP_API_URL - }/payment-request/${paymentRequestId}/pay?returnURL=${encodeURIComponent( - window.location.href, - )}`; + const paymentURL = `${import.meta.env.VITE_APP_API_URL + }/payment-request/${paymentRequestId}/pay?returnURL=${encodeURIComponent( + window.location.href, + )}`; const response = await axios.post(paymentURL); return response.data; } diff --git a/editor.planx.uk/src/routes/pay.tsx b/editor.planx.uk/src/routes/pay.tsx index e01e100de7..6b2ba02e84 100644 --- a/editor.planx.uk/src/routes/pay.tsx +++ b/editor.planx.uk/src/routes/pay.tsx @@ -112,6 +112,7 @@ const fetchPaymentRequest = async (paymentRequestId: string) => { ) { id sessionPreviewData: session_preview_data + feeBreakdown: fee_breakdown createdAt: created_at paymentAmount: payment_amount govPayPaymentId: govpay_payment_id diff --git a/hasura.planx.uk/metadata/tables.yaml b/hasura.planx.uk/metadata/tables.yaml index 3a24978694..fe53e49f90 100644 --- a/hasura.planx.uk/metadata/tables.yaml +++ b/hasura.planx.uk/metadata/tables.yaml @@ -1235,6 +1235,7 @@ columns: - applicant_name - created_at + - fee_breakdown - govpay_metadata - govpay_payment_id - id @@ -1250,6 +1251,7 @@ columns: - applicant_name - created_at + - fee_breakdown - govpay_metadata - govpay_payment_id - id @@ -1265,6 +1267,7 @@ columns: - applicant_name - created_at + - fee_breakdown - govpay_payment_id - id - paid_at @@ -1279,6 +1282,7 @@ columns: - applicant_name - created_at + - fee_breakdown - govpay_metadata - govpay_payment_id - id diff --git a/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/down.sql b/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/down.sql new file mode 100644 index 0000000000..2891481d9b --- /dev/null +++ b/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE "public"."payment_requests" +DROP COLUMN "fee_breakdown"; \ No newline at end of file diff --git a/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/up.sql b/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/up.sql new file mode 100644 index 0000000000..2d988221af --- /dev/null +++ b/hasura.planx.uk/migrations/1733686124805_alter_table_public_payment_requests_add_column_fee_breakdown/up.sql @@ -0,0 +1,2 @@ +alter table "public"."payment_requests" add column "fee_breakdown" jsonb + null;