Skip to content

Commit e66b310

Browse files
authored
Merge pull request #588 from companieshouse/lp-1324-intro-pflp-designate-page
LP-1324 Post transition designate as private fund page
2 parents beec8cd + 0b1f0a3 commit e66b310

File tree

10 files changed

+326
-9
lines changed

10 files changed

+326
-9
lines changed

locales/cy/translations.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,26 @@
656656
"title": "WELSH - What information we'll show on the public register"
657657
},
658658

659+
"redesignateToPflpPage": {
660+
"title": "WELSH - Apply for designation as a private fund limited partnership (PFLP)",
661+
"introduction1": "WELSH - A limited partnership can be designated as a PFLP if it is constituted by an agreement in writing and is a collective investment scheme.",
662+
"introduction2": "WELSH - Once the designation has been made, the type of partnership cannot be changed again.",
663+
"pflpMeaningsIntro": "WELSH - Becoming a PFLP means that:",
664+
"pflpMeanings": {
665+
"capital": "WELSH - imited partners will no longer be required to contribute capital",
666+
"appoint": "WELSH - Limited partners can appoint a person to wind up the partnership if there is no general partner available to do so",
667+
"agreement": "WELSH - Partners can make an agreement about winding up the partnership",
668+
"risk": "WELSH - Limited partners may take more actions without risking losing their limited liability status",
669+
"admin": "WELSH - Some administrative requirements will be removed",
670+
"scheme": "WELSH - The partnership will no longer qualify as a ‘partnership scheme’, and therefore cannot be an authorised contractual scheme under section 235A(6)(aa) of the Financial Services and Markets Act 2000"
671+
},
672+
"information": "WELSH - For more information in the",
673+
"informationLink": "WELSH - Legislative Reform (Private Fund Limited Partnerships) Order 2017",
674+
"cost": "WELSH - It costs £XX to apply.",
675+
"applicationCheck": "WELSH - I/We apply for this firm to be designated as a private fund limited partnership. For that purpose, I confirm that the partnership is constituted by an agreement in writing and is a collective investment scheme within the meaning of section 8D(4) of the Limited Partnerships Act 1907",
676+
"confirmationCheck": "WELSH - I confirm that all general partners have agreed for this application to be made"
677+
},
678+
659679
"removePartnerPage": {
660680
"title": "WELSH - Are you sure you want to remove"
661681
},

locales/en/translations.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,26 @@
657657
"title": "What information we'll show on the public register"
658658
},
659659

660+
"redesignateToPflpPage": {
661+
"title": "Apply for designation as a private fund limited partnership (PFLP)",
662+
"introduction1": "A limited partnership can be designated as a PFLP if it is constituted by an agreement in writing and is a collective investment scheme.",
663+
"introduction2": "Once the designation has been made, the type of partnership cannot be changed again.",
664+
"pflpMeaningsIntro": "Becoming a PFLP means that:",
665+
"pflpMeanings": {
666+
"capital": "Limited partners will no longer be required to contribute capital",
667+
"appoint": "Limited partners can appoint a person to wind up the partnership if there is no general partner available to do so",
668+
"agreement": "Partners can make an agreement about winding up the partnership",
669+
"risk": "Limited partners may take more actions without risking losing their limited liability status",
670+
"admin": "Some administrative requirements will be removed",
671+
"scheme": "The partnership will no longer qualify as a ‘partnership scheme’, and therefore cannot be an authorised contractual scheme under section 235A(6)(aa) of the Financial Services and Markets Act 2000"
672+
},
673+
"information": "For more information in the",
674+
"informationLink": "Legislative Reform (Private Fund Limited Partnerships) Order 2017",
675+
"cost": "It costs £XX to apply.",
676+
"applicationCheck": "I/We apply for this firm to be designated as a private fund limited partnership. For that purpose, I confirm that the partnership is constituted by an agreement in writing and is a collective investment scheme within the meaning of section 8D(4) of the Limited Partnerships Act 1907",
677+
"confirmationCheck": "I confirm that all general partners have agreed for this application to be made"
678+
},
679+
660680
"removePartnerPage": {
661681
"title": "Are you sure you want to remove"
662682
},

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"license": "MIT",
3434
"homepage": "https://github.com/companieshouse/limited-partnerships-web#readme",
3535
"dependencies": {
36-
"@companieshouse/api-sdk-node": "^2.0.310",
36+
"@companieshouse/api-sdk-node": "^2.0.315",
3737
"@companieshouse/ch-node-utils": "^2.1.8",
3838
"@companieshouse/node-session-handler": "^5.0.1",
3939
"@companieshouse/structured-logging-node": "^2.0.1",

src/presentation/controller/postTransition/LimitedPartnershipController.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,91 @@ class LimitedPartnershipController extends AbstractController {
424424
};
425425
}
426426

