Skip to content

Commit

Permalink
Merge pull request #708 from companieshouse/feature/ecct-617-validati…
Browse files Browse the repository at this point in the history
…on-for-statement-checkboxes

Feature/ecct 617 validation for statement checkboxes
  • Loading branch information
nevans4-ch authored Dec 20, 2023
2 parents 39afd8b + 2eca378 commit 4099248
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 12 deletions.
52 changes: 50 additions & 2 deletions src/controllers/review.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { startPaymentsSession } from "../services/payment.service";
import { ApiResponse } from "@companieshouse/api-sdk-node/dist/services/resource";
import { Payment } from "@companieshouse/api-sdk-node/dist/services/payment";
import { createAndLogError } from "../utils/logger";
import { links } from "../utils/constants";
import { links, CONFIRMATION_STATEMENT_ERROR, LAWFUL_ACTIVITY_STATEMENT_ERROR } from "../utils/constants";
import { toReadableFormat } from "../utils/date";
import { ConfirmationStatementSubmission } from "@companieshouse/api-sdk-node/dist/services/confirmation-statement";
import { getConfirmationStatement } from "../services/confirmation.statement.service";
Expand Down Expand Up @@ -55,7 +55,46 @@ export const post = async (req: Request, res: Response, next: NextFunction) => {
const transactionId = urlUtils.getTransactionIdFromRequestParams(req);
const submissionId = urlUtils.getSubmissionIdFromRequestParams(req);

await sendLawfulPurposeStatementUpdate(req, true);
const company: CompanyProfile = await getCompanyProfile(companyNumber);
const transaction: Transaction = await getTransaction(session, transactionId);
const csSubmission: ConfirmationStatementSubmission = await getConfirmationStatement(session, transactionId, submissionId);

const statementDate: Date = new Date(company.confirmationStatement?.nextMadeUpTo as string);
const ecctEnabled: boolean = ecctDayOneEnabled(statementDate);

if (ecctEnabled) {

const confirmationCheckboxValue = req.body.confirmationStatement;
const lawfulActivityCheckboxValue = req.body.lawfulActivityStatement;

const confirmationValid = isStatementCheckboxTicked(confirmationCheckboxValue);
const lawfulActivityValid = isStatementCheckboxTicked(lawfulActivityCheckboxValue);

let confirmationStatementError: string = "";
if (!confirmationValid) {
confirmationStatementError = CONFIRMATION_STATEMENT_ERROR;
}

let lawfulActivityStatementError: string = "";
if (!lawfulActivityValid) {
lawfulActivityStatementError = LAWFUL_ACTIVITY_STATEMENT_ERROR;
}

if (!confirmationValid || !lawfulActivityValid) {
return res.render(Templates.REVIEW, {
backLinkUrl: urlUtils.getUrlToPath(TASK_LIST_PATH, req),
company,
nextMadeUpToDate: toReadableFormat(csSubmission.data?.confirmationStatementMadeUpToDate),
isPaymentDue: isPaymentDue(transaction, submissionId),
ecctEnabled,
confirmationStatementError,
lawfulActivityStatementError
});
}

await sendLawfulPurposeStatementUpdate(req, true);

}

const paymentUrl: string | undefined = await closeTransaction(session, companyNumber, submissionId, transactionId);

Expand Down Expand Up @@ -92,3 +131,12 @@ const isPaymentDue = (transaction: Transaction, submissionId: string): boolean =
}
return transaction.resources[resourceKeyName].links?.[links.COSTS];
};

const isStatementCheckboxTicked = (checkboxValue: string): boolean => {

if (checkboxValue === "true") {
return true;
}

return false;
};
2 changes: 2 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const WRONG_PSC_DETAILS_TEXT = "wrong-psc-details";
export const WRONG_PSC_STATEMENT_TEXT = "wrong-psc-statement";
export const EMAIL_ADDRESS_INVALID: string = "Enter an email address in the correct format, like [email protected]";
export const NO_EMAIL_ADDRESS_SUPPLIED: string = "Enter the registered email address";
export const CONFIRMATION_STATEMENT_ERROR: string = "You need to accept the confirmation statement";
export const LAWFUL_ACTIVITY_STATEMENT_ERROR: string = "You need to accept the statement on the intended future activities of the company";
export const ACCEPT_LAWFUL_PURPOSE_STATEMENT = "acceptLawfulPurposeStatement";

export enum RADIO_BUTTON_VALUE {
Expand Down
64 changes: 62 additions & 2 deletions test/controllers/review.controller.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const COSTS_TEXT = "You will need to pay a fee";
const CONFIRMATION_STATEMENT_TEXT = "By continuing, you confirm that all information required to be delivered by the company pursuant to";
const CONFIRMATION_STATEMENT_ECCT_TEXT = "I confirm that all information required to be delivered by the company pursuant to";
const LAWFUL_ACTIVITY_STATEMENT_TEXT = "I confirm that the intended future activities of the company are lawful";
const CONFIRMATION_STATEMENT_ERROR = "You need to accept the confirmation statement";
const LAWFUL_ACTIVITY_STATEMENT_ERROR = "You need to accept the statement on the intended future activities of the company";
const ERROR_HEADING = "There is a problem";
const COMPANY_NUMBER = "12345678";
const TRANSACTION_ID = "66454";
const SUBMISSION_ID = "435435";
Expand Down Expand Up @@ -192,7 +195,10 @@ describe("review controller tests", () => {
});

describe("post tests", () => {

it("Should redirect to the payment journey url", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2026-06-28";
mockCloseTransaction.mockResolvedValueOnce(PAYMENT_URL);
mockStartPaymentsSession.mockResolvedValueOnce(dummyPaymentResponse);

Expand All @@ -204,6 +210,8 @@ describe("review controller tests", () => {
});

it("Should redirect to the confirmation url", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2026-06-28";
mockCloseTransaction.mockResolvedValueOnce(undefined);

const response = await request(app)
Expand All @@ -214,21 +222,27 @@ describe("review controller tests", () => {
});

it("Should update the lawful purpose statement", async () => {
await request(app).post(URL);
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
await request(app).post(URL).send({ confirmationStatement: "true", lawfulActivityStatement: "true" });
const csSubmission: ConfirmationStatementSubmission = mockUpdateConfirmationStatement.mock.calls[0][3];
expect(csSubmission.data.acceptLawfulPurposeStatement).toBe(true);
});

it("Should show error page if lawful purpose statement update fails", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
mockUpdateConfirmationStatement.mockRejectedValueOnce("Error");
const response = await request(app)
.post(URL);
.post(URL).send({ confirmationStatement: "true", lawfulActivityStatement: "true" });

expect(response.status).toBe(500);
expect(response.text).toContain(SERVICE_UNAVAILABLE_TEXT);
});

it("Should show error page if payment response has no resource", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2026-06-28";
mockCloseTransaction.mockResolvedValueOnce(PAYMENT_URL);
mockStartPaymentsSession.mockResolvedValueOnce({
headers: dummyHeaders,
Expand All @@ -244,6 +258,8 @@ describe("review controller tests", () => {
});

it("Should show error page if error is thrown inside post function", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2026-06-28";
mockCloseTransaction.mockRejectedValueOnce(new Error("Internal error"));

const response = await request(app)
Expand All @@ -253,5 +269,49 @@ describe("review controller tests", () => {
expect(response.text).toContain(SERVICE_UNAVAILABLE_TEXT);
expect(mockStartPaymentsSession).not.toHaveBeenCalled();
});

it("Should go to payment url when both confirmation & lawful activity statement checkboxes are ticked", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
mockCloseTransaction.mockResolvedValueOnce(PAYMENT_URL);
mockStartPaymentsSession.mockResolvedValueOnce(dummyPaymentResponse);
const response = await request(app).post(URL).send({ confirmationStatement: "true", lawfulActivityStatement: "true" });
expect(response.status).toEqual(302);
expect(response.header.location).toBe(PAYMENT_JOURNEY_URL);
});

it("Should reload the review page with error messages when both confirmation & lawful activity statement checkboxes not ticked", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
mockGetTransaction.mockResolvedValueOnce(dummyTransactionNoCosts);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
const response = await request(app).post(URL).send();
expect(response.status).toEqual(200);
expect(response.text).toContain(ERROR_HEADING);
expect(response.text).toContain(CONFIRMATION_STATEMENT_ERROR);
expect(response.text).toContain(LAWFUL_ACTIVITY_STATEMENT_ERROR);
});

it("Should reload the review page with an error message when confirmation statement checkbox not ticked", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
mockGetTransaction.mockResolvedValueOnce(dummyTransactionNoCosts);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
const response = await request(app).post(URL).send({ lawfulActivityStatement: "true" });
expect(response.status).toEqual(200);
expect(response.text).toContain(ERROR_HEADING);
expect(response.text).toContain(CONFIRMATION_STATEMENT_ERROR);
expect(response.text).not.toContain(LAWFUL_ACTIVITY_STATEMENT_ERROR);
});

it("Should reload the review page with an error message when lawful activity statement checkbox not ticked", async () => {
mockGetCompanyProfile.mockResolvedValueOnce(validCompanyProfile);
mockGetTransaction.mockResolvedValueOnce(dummyTransactionNoCosts);
PropertiesMock.FEATURE_FLAG_ECCT_START_DATE_14082023 = "2020-02-01";
const response = await request(app).post(URL).send({ confirmationStatement: "true" });
expect(response.status).toEqual(200);
expect(response.text).toContain(ERROR_HEADING);
expect(response.text).toContain(LAWFUL_ACTIVITY_STATEMENT_ERROR);
expect(response.text).not.toContain(CONFIRMATION_STATEMENT_ERROR);
});

});
});
76 changes: 68 additions & 8 deletions views/review.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{% extends "layout.html" %}

{% block pageTitle %}
Submit the confirmation statement
{% if confirmationStatementError or lawfulActivityStatementError %}
Error:
{% endif %}
Submit the confirmation statement
{% endblock %}

{% block backLink %}
Expand All @@ -19,40 +22,97 @@ <h2 class="govuk-heading-m">
Confirmation statement date: {{nextMadeUpToDate}}</h2>
<form action="" method="post">
{% if ecctEnabled %}
{% if confirmationStatementError or lawfulActivityStatementError %}

{{ govukErrorSummary({
titleText: "There is a problem",
errorList: [
{
text: confirmationStatementError,
href: "#confirmation-statement"
},
{
text: lawfulActivityStatementError,
href: "#lawful-activity-statement"
}
]
}) }}

{% if confirmationStatementError %}
{% set confirmationStatementError = {
text: confirmationStatementError
} %}
{% else %}
{% set confirmationStatementError = false %}
{% endif %}

{% if lawfulActivityStatementError %}
{% set lawfulActivityStatementError = {
text: lawfulActivityStatementError
} %}
{% else %}
{% set lawfulActivityStatementError = false %}
{% endif %}

{% endif %}

<p>
{{ govukCheckboxes({
name: "confirmation-statement",
idPrefix: "confirmation-statement",
name: "confirmationStatement",
errorMessage: confirmationStatementError,
fieldset: {
legend: {
isPageHeading: false,
classes: "govuk-fieldset-legend--l"
classes: "govuk-fieldset__legend--m"
}
},
items: [
{
value: "confirmationStatement",
html: "I confirm that all information required to be delivered by the company pursuant to " +
"<a href=" + "https://www.legislation.gov.uk/ukpga/2006/46/section/853A data-event-id=section-831A(1)-information-link>section 853A(1)(a) of the Companies Act 2006</a>" +
" in relation to the confirmation period ending " +
"<strong>" + nextMadeUpToDate + "</strong>" + " either has been delivered or is being delivered with this statement.",
id: "confirmationStatement"
},
id: "confirmation-statement",
name: "confirmationStatement",
value: "true"
}
]
}) }}
</p>
<p>
{{ govukCheckboxes({
idPrefix: "lawful-activity-statement",
name: "lawfulActivityStatement",
errorMessage: lawfulActivityStatementError,
fieldset: {
legend: {
isPageHeading: false,
classes: "govuk-fieldset__legend--m"
}
},
items: [
{
value: "lawfulActivityStatement",
html: "I confirm that the intended future activities of the company are lawful.",
id: "lawfulActivityStatement"
id: "lawful-activity-statement",
name: "lawfulActivityStatement",
value: "true"
}
]
}) }}
</p>

{% else %}

<p>By continuing, you confirm that all information required to be delivered by the company pursuant to
<a href="https://www.legislation.gov.uk/ukpga/2006/46/section/853A" data-event-id="section-831A(1)-information-link">section 853A(1)(a) of the Companies Act 2006</a>
in relation to the confirmation period ending
<strong>{{nextMadeUpToDate}}</strong>
either has been delivered or is being delivered with this statement.
</p>

{% endif %}

{% if isPaymentDue %}
<p>You will need to pay a fee of £13 to submit your confirmation statement.</p>
{% endif %}
Expand Down

0 comments on commit 4099248

Please sign in to comment.