diff --git a/src/config/index.ts b/src/config/index.ts index 1b359081b..074b7f22c 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -146,6 +146,7 @@ export const UPDATE_STATEMENT_VALIDATION_ERRORS_PAGE = "update-statement-validat export const REMOVE_SOLD_ALL_LAND_FILTER_PAGE = "remove-sold-all-land-filter"; export const REMOVE_IS_ENTITY_REGISTERED_OWNER_PAGE = "remove-is-entity-registered-owner"; export const REMOVE_CANNOT_USE_PAGE = "remove-cannot-use"; +export const REMOVE_NEED_MAKE_CHANGES_PAGE = "remove-need-to-make-changes-to-entity"; // URL PARAMS export const ROUTE_PARAM_TRUST_ID = "trustId"; @@ -304,6 +305,7 @@ export const UPDATE_PAYMENT_FAILED_URL = UPDATE_AN_OVERSEAS_ENTITY_URL + PAYMENT export const REMOVE_SOLD_ALL_LAND_FILTER_URL = UPDATE_AN_OVERSEAS_ENTITY_URL + REMOVE_SOLD_ALL_LAND_FILTER_PAGE; export const REMOVE_CANNOT_USE_URL = UPDATE_AN_OVERSEAS_ENTITY_URL + REMOVE_CANNOT_USE_PAGE; export const REMOVE_IS_ENTITY_REGISTERED_OWNER_URL = UPDATE_AN_OVERSEAS_ENTITY_URL + REMOVE_IS_ENTITY_REGISTERED_OWNER_PAGE; +export const REMOVE_NEED_MAKE_CHANGES_URL = UPDATE_AN_OVERSEAS_ENTITY_URL + REMOVE_NEED_MAKE_CHANGES_PAGE; // PAYMENT CONFIGs export const PAYMENT = "payment"; diff --git a/src/controllers/index.ts b/src/controllers/index.ts index a850e6804..a15e1fe71 100644 --- a/src/controllers/index.ts +++ b/src/controllers/index.ts @@ -101,3 +101,4 @@ export * as updateManageTrustsTellUsAboutTheLegalEntity from './update/update.ma export * as removeSoldAllLandFilter from './update/remove.sold.all.land.filter.controller'; export * as removeCannotUse from "./update/remove.cannot.use.controller"; export * as removeIsEntityRegisteredOwner from "./update/remove.is.entity.registered.owner.controller"; +export * as removeNeedMakeChanges from "./update/remove.need.to.make.changes.to.entity.controller"; diff --git a/src/controllers/update/remove.need.to.make.changes.to.entity.controller.ts b/src/controllers/update/remove.need.to.make.changes.to.entity.controller.ts new file mode 100644 index 000000000..96d4d6881 --- /dev/null +++ b/src/controllers/update/remove.need.to.make.changes.to.entity.controller.ts @@ -0,0 +1,30 @@ +import { NextFunction, Request, Response } from "express"; +import * as config from "../../config"; +import { logger } from "../../utils/logger"; + +export const get = (req: Request, res: Response, next: NextFunction) => { + try { + logger.debugRequest(req, `GET ${config.REMOVE_NEED_MAKE_CHANGES_PAGE}`); + return res.render(config.REMOVE_NEED_MAKE_CHANGES_PAGE, { + journey: config.JourneyType.remove, + backLinkUrl: `${config.OVERSEAS_ENTITY_PRESENTER_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`, + templateName: config.REMOVE_NEED_MAKE_CHANGES_PAGE + }); + } catch (error) { + next(error); + } +}; + +export const post = (req: Request, res: Response, next: NextFunction) => { + try { + logger.debugRequest(req, `POST ${config.REMOVE_NEED_MAKE_CHANGES_PAGE}`); + + if (req.body["make_changes"] === 'yes') { + return res.redirect(`${config.WHO_IS_MAKING_UPDATE_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + } + // TODO redirect to new component - Has the overseas entity identified any registrable beneficial owners? + return res.redirect(`${config.UPDATE_LANDING_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + } catch (error) { + next(error); + } +}; diff --git a/src/routes/index.ts b/src/routes/index.ts index 3a879d8cf..f0d652118 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -45,6 +45,7 @@ import { removeSoldAllLandFilter, removeIsEntityRegisteredOwner, resumeSubmission, + removeNeedMakeChanges, overseasName, startingNew, overseasEntityPayment, @@ -1098,6 +1099,14 @@ router.route(config.UPDATE_STATEMENT_VALIDATION_ERRORS_URL) .get(validateStatements, statementValidationErrorsGuard, updateStatementValidationErrors.get) .post(validateStatements, ...validator.statementResolution, updateStatementValidationErrors.post); +router.route(config.REMOVE_NEED_MAKE_CHANGES_URL) + .all( + authentication, + companyAuthentication, + navigation.hasUpdatePresenter) + .get(removeNeedMakeChanges.get) + .post(...validator.removeNeedMakeChanges, checkValidations, removeNeedMakeChanges.post); + router.get(config.REMOVE_CANNOT_USE_URL, authentication, removeCannotUse.get); export default router; diff --git a/src/utils/navigation.ts b/src/utils/navigation.ts index b2b5a7d05..0cf567252 100644 --- a/src/utils/navigation.ts +++ b/src/utils/navigation.ts @@ -519,4 +519,9 @@ export const NAVIGATION: Navigation = { previousPage: () => `${config.REMOVE_SOLD_ALL_LAND_FILTER_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`, nextPage: [`${config.SECURE_UPDATE_FILTER_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`] }, + [config.REMOVE_NEED_MAKE_CHANGES_URL]: { // TODO set next and previous to specification in ACs on UAR-1285 + currentPage: config.REMOVE_NEED_MAKE_CHANGES_PAGE, + previousPage: () => `${config.WHO_IS_MAKING_FILING_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`, + nextPage: [`${config.WHO_IS_MAKING_UPDATE_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`] + } }; diff --git a/src/validation/error.messages.ts b/src/validation/error.messages.ts index 385cb17ee..541deb74d 100644 --- a/src/validation/error.messages.ts +++ b/src/validation/error.messages.ts @@ -199,6 +199,7 @@ export enum ErrorMessages { SELECT_DO_YOU_WANT_TO_MAKE_CHANGES_UPDATE_STATEMENT = "Select yes if all the information in this update statement is correct", SELECT_UPDATE_STATEMENT_VALIDATION_RESOLUTION = "Select if you want to change your statements or change the information provided in this update", SELECT_IF_REMOVE_SOLD_ALL_LAND_FILTER = "Select yes if the entity has disposed of all its property or land in the UK", + SELECT_REMOVE_NEED_TO_MAKE_CHANGES = "Select yes if you need to make changes to this overseas entity before it is removed", // MAX Lengths MAX_FIRST_NAME_LENGTH = "First name must be 50 characters or less", diff --git a/src/validation/index.ts b/src/validation/index.ts index 46f8c4630..e81ccac2f 100644 --- a/src/validation/index.ts +++ b/src/validation/index.ts @@ -36,6 +36,7 @@ import { doYouWantToMakeOeChange } from "./update/do.you.want.to.make.oe.change. import { reviewUpdateStatementChange, statementResolution } from "./update/review.update.statement.validation"; import { removeSoldAllLandFilter } from "./update/remove.sold.all.land.filter.validation"; import { removeIsEntityRegisteredOwner } from "./update/remove.is.entity.registered.owner.validation"; +import { removeNeedMakeChanges } from "./update/remove.need.to.make.changes.to.entity.validation"; export const validator = { soldLandFilter, secureRegisterFilter, @@ -87,5 +88,6 @@ export const validator = { reviewUpdateStatementChange, statementResolution, removeSoldAllLandFilter, - removeIsEntityRegisteredOwner + removeIsEntityRegisteredOwner, + removeNeedMakeChanges }; diff --git a/src/validation/update/remove.need.to.make.changes.to.entity.validation.ts b/src/validation/update/remove.need.to.make.changes.to.entity.validation.ts new file mode 100644 index 000000000..afd8e8ac6 --- /dev/null +++ b/src/validation/update/remove.need.to.make.changes.to.entity.validation.ts @@ -0,0 +1,7 @@ +import { body } from "express-validator"; + +import { ErrorMessages } from "../error.messages"; + +export const removeNeedMakeChanges = [ + body("make_changes").not().isEmpty().withMessage(ErrorMessages.SELECT_REMOVE_NEED_TO_MAKE_CHANGES) +]; diff --git a/test/__mocks__/text.mock.ts b/test/__mocks__/text.mock.ts index 36224cd95..3c60e90e7 100644 --- a/test/__mocks__/text.mock.ts +++ b/test/__mocks__/text.mock.ts @@ -250,6 +250,7 @@ export const UPDATE_MANAGE_TRUSTS_REVIEWED_HEADING = "What you have reviewed"; export const REMOVE_SOLD_ALL_LAND_FILTER_PAGE_TITLE = "Has the overseas entity disposed of all its property or land in the UK?"; export const REMOVE_IS_ENTITY_REGISTERED_OWNER_TITLE = "Is the overseas entity currently listed on any land registry records as the registered owner of property or land in the UK?"; export const REMOVE_INTERRUPT_CARD_TEXT = "Once an overseas entity is removed"; +export const REMOVE_NEED_MAKE_CHANGES_TITLE = "Do you need to make any changes to this overseas entity before it is removed?"; // Manage Trusts export const UPDATE_MANAGE_TRUSTS_REVIEW_FORMER_BO_TITLE = "Review former beneficial owners"; diff --git a/test/controllers/update/remove.need.to.make.changes.to.entity.controller.spec.ts b/test/controllers/update/remove.need.to.make.changes.to.entity.controller.spec.ts new file mode 100644 index 000000000..f9f2486fc --- /dev/null +++ b/test/controllers/update/remove.need.to.make.changes.to.entity.controller.spec.ts @@ -0,0 +1,116 @@ +jest.mock("ioredis"); +jest.mock("../../../src/utils/logger"); +jest.mock('../../../src/middleware/authentication.middleware'); +jest.mock('../../../src/middleware/company.authentication.middleware'); +jest.mock('../../../src/middleware/service.availability.middleware'); +jest.mock('../../../src/middleware/navigation/update/has.presenter.middleware'); +jest.mock('../../../src/utils/application.data'); + +import { NextFunction, Request, Response } from "express"; +import * as config from "../../../src/config"; +import request from "supertest"; +import { logger } from "../../../src/utils/logger"; +import app from "../../../src/app"; +import { ErrorMessages } from '../../../src/validation/error.messages'; +import { hasUpdatePresenter } from "../../../src/middleware/navigation/update/has.presenter.middleware"; +import { serviceAvailabilityMiddleware } from "../../../src/middleware/service.availability.middleware"; +import { authentication } from "../../../src/middleware/authentication.middleware"; +import { companyAuthentication } from "../../../src/middleware/company.authentication.middleware"; +import { + ANY_MESSAGE_ERROR, + PAGE_TITLE_ERROR, + FOUND_REDIRECT_TO, + REMOVE_NEED_MAKE_CHANGES_TITLE, + SERVICE_UNAVAILABLE, +} from "../../__mocks__/text.mock"; +import { REMOVE_SERVICE_NAME } from "../../../src/config"; +import { getApplicationData } from "../../../src/utils/application.data"; +import { APPLICATION_DATA_CH_REF_UPDATE_MOCK } from "../../__mocks__/session.mock"; + +const mockGetApplicationData = getApplicationData as jest.Mock; + +const mockHasUpdatePresenter = hasUpdatePresenter as jest.Mock; +mockHasUpdatePresenter.mockImplementation((req: Request, res: Response, next: NextFunction) => next() ); + +const mockCompanyAuthenticationMiddleware = companyAuthentication as jest.Mock; +mockCompanyAuthenticationMiddleware.mockImplementation((req: Request, res: Response, next: NextFunction) => next() ); + +const mockAuthenticationMiddleware = authentication as jest.Mock; +mockAuthenticationMiddleware.mockImplementation((req: Request, res: Response, next: NextFunction) => next()); + +const mockServiceAvailabilityMiddleware = serviceAvailabilityMiddleware as jest.Mock; +mockServiceAvailabilityMiddleware.mockImplementation((req: Request, res: Response, next: NextFunction) => next()); + +const mockLoggerDebugRequest = logger.debugRequest as jest.Mock; + +describe("Remove need to make changes to entity controller", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("GET tests", () => { + test(`renders the ${config.REMOVE_NEED_MAKE_CHANGES_URL} page`, async () => { + mockGetApplicationData.mockReturnValueOnce({ + ...APPLICATION_DATA_CH_REF_UPDATE_MOCK + }); + const resp = await request(app).get(`${config.REMOVE_NEED_MAKE_CHANGES_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(resp.status).toEqual(200); + expect(resp.text).toContain(REMOVE_NEED_MAKE_CHANGES_TITLE); + expect(resp.text).toContain(REMOVE_SERVICE_NAME); + expect(resp.text).not.toContain(PAGE_TITLE_ERROR); + expect(mockLoggerDebugRequest).toHaveBeenCalledTimes(1); + }); + + test("catch error on current page for GET method", async () => { + mockLoggerDebugRequest.mockImplementationOnce(() => { throw new Error(ANY_MESSAGE_ERROR); }); + const resp = await request(app).get(`${config.REMOVE_NEED_MAKE_CHANGES_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(resp.status).toEqual(500); + expect(resp.text).toContain(SERVICE_UNAVAILABLE); + }); + }); + + describe("POST tests", () => { + test(`redirects to the ${config.REMOVE_NEED_MAKE_CHANGES_URL} page when yes is selected`, async () => { + const resp = await request(app) + .post(`${config.REMOVE_NEED_MAKE_CHANGES_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`) + .send({ make_changes: 'yes' }); + expect(resp.status).toEqual(302); + expect(resp.text).toEqual(`${FOUND_REDIRECT_TO} ${config.WHO_IS_MAKING_UPDATE_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(resp.header.location).toEqual(`${config.WHO_IS_MAKING_UPDATE_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(mockLoggerDebugRequest).toHaveBeenCalledTimes(1); + }); + + test(`redirects to the ${config.REMOVE_NEED_MAKE_CHANGES_URL} page when no is selected`, async () => { + const resp = await request(app) + .post(`${config.REMOVE_NEED_MAKE_CHANGES_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`) + .send({ make_changes: 'no' }); + expect(resp.status).toEqual(302); + // TODO redirect to new component - Has the overseas entity identified any registrable beneficial owners? + expect(resp.text).toEqual(`${FOUND_REDIRECT_TO} ${config.UPDATE_LANDING_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(resp.header.location).toEqual(`${config.UPDATE_LANDING_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + expect(mockLoggerDebugRequest).toHaveBeenCalledTimes(1); + }); + + test("renders the current page with error message and correct page title", async () => { + const resp = await request(app) + .post(`${config.REMOVE_NEED_MAKE_CHANGES_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`); + + expect(resp.status).toEqual(200); + expect(resp.text).toContain(REMOVE_NEED_MAKE_CHANGES_TITLE); + expect(resp.text).toContain(PAGE_TITLE_ERROR); + expect(resp.text).toContain(ErrorMessages.SELECT_REMOVE_NEED_TO_MAKE_CHANGES); + expect(resp.text).toContain(REMOVE_SERVICE_NAME); + }); + + test("catch error on current page for POST method", async () => { + mockLoggerDebugRequest.mockImplementationOnce(() => { throw new Error(ANY_MESSAGE_ERROR); }); + const resp = await request(app) + .post(`${config.REMOVE_SOLD_ALL_LAND_FILTER_URL}${config.JOURNEY_REMOVE_QUERY_PARAM}`) + .send({ disposed_all_land: 'yes' }); + + expect(resp.status).toEqual(500); + expect(resp.text).toContain(SERVICE_UNAVAILABLE); + }); + + }); +}); diff --git a/views/update/remove-need-to-make-changes-to-entity.html b/views/update/remove-need-to-make-changes-to-entity.html new file mode 100644 index 000000000..db61f3ecd --- /dev/null +++ b/views/update/remove-need-to-make-changes-to-entity.html @@ -0,0 +1,76 @@ +{% extends "update-layout.html" %} + +{% set title = "Do you need to make any changes to this overseas entity before it is removed?" %} + +{% block pageTitle %} + {% include "includes/update-page-title.html" %} +{% endblock %} + +{% block backLink %} + {% include "includes/back-link.html" %} +{% endblock %} + +{% block content %} + +
+
+ + {% include "includes/list/errors.html" %} + +
+ + {{ data['overseas-name'] }} - OE001485 +

Do you need to make any changes to this overseas entity before it is removed?

+

+ All information about the overseas entity must be up to date before the entity can be removed. It should be correct as at the date of this application. This includes information about any beneficial owners and managing officers. +

+ {{ govukRadios({ + errorMessage: errors.make_changes if errors, + idPrefix: "make_changes", + name: "make_changes", + fieldset: { + legend: { + text: "Have you made any changes to the overseas entity?", + isPageHeading: false, + classes: "govuk-visually-hidden" + } + }, + items: [ + { + value: "yes", + text: "Yes, I need to make changes", + attributes: { + "data-event-id": "make_changes" + } + }, + { + value: "no", + text: "No, I do not need to make changes", + attributes: { + "data-event-id": "make_changes" + } + } + ] + }) + }} + {{ govukButton({ + text: "Save and continue" + }) + }} +
+ + + What verification checks are needed? + + +
+ Verification checks are needed on any changes made to information about the overseas entity, its beneficial owners or managing officers. +
+
+ Verification checks can only be carried out by a UK-regulated agent, and must have been completed no more than 3 months before the date of this update statement.
+
+ + +
+ +{% endblock %} \ No newline at end of file