427+
postRedesignateToPFLP() {
428+
return async (request: Request, response: Response, next: NextFunction) => {
429+
try {
430+
const { tokens, ids } = super.extract(request);
431+
const pageType = super.extractPageTypeOrThrowError(request, PostTransitionPageType);
432+
const pageRouting = super.getRouting(postTransitionRouting, pageType, request);
433+
const { limitedPartnership } = await this.companyService.buildLimitedPartnershipFromCompanyProfile(
434+
tokens,
435+
ids.companyId
436+
);
437+
438+
const errorData = this.makeErrorData(
439+
limitedPartnership,
440+
request.body
441+
);
442+
443+
const resultTransaction = await this.createTransaction(limitedPartnership, tokens);
444+
if (resultTransaction.errors) {
445+
return response.render(
446+
super.templateName(pageRouting.currentUrl),
447+
super.makeProps(pageRouting, errorData, resultTransaction.errors)
448+
);
449+
}
450+
451+
const resultLimitedPartnershipCreate = await this.createPartnership(
452+
request,
453+
limitedPartnership,
454+
resultTransaction.transactionId,
455+
PartnershipKind.UPDATE_PARTNERSHIP_REDESIGNATE_TO_PFLP,
456+
{
457+
...request.body,
458+
date_of_update: new Date().toISOString().split('T')[0]
459+
}
460+
);
461+
if (resultLimitedPartnershipCreate.errors) {
462+
return response.render(
463+
super.templateName(pageRouting.currentUrl),
464+
super.makeProps(pageRouting, errorData, resultLimitedPartnershipCreate.errors)
465+
);
466+
}
467+
468+
const newIds = {
469+
...ids,
470+
transactionId: resultTransaction.transactionId,
471+
submissionId: resultLimitedPartnershipCreate.submissionId
472+
};
473+
474+
let redirectUrl = super
475+
.insertIdsInUrl(CONFIRMATION_POST_TRANSITION_URL, newIds, request.url)
476+
.replace(JOURNEY_TYPE_PARAM, getJourneyTypes(request.url).journey);
477+
478+
const closeTransactionResponse = await this.limitedPartnershipService.closeTransaction(
479+
tokens,
480+
newIds.transactionId
481+
);
482+
483+
const startPaymentSessionUrl: string = closeTransactionResponse.headers?.["x-payment-required"];
484+
if (!startPaymentSessionUrl) {
485+
throw new Error("No payment URL found in response header from closeTransaction");
486+
}
487+
488+
const urlWithJourney = `${CHS_URL}${PAYMENT_RESPONSE_URL}`.replace(
489+
JOURNEY_TYPE_PARAM,
490+
getJourneyTypes(request.url).journey
491+
);
492+
493+
const paymentReturnUri = super.insertIdsInUrl(urlWithJourney, newIds, request.url);
494+
495+
redirectUrl = await this.paymentService.startPaymentSession(
496+
tokens,
497+
startPaymentSessionUrl,
498+
paymentReturnUri,
499+
newIds.transactionId
500+
);
501+
502+
if (!redirectUrl) {
503+
throw new Error("No payment redirect URL returned from start payment session");
504+
}
505+
response.redirect(redirectUrl);
506+
} catch (error) {
507+
next(error);
508+
}
509+
};
510+
}
511+
427512
private validateAddress(
428513
request: Request,
429514
response: Response,

src/presentation/controller/postTransition/routing/limitedPartnership.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ const postTransitionRoutingPrincipalPlaceOfBusinessAddressChangeCheckYourAnswers
147147
}
148148
};
149149

150+
const postTransitionRoutingRedesignateToPFLP = {
151+
previousUrl: url.LANDING_PAGE_URL,
152+
currentUrl: url.REDESIGNATE_TO_PFLP_URL,
153+
nextUrl: "/",
154+
pageType: PostTransitionPageType.redesignateToPflp
155+
};
156+
150157
const limitedPartnershipRouting = [
151158
postTransitionRoutingCompanyNumber,
152159
postTransitionRoutingConfirmLimitedPartnership,
@@ -166,7 +173,8 @@ const limitedPartnershipRouting = [
166173

167174
postTransitionRoutingPrincipalPlaceOfBusinessAddress,
168175
postTransitionRoutingPrincipalPlaceOfBusinessAddressChange,
169-
postTransitionRoutingPrincipalPlaceOfBusinessAddressChangeCheckYourAnswers
176+
postTransitionRoutingPrincipalPlaceOfBusinessAddressChangeCheckYourAnswers,
177+
postTransitionRoutingRedesignateToPFLP
170178
];
171179

172180
export default limitedPartnershipRouting;

src/presentation/controller/postTransition/url.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const TERM_URL = `${POST_TRANSITION_WITH_ID_URL}/${template.TERM_TEMPLATE
4444
export const TERM_WITH_IDS_URL = `${POST_TRANSITION_WITH_IDS_AND_SUBMISSION_URL}/${template.TERM_TEMPLATE}`;
4545
export const WHEN_DID_THE_TERM_CHANGE_URL = `${POST_TRANSITION_WITH_IDS_AND_SUBMISSION_URL}/${template.WHEN_DID_TERM_CHANGE_TEMPLATE}`;
4646
export const TERM_CHANGE_CHECK_YOUR_ANSWERS_URL = `${POST_TRANSITION_WITH_IDS_AND_SUBMISSION_URL}/${template.TERM_CHANGE_CHECK_YOUR_ANSWERS_TEMPLATE}`;
47+
export const REDESIGNATE_TO_PFLP_URL = `${POST_TRANSITION_WITH_ID_URL}/${template.REDESIGNATE_TO_PFLP_TEMPLATE}`;
4748

4849
export const ENTER_PRINCIPAL_PLACE_OF_BUSINESS_ADDRESS_URL = `${POST_TRANSITION_WITH_ID_URL}/${template.ENTER_PRINCIPAL_PLACE_OF_BUSINESS_ADDRESS_TEMPLATE}`;
4950
export const ENTER_PRINCIPAL_PLACE_OF_BUSINESS_ADDRESS_WITH_IDS_URL = `${POST_TRANSITION_WITH_IDS_AND_SUBMISSION_URL}/${template.ENTER_PRINCIPAL_PLACE_OF_BUSINESS_ADDRESS_TEMPLATE}`;
@@ -64,5 +65,3 @@ export const REMOVE_LIMITED_PARTNER_PERSON_CHECK_YOUR_ANSWERS_URL = `${POST_TRAN
6465
export const WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_URL = `${POST_TRANSITION_WITH_ID_URL}${APPOINTMENT_ID_URL}/${template.WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_TEMPLATE}`;
6566
export const WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_WITH_IDS_URL = `${POST_TRANSITION_WITH_IDS_URL}${LIMITED_PARTNER_WITH_ID_URL}/${template.WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_TEMPLATE}`;
6667
export const REMOVE_LIMITED_PARTNER_LEGAL_ENTITY_CHECK_YOUR_ANSWERS_URL = `${POST_TRANSITION_WITH_IDS_URL}${LIMITED_PARTNER_WITH_ID_URL}/${template.REMOVE_LIMITED_PARTNER_LEGAL_ENTITY_CHECK_YOUR_ANSWERS_TEMPLATE}`;
67-
68-
export const REDESIGNATE_TO_PFLP_URL = `${POST_TRANSITION_WITH_IDS_URL}${LIMITED_PARTNER_WITH_ID_URL}/${template.REDESIGNATE_TO_PFLP_TEMPLATE}`;
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import request from "supertest";
2+
3+
import enTranslationText from "../../../../../../locales/en/translations.json";
4+
import cyTranslationText from "../../../../../../locales/cy/translations.json";
5+
6+
import app from "../../app";
7+
import { appDevDependencies } from "../../../../../config/dev-dependencies";
8+
import { getUrl, setLocalesEnabled, testTranslations } from "../../../utils";
9+
import { REDESIGNATE_TO_PFLP_URL } from "presentation/controller/postTransition/url";
10+
import CompanyProfileBuilder from "../../../builder/CompanyProfileBuilder";
11+
import PostTransitionPageType from "presentation/controller/postTransition/pageType";
12+
import { PartnershipType } from "@companieshouse/api-sdk-node/dist/services/limited-partnerships";
13+
import { TRANSACTION_DESCRIPTION_UPDATE_LIMITED_PARTNERSHIP } from "config";
14+
import LimitedPartnershipBuilder from "presentation/test/builder/LimitedPartnershipBuilder";
15+
import { ApiErrors } from "domain/entities/UIErrors";
16+
17+
describe("Redesignate to pflp page", () => {
18+
const URL = getUrl(REDESIGNATE_TO_PFLP_URL);
19+
const PAYMENT_LINK_JOURNEY = "https://api-test-payments.chs.local:4001";
20+
let companyProfile;
21+
22+
beforeEach(() => {
23+
setLocalesEnabled(true);
24+
companyProfile = new CompanyProfileBuilder().build();
25+
appDevDependencies.companyGateway.feedCompanyProfile(companyProfile.data);
26+
appDevDependencies.limitedPartnershipGateway.feedLimitedPartnerships([]);
27+
appDevDependencies.limitedPartnershipGateway.feedErrors();
28+
appDevDependencies.limitedPartnershipGateway.setError(false);
29+
});
30+
31+
describe("GET page", () => {
32+
it("should load the page with English text", async () => {
33+
const res = await request(app).get(URL + "?lang=en");
34+
35+
expect(res.status).toBe(200);
36+
testTranslations(res.text, enTranslationText.redesignateToPflpPage);
37+
expect(res.text).toContain(
38+
`${enTranslationText.redesignateToPflpPage.title} - ${enTranslationText.servicePostTransition} - GOV.UK`
39+
);
40+
expect(res.text).not.toContain("WELSH -");
41+
});
42+
43+
it("should load the page with Welsh text", async () => {
44+
const res = await request(app).get(URL + "?lang=cy");
45+
46+
expect(res.status).toBe(200);
47+
expect(res.text).toContain(
48+
`${cyTranslationText.redesignateToPflpPage.title} - ${cyTranslationText.servicePostTransition} - GOV.UK`
49+
);
50+
testTranslations(res.text, cyTranslationText.redesignateToPflpPage);
51+
});
52+
});
53+
54+
describe("POST page", () => {
55+
it("should create a transaction, send data and navigate to payment", async () => {
56+
const res = await request(app).post(URL).send({
57+
pageType: PostTransitionPageType.redesignateToPflp,
58+
redesignate_to_pflp_apply: true,
59+
redesignate_to_pflp_confirm: true,
60+
partnership_type: PartnershipType.LP
61+
});
62+
63+
expect(res.status).toBe(302);
64+
expect(res.text).toContain(`Redirecting to ${PAYMENT_LINK_JOURNEY}`);
65+
expect(appDevDependencies.limitedPartnershipGateway.limitedPartnerships.length).toEqual(1);
66+
expect(appDevDependencies.transactionGateway.transactions[0].description).toEqual(TRANSACTION_DESCRIPTION_UPDATE_LIMITED_PARTNERSHIP);
67+
});
68+
69+
it("should return a validation error if api validation error occurs creating LimitedPartnership", async () => {
70+
const limitedPartnership = new LimitedPartnershipBuilder().build();
71+
appDevDependencies.limitedPartnershipGateway.feedLimitedPartnerships([limitedPartnership]);
72+
const apiErrors: ApiErrors = {
73+
errors: { something: "Something is invalid" }
74+
};
75+
appDevDependencies.limitedPartnershipGateway.feedErrors(apiErrors);
76+
77+
const res = await request(app)
78+
.post(URL)
79+
.send({
80+
pageType: PostTransitionPageType.enterPrincipalPlaceOfBusinessAddress,
81+
...limitedPartnership.data?.principal_place_of_business_address
82+
});
83+
84+
expect(res.status).toBe(200);
85+
expect(res.text).toContain(enTranslationText.govUk.error.title);
86+
expect(res.text).toContain(companyProfile.data.companyName.toUpperCase());
87+
expect(res.text).toContain("Something is invalid");
88+
});
89+
90+
it("should throw error when payment redirect url is missing", async () => {
91+
appDevDependencies.paymentGateway.feedPaymentWithEmptyJourney();
92+
const res = await request(app).post(URL).send({
93+
pageType: PostTransitionPageType.redesignateToPflp
94+
});
95+
96+
expect(res.status).toBe(500);
97+
expect(res.text).not.toContain(`Redirecting to ${PAYMENT_LINK_JOURNEY}`);
98+
});
99+
});
100+
});

src/routes/postTransition.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ import {
4848
REMOVE_LIMITED_PARTNER_PERSON_CHECK_YOUR_ANSWERS_URL,
4949
WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_WITH_IDS_URL,
5050
WHEN_DID_THE_LIMITED_PARTNER_LEGAL_ENTITY_CEASE_URL,
51-
REMOVE_LIMITED_PARTNER_LEGAL_ENTITY_CHECK_YOUR_ANSWERS_URL
51+
REMOVE_LIMITED_PARTNER_LEGAL_ENTITY_CHECK_YOUR_ANSWERS_URL,
52+
REDESIGNATE_TO_PFLP_URL
5253
} from "../presentation/controller/postTransition/url";
5354
import {
5455
TRANSACTION_DESCRIPTION_ADD_GENERAL_PARTNER_LEGAL_ENTITY,
@@ -427,6 +428,17 @@ const postTransitionEndpoints = (router: Router, dependencies: IDependencies): v
427428
dependencies.limitedPartnershipPostTransitionController.postCheckYourAnswers()
428429
);
429430

431+
router.get(
432+
REDESIGNATE_TO_PFLP_URL,
433+
companyAuthentication,
434+
dependencies.limitedPartnershipPostTransitionController.getPageRouting()
435+
);
436+
router.post(
437+
REDESIGNATE_TO_PFLP_URL,
438+
companyAuthentication,
439+
dependencies.limitedPartnershipPostTransitionController.postRedesignateToPFLP()
440+
);
441+
430442
// Remove General Partner
431443
router.get(
432444
WHEN_DID_THE_GENERAL_PARTNER_PERSON_CEASE_URL,

0 commit comments

Comments
 (0)