diff --git a/src/service/persons.with.signficant.control.statement.service.ts b/src/service/persons.with.signficant.control.statement.service.ts new file mode 100644 index 000000000..14ea5942e --- /dev/null +++ b/src/service/persons.with.signficant.control.statement.service.ts @@ -0,0 +1,27 @@ +import { Session } from "@companieshouse/node-session-handler"; +import { Request } from "express"; +import { makeApiCallWithRetry } from "./retry.handler.service"; +import { createAndLogErrorRequest, logger } from "../utils/logger"; +import { CompanyPersonsWithSignificantControlStatements } from "@companieshouse/api-sdk-node/dist/services/company-psc-statements/types"; + +export const getCompanyPscStatements = async ( + req: Request, + companyNumber: string, +): Promise => { + const response = await makeApiCallWithRetry( + "companyPscStatements", + "getCompanyPscStatements", + req, + req.session as Session, + companyNumber + ); + + if (response.httpStatusCode === 200) { + logger.debugRequest(req, `Received company PSC Statment data for ${companyNumber}`); + } else if (response.httpStatusCode === 404) { + logger.debugRequest(req, `No company PSC Statment data found for ${companyNumber}`); + } else { + throw createAndLogErrorRequest(req, `getCompanyPscStatements API request returned HTTP status code ${response.httpStatusCode}`); + } + return response?.resource; +}; diff --git a/test/__mocks__/get.company.psc.statement.mock.ts b/test/__mocks__/get.company.psc.statement.mock.ts new file mode 100644 index 000000000..948f39e01 --- /dev/null +++ b/test/__mocks__/get.company.psc.statement.mock.ts @@ -0,0 +1,44 @@ +import { ApiErrorResponse, ApiResponse } from "@companieshouse/api-sdk-node/dist/services/resource"; +import { + CompanyPersonsWithSignificantControlStatementsResource +} from "@companieshouse/api-sdk-node/dist/services/company-psc-statements"; +import { ANY_MESSAGE_ERROR } from "./text.mock"; + +const NO_INDIVIDUAL_STATEMENT_MOCK = { + "links": { + "self": "/company/OE000001/persons-with-significant-control-statements/123" + }, + "notified_on": "2025-01-01T00:00:10.100Z", + "etag": "1234", + "kind": "persons-with-significant-control-statement", + "statement": "no-individual-or-entity-with-signficant-control" +}; + +export const MOCK_GET_COMPANY_PSC_STATEMENTS_RESOURCE_INDIVIDUAL = { + "active_count": '1', + "ceased_count": '', + "items": [ + NO_INDIVIDUAL_STATEMENT_MOCK + ], + "items_per_page": '25', + "links": { + "self": "/company/OE000001/persons-with-significant-control-statements" + }, + "start_index": '0', + "total_results": '1' +}; + +export const MOCK_GET_COMPANY_PSC_STATEMENTS_RESPONSE: ApiResponse = { + httpStatusCode: 200, + resource: MOCK_GET_COMPANY_PSC_STATEMENTS_RESOURCE_INDIVIDUAL +}; + +export const MOCK_GET_COMPANY_PSC_STATEMENTS_UNAUTHORISED_RESPONSE: ApiErrorResponse = { + httpStatusCode: 401, + errors: [ { error: ANY_MESSAGE_ERROR }] +}; + +export const MOCK_GET_COMPANY_PSC_STATEMENTS_NOT_FOUND_RESPONSE: ApiErrorResponse = { + httpStatusCode: 404, + errors: [ { error: ANY_MESSAGE_ERROR }] +}; diff --git a/test/__mocks__/session.mock.ts b/test/__mocks__/session.mock.ts index d125ba131..3a07c760c 100644 --- a/test/__mocks__/session.mock.ts +++ b/test/__mocks__/session.mock.ts @@ -2444,6 +2444,10 @@ export const UPDATE_REVIEW_INDIVIDUAL_MANAGING_OFFICER_WITH_PARAM_URL_TEST = `${ export const serviceNameGetCompanyPsc = "companyPsc"; export const fnNameGetCompanyPsc = "getCompanyPsc"; +// get company psc statements mocks +export const serviceNameGetCompanyPscStatements = "companyPscStatements"; +export const fnNameGetCompanyPscStatements = "getCompanyPscStatements"; + export const RESET_DATA_FOR_CHANGE_RESPONSE = { [PaymentKey]: undefined, [beneficialOwnerStatementType.BeneficialOwnerStatementKey]: undefined, diff --git a/test/service/persons.with.significant.control.statement.service.spec.ts b/test/service/persons.with.significant.control.statement.service.spec.ts new file mode 100644 index 000000000..ac36ba692 --- /dev/null +++ b/test/service/persons.with.significant.control.statement.service.spec.ts @@ -0,0 +1,67 @@ +jest.mock("../../src/utils/logger"); +jest.mock("../../src/utils/application.data"); +jest.mock("../../src/service/retry.handler.service"); + +import { describe, expect, test, jest, beforeEach } from "@jest/globals"; +import { Request } from "express"; + +import { createAndLogErrorRequest, logger } from "../../src/utils/logger"; +import { makeApiCallWithRetry } from "../../src/service/retry.handler.service"; +import { + serviceNameGetCompanyPscStatements, + fnNameGetCompanyPscStatements, + COMPANY_NUMBER, + ERROR, + getSessionRequestWithExtraData, +} from "../__mocks__/session.mock"; +import { + MOCK_GET_COMPANY_PSC_STATEMENTS_NOT_FOUND_RESPONSE, + MOCK_GET_COMPANY_PSC_STATEMENTS_RESPONSE, + MOCK_GET_COMPANY_PSC_STATEMENTS_UNAUTHORISED_RESPONSE, + MOCK_GET_COMPANY_PSC_STATEMENTS_RESOURCE_INDIVIDUAL +} from "../__mocks__/get.company.psc.statement.mock"; +import { getCompanyPscStatements } from "../../src/service/persons.with.signficant.control.statement.service"; + +const mockDebugRequestLog = logger.debugRequest as jest.Mock; + +const mockCreateAndLogErrorRequest = createAndLogErrorRequest as jest.Mock; +mockCreateAndLogErrorRequest.mockReturnValue(ERROR); + +const mockMakeApiCallWithRetry = makeApiCallWithRetry as jest.Mock; + +const session = getSessionRequestWithExtraData(); +const req: Request = { session } as Request; +describe('Get persons with significant control statement service that calls API for given company number', () => { + beforeEach (() => { + jest.clearAllMocks(); + }); + + test('data returned on 200 response from API', async () => { + mockMakeApiCallWithRetry.mockResolvedValueOnce(MOCK_GET_COMPANY_PSC_STATEMENTS_RESPONSE); + + const resource = await getCompanyPscStatements(req, COMPANY_NUMBER); + + expect(mockMakeApiCallWithRetry).toBeCalledWith(serviceNameGetCompanyPscStatements, fnNameGetCompanyPscStatements, req, session, COMPANY_NUMBER); + expect(mockCreateAndLogErrorRequest).not.toHaveBeenCalled(); + expect(mockDebugRequestLog).toHaveBeenCalled(); + expect(resource).toEqual(MOCK_GET_COMPANY_PSC_STATEMENTS_RESOURCE_INDIVIDUAL); + }); + + test('logs error on 401 response from API', async () => { + mockMakeApiCallWithRetry.mockResolvedValueOnce(MOCK_GET_COMPANY_PSC_STATEMENTS_UNAUTHORISED_RESPONSE); + + await expect(getCompanyPscStatements(req, COMPANY_NUMBER)).rejects.toThrow(ERROR); + + expect(mockCreateAndLogErrorRequest).toHaveBeenCalled(); + expect(mockDebugRequestLog).not.toHaveBeenCalled(); + }); + + test('undefined returned on 404 response from API', async () => { + mockMakeApiCallWithRetry.mockResolvedValueOnce(MOCK_GET_COMPANY_PSC_STATEMENTS_NOT_FOUND_RESPONSE); + + const resource = await getCompanyPscStatements(req, COMPANY_NUMBER); + expect(resource).toEqual(undefined); + expect(mockCreateAndLogErrorRequest).not.toHaveBeenCalled(); + expect(mockDebugRequestLog).toHaveBeenCalled(); + }); +});