Skip to content

Commit 8868d1a

Browse files
authored
Merge pull request #833 from companieshouse/feature/DEEP-620-add-endpoint-for-valid-first-request-psc-extensions
Adding new endpoints for psc extension service
2 parents 2b5473e + b34af64 commit 8868d1a

File tree

3 files changed

+387
-1
lines changed

3 files changed

+387
-1
lines changed

src/services/psc-extensions-link/service.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PscExtension, PscExtensionData } from "./types"
1+
import { PscExtension, PscExtensionData, ValidationStatusResponse } from "./types"
22

33
import { Headers, HttpResponse, IHttpClient } from "../../http";
44
import Resource, { ApiErrorResponse } from "../resource";
@@ -34,6 +34,58 @@ export default class PscExtensionService {
3434
return this.populateFrontEndResource(response);
3535
}
3636

37+
/**
38+
* Retrieves the count of extension requests for a specific PSC notification.
39+
*
40+
* @param pscNotificationId - The unique identifier of the PSC notification.
41+
* @param headers - Optional headers to include in the request.
42+
* @returns A promise that resolves to either:
43+
* - A `Resource<number>` object containing the extension count (0, 1, or 2).
44+
* - An `ApiErrorResponse` object if an error occurs during the request.
45+
*/
46+
public async getPscExtensionCount (pscNotificationId: string, headers?: Headers): Promise<Resource<number> | ApiErrorResponse> {
47+
const resourceUri = `/persons-with-significant-control-extensions/${pscNotificationId}/extensionCount`;
48+
const response = await this.client.httpGet(resourceUri, headers);
49+
50+
if (response.error) {
51+
return this.handleErrorResponse(response);
52+
}
53+
54+
const frontEndResource: Resource<number> = {
55+
httpStatusCode: response.status,
56+
resource: response.body as number
57+
};
58+
59+
return frontEndResource;
60+
}
61+
62+
/**
63+
* Validates whether a PSC extension request is valid for the given parameters.
64+
*
65+
* @param transactionId - The unique identifier of the transaction.
66+
* @param pscNotificationId - The unique identifier of the PSC notification.
67+
* @param companyNumber - The company number.
68+
* @param headers - Optional headers to include in the request.
69+
* @returns A promise that resolves to either:
70+
* - A `Resource<ValidationStatusResponse>` object containing validation results.
71+
* - An `ApiErrorResponse` object if an error occurs during the request.
72+
*/
73+
public async getIsPscExtensionValid (transactionId: string, pscNotificationId: string, companyNumber: string, headers?: Headers): Promise<Resource<ValidationStatusResponse> | ApiErrorResponse> {
74+
const resourceUri = `/persons-with-significant-control-extensions/${transactionId}/${pscNotificationId}/${companyNumber}/isPscExtensionRequestValid`;
75+
const response = await this.client.httpGet(resourceUri, headers);
76+
77+
if (response.error) {
78+
return this.handleErrorResponse(response);
79+
}
80+
81+
const frontEndResource: Resource<ValidationStatusResponse> = {
82+
httpStatusCode: response.status,
83+
resource: Mapping.camelCaseKeys<ValidationStatusResponse>(response.body)
84+
};
85+
86+
return frontEndResource;
87+
}
88+
3789
/**
3890
* Maps the response body to a front-end resource format with camelCase keys.
3991
*
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { ReasonPhrases, StatusCodes } from "http-status-codes";
2+
import { RequestClient } from "../../../src";
3+
import { PscExtension, PscExtensionData, ValidationStatusResponse } from "../../../src/services/psc-extensions-link/types";
4+
5+
export const requestClient = new RequestClient({ baseUrl: "URL_NOT_USED", oauthToken: "123" });
6+
export const TRANSACTION_ID = "1234-5678-9123";
7+
export const PSC_NOTIFICATION_ID = "123456";
8+
export const COMPANY_NUMBER = "00064000";
9+
10+
const PSC_EXTENSION_DATA: PscExtensionData = {
11+
companyNumber: COMPANY_NUMBER,
12+
pscNotificationId: PSC_NOTIFICATION_ID,
13+
extensionDetails: {
14+
extensionReason: "Have arranged through GOV.UK One Login to verify identity at the Post Office",
15+
extensionStatus: "pending",
16+
extensionRequestDate: "2024-10-17"
17+
}
18+
};
19+
20+
const PSC_EXTENSION_RESOURCE = {
21+
created_at: new Date("2024-10-17T10:30:00Z"),
22+
updated_at: new Date("2024-10-17T10:30:00Z"),
23+
links: {
24+
self: `/transactions/${TRANSACTION_ID}/persons-with-significant-control-extensions/extension-id`,
25+
validation_status: `/transactions/${TRANSACTION_ID}/persons-with-significant-control-extensions/extension-id/validation_status`
26+
},
27+
data: {
28+
company_number: COMPANY_NUMBER,
29+
psc_notification_id: PSC_NOTIFICATION_ID,
30+
extension_details: {
31+
extension_reason: "Have arranged through GOV.UK One Login to verify identity at the Post Office",
32+
extension_status: "pending",
33+
extension_request_date: "2024-10-17"
34+
}
35+
}
36+
};
37+
38+
export const PSC_EXTENSION: PscExtension = {
39+
createdAt: new Date("2024-10-17T10:30:00Z"),
40+
updatedAt: new Date("2024-10-17T10:30:00Z"),
41+
links: {
42+
self: `/transactions/${TRANSACTION_ID}/persons-with-significant-control-extensions/extension-id`,
43+
validationStatus: `/transactions/${TRANSACTION_ID}/persons-with-significant-control-extensions/extension-id/validation_status`
44+
},
45+
data: PSC_EXTENSION_DATA
46+
};
47+
48+
const VALIDATION_STATUS_RESPONSE_RESOURCE = {
49+
is_valid: true,
50+
errors: []
51+
};
52+
53+
export const VALIDATION_STATUS_RESPONSE: ValidationStatusResponse = {
54+
isValid: true,
55+
errors: []
56+
};
57+
58+
const VALIDATION_STATUS_RESPONSE_INVALID_RESOURCE = {
59+
is_valid: false,
60+
errors: [
61+
{
62+
error: "PSC has exceeded maximum number of extension requests",
63+
location: "$.",
64+
location_type: "json-path",
65+
type: "ch:validation"
66+
}
67+
]
68+
};
69+
70+
export const VALIDATION_STATUS_RESPONSE_INVALID: ValidationStatusResponse = {
71+
isValid: false,
72+
errors: [
73+
{
74+
error: "PSC has exceeded maximum number of extension requests",
75+
location: "$.",
76+
locationType: "json-path",
77+
type: "ch:validation"
78+
}
79+
]
80+
};
81+
82+
export const mockPostPscExtensionResponse = {
83+
201: { status: StatusCodes.CREATED, body: PSC_EXTENSION_RESOURCE },
84+
400: { status: StatusCodes.BAD_REQUEST, error: ReasonPhrases.BAD_REQUEST },
85+
401: { status: StatusCodes.UNAUTHORIZED, error: ReasonPhrases.UNAUTHORIZED },
86+
404: { status: StatusCodes.NOT_FOUND, error: ReasonPhrases.NOT_FOUND },
87+
500: { status: StatusCodes.INTERNAL_SERVER_ERROR, error: ReasonPhrases.INTERNAL_SERVER_ERROR }
88+
};
89+
90+
export const mockGetPscExtensionCountResponse = {
91+
200: { status: StatusCodes.OK, body: 1 },
92+
400: { status: StatusCodes.BAD_REQUEST, error: ReasonPhrases.BAD_REQUEST },
93+
401: { status: StatusCodes.UNAUTHORIZED, error: ReasonPhrases.UNAUTHORIZED },
94+
404: { status: StatusCodes.NOT_FOUND, error: ReasonPhrases.NOT_FOUND },
95+
500: { status: StatusCodes.INTERNAL_SERVER_ERROR, error: ReasonPhrases.INTERNAL_SERVER_ERROR }
96+
};
97+
98+
export const mockGetIsPscExtensionValidResponse = {
99+
200: { status: StatusCodes.OK, body: VALIDATION_STATUS_RESPONSE_RESOURCE },
100+
400: { status: StatusCodes.BAD_REQUEST, error: ReasonPhrases.BAD_REQUEST },
101+
401: { status: StatusCodes.UNAUTHORIZED, error: ReasonPhrases.UNAUTHORIZED },
102+
404: { status: StatusCodes.NOT_FOUND, error: ReasonPhrases.NOT_FOUND },
103+
500: { status: StatusCodes.INTERNAL_SERVER_ERROR, error: ReasonPhrases.INTERNAL_SERVER_ERROR }
104+
};
105+
106+
export const mockGetIsPscExtensionValidInvalidResponse = {
107+
200: { status: StatusCodes.OK, body: VALIDATION_STATUS_RESPONSE_INVALID_RESOURCE }
108+
};
109+
110+
export { PSC_EXTENSION_DATA };

0 commit comments

Comments
 (0)