Skip to content

Commit 4274fdb

Browse files
author
Zain Kassam
committed
Merge branch 'main' into feat/FN-3819
2 parents de1388a + 3c2fc50 commit 4274fdb

File tree

71 files changed

+3500
-530
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+3500
-530
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ env:
169169
ENTRA_ID_REDIRECT_URL: ${{ vars.ENTRA_ID_REDIRECT_URL }}
170170
DEAL_CANCELLATION_SCHEDULE: ${{ vars.DEAL_CANCELLATION_SCHEDULE }}
171171
RECORD_CORRECTION_TRANSIENT_FORM_DATA_DELETE_SCHEDULE: ${{ vars.RECORD_CORRECTION_TRANSIENT_FORM_DATA_DELETE_SCHEDULE }}
172+
UKEF_GEF_REPORTING_EMAIL_RECIPIENT: ${{ secrets.UKEF_GEF_REPORTING_EMAIL_RECIPIENT }}
172173

173174
jobs:
174175
# 1. Setup test infrastructure

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ services:
8989
- FF_TFM_DEAL_CANCELLATION_ENABLED
9090
- DEAL_CANCELLATION_SCHEDULE
9191
- FF_PORTAL_FACILITY_AMENDMENTS_ENABLED
92+
- UKEF_GEF_REPORTING_EMAIL_RECIPIENT
93+
- TFM_UI_URL=http://localhost:5003
9294
- RECORD_CORRECTION_TRANSIENT_FORM_DATA_DELETE_SCHEDULE
9395

9496
trade-finance-manager-ui:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { HttpStatusCode } from 'axios';
2+
import {
3+
Bank,
4+
FEE_RECORD_STATUS,
5+
FeeRecordCorrectionEntityMockBuilder,
6+
FeeRecordEntityMockBuilder,
7+
RECONCILIATION_IN_PROGRESS,
8+
RECORD_CORRECTION_REASON,
9+
UtilisationReportEntityMockBuilder,
10+
} from '@ukef/dtfs2-common';
11+
import { testApi } from '../../../test-api';
12+
import { SqlDbHelper } from '../../../sql-db-helper';
13+
import { aBank } from '../../../../test-helpers';
14+
import { mongoDbClient } from '../../../../src/drivers/db-client';
15+
import { wipe } from '../../../wipeDB';
16+
import { replaceUrlParameterPlaceholders } from '../../../../test-helpers/replace-url-parameter-placeholders';
17+
18+
console.error = jest.fn();
19+
20+
const BASE_URL = '/v1/bank/:bankId/utilisation-reports/completed-corrections';
21+
22+
describe(`GET ${BASE_URL}`, () => {
23+
const bankId = '123';
24+
const bank: Bank = {
25+
...aBank(),
26+
id: bankId,
27+
};
28+
29+
const report = UtilisationReportEntityMockBuilder.forStatus(RECONCILIATION_IN_PROGRESS).withBankId(bankId).build();
30+
const feeRecord = FeeRecordEntityMockBuilder.forReport(report).withExporter('An exporter').withStatus(FEE_RECORD_STATUS.TO_DO_AMENDED).build();
31+
report.feeRecords = [feeRecord];
32+
33+
beforeAll(async () => {
34+
await SqlDbHelper.initialize();
35+
await SqlDbHelper.deleteAllEntries('UtilisationReport');
36+
await wipe(['banks']);
37+
38+
const banksCollection = await mongoDbClient.getCollection('banks');
39+
await banksCollection.insertOne(bank);
40+
41+
await SqlDbHelper.saveNewEntries('UtilisationReport', [report]);
42+
});
43+
44+
afterEach(async () => {
45+
await SqlDbHelper.deleteAllEntries('FeeRecordCorrection');
46+
});
47+
48+
afterAll(async () => {
49+
await SqlDbHelper.deleteAllEntries('UtilisationReport');
50+
await wipe(['banks']);
51+
});
52+
53+
it(`should return '${HttpStatusCode.Ok}' and the completed fee record corrections response`, async () => {
54+
// Arrange
55+
const dateCorrectionReceived = new Date('2024-01-01');
56+
const oldFacilityId = feeRecord.facilityId;
57+
const newFacilityId = '12345678';
58+
59+
const feeRecordCorrection = FeeRecordCorrectionEntityMockBuilder.forFeeRecordAndIsCompleted(feeRecord, true)
60+
.withId(1)
61+
.withDateReceived(dateCorrectionReceived)
62+
.withReasons([RECORD_CORRECTION_REASON.FACILITY_ID_INCORRECT, RECORD_CORRECTION_REASON.OTHER])
63+
.withPreviousValues({
64+
facilityId: oldFacilityId,
65+
})
66+
.withCorrectedValues({
67+
facilityId: newFacilityId,
68+
})
69+
.withBankCommentary('Some bank commentary')
70+
.build();
71+
72+
await SqlDbHelper.saveNewEntry('FeeRecordCorrection', feeRecordCorrection);
73+
74+
// Act
75+
const response = await testApi.get(replaceUrlParameterPlaceholders(BASE_URL, { bankId }));
76+
77+
// Assert
78+
expect(response.status).toEqual(HttpStatusCode.Ok);
79+
80+
const expectedMappedCompletedCorrections = [
81+
{
82+
id: feeRecordCorrection.id,
83+
dateSent: dateCorrectionReceived.toISOString(),
84+
exporter: feeRecord.exporter,
85+
formattedReasons: 'Facility ID is incorrect, Other',
86+
formattedPreviousValues: `${oldFacilityId}, -`,
87+
formattedCorrectedValues: `${newFacilityId}, -`,
88+
bankCommentary: feeRecordCorrection.bankCommentary,
89+
},
90+
];
91+
92+
expect(response.body).toEqual(expectedMappedCompletedCorrections);
93+
});
94+
95+
it(`should return '${HttpStatusCode.Ok}' and an empty array when no completed fee record corrections with the supplied bank id can be found`, async () => {
96+
// Arrange
97+
const feeRecordCorrection = FeeRecordCorrectionEntityMockBuilder.forFeeRecordAndIsCompleted(feeRecord, true).build();
98+
99+
await SqlDbHelper.saveNewEntry('FeeRecordCorrection', feeRecordCorrection);
100+
101+
// Act
102+
const response = await testApi.get(replaceUrlParameterPlaceholders(BASE_URL, { bankId: `${bankId}123` }));
103+
104+
// Assert
105+
expect(response.status).toEqual(HttpStatusCode.Ok);
106+
107+
expect(response.body).toEqual([]);
108+
});
109+
});

dtfs-central-api/api-tests/v1/utilisation-reports/fee-record-corrections/put-fee-record-correction.api-test.ts

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { HttpStatusCode } from 'axios';
22
import { Response } from 'supertest';
33
import {
44
FEE_RECORD_STATUS,
5+
FeeRecordCorrectionEntity,
56
FeeRecordCorrectionEntityMockBuilder,
67
FeeRecordCorrectionTransientFormDataEntity,
78
FeeRecordCorrectionTransientFormDataEntityMockBuilder,
9+
FeeRecordEntity,
810
FeeRecordEntityMockBuilder,
911
RECONCILIATION_IN_PROGRESS,
12+
RECORD_CORRECTION_REASON,
1013
ReportPeriod,
1114
UtilisationReportEntityMockBuilder,
1215
} from '@ukef/dtfs2-common';
@@ -33,12 +36,13 @@ const BASE_URL = '/v1/bank/:bankId/fee-record-corrections/:correctionId';
3336

3437
describe(`PUT ${BASE_URL}`, () => {
3538
const bankId = '1';
39+
const feeRecordId = 1;
3640
const correctionId = 2;
3741
const userId = new ObjectId().toString();
3842

3943
const reportPeriod = { start: { month: 3, year: 2023 }, end: { month: 4, year: 2023 } };
4044

41-
const paymentOfficerTeamEmails = ['email1@ukexportfinance.gov.uk'];
45+
const paymentOfficerTeamEmails = ['payment-officer1@ukexportfinance.gov.uk'];
4246

4347
const mockBank = {
4448
...aBank(),
@@ -53,6 +57,11 @@ describe(`PUT ${BASE_URL}`, () => {
5357
user: { _id: userId },
5458
});
5559

60+
const reasons = [RECORD_CORRECTION_REASON.FACILITY_ID_INCORRECT];
61+
62+
const incorrectFacilityId = '11111111';
63+
const correctFacilityId = '22222222';
64+
5665
beforeAll(async () => {
5766
await SqlDbHelper.initialize();
5867
await wipeDB.wipe(['banks']);
@@ -68,16 +77,24 @@ describe(`PUT ${BASE_URL}`, () => {
6877

6978
const report = UtilisationReportEntityMockBuilder.forStatus(RECONCILIATION_IN_PROGRESS).withBankId(bankId).withReportPeriod(reportPeriod).build();
7079

71-
const feeRecord = FeeRecordEntityMockBuilder.forReport(report).withStatus(FEE_RECORD_STATUS.PENDING_CORRECTION).build();
80+
const feeRecord = FeeRecordEntityMockBuilder.forReport(report)
81+
.withId(feeRecordId)
82+
.withStatus(FEE_RECORD_STATUS.PENDING_CORRECTION)
83+
.withFacilityId(incorrectFacilityId)
84+
.build();
7285

73-
const correction = FeeRecordCorrectionEntityMockBuilder.forFeeRecordAndIsCompleted(feeRecord, false).withId(correctionId).build();
86+
const correction = FeeRecordCorrectionEntityMockBuilder.forFeeRecordAndIsCompleted(feeRecord, false).withId(correctionId).withReasons(reasons).build();
7487

7588
feeRecord.corrections = [correction];
7689
report.feeRecords = [feeRecord];
7790

7891
await SqlDbHelper.saveNewEntry('UtilisationReport', report);
7992

80-
const formData = new FeeRecordCorrectionTransientFormDataEntityMockBuilder().withCorrectionId(correctionId).withUserId(userId).build();
93+
const formData = new FeeRecordCorrectionTransientFormDataEntityMockBuilder()
94+
.withCorrectionId(correctionId)
95+
.withUserId(userId)
96+
.withFormData({ facilityId: correctFacilityId })
97+
.build();
8198

8299
await SqlDbHelper.saveNewEntry('FeeRecordCorrectionTransientFormData', formData);
83100
});
@@ -149,6 +166,50 @@ describe(`PUT ${BASE_URL}`, () => {
149166
expect(status).toEqual(HttpStatusCode.Ok);
150167
});
151168

169+
it(`should update the fee record with corrected values and set status to ${FEE_RECORD_STATUS.TO_DO_AMENDED}`, async () => {
170+
// Arrange
171+
const requestBody = aValidRequestBody();
172+
173+
// Act
174+
await testApi.put(requestBody).to(replaceUrlParameterPlaceholders(BASE_URL, { bankId, correctionId }));
175+
176+
// Assert
177+
const feeRecord = await SqlDbHelper.manager.findOneBy(FeeRecordEntity, { id: feeRecordId });
178+
expect(feeRecord?.facilityId).toEqual(correctFacilityId);
179+
expect(feeRecord?.status).toEqual(FEE_RECORD_STATUS.TO_DO_AMENDED);
180+
});
181+
182+
it('should save the previous and corrected values on the correction and complete it', async () => {
183+
// Arrange
184+
const requestBody = aValidRequestBody();
185+
186+
// Act
187+
await testApi.put(requestBody).to(replaceUrlParameterPlaceholders(BASE_URL, { bankId, correctionId }));
188+
189+
// Assert
190+
const correction = await SqlDbHelper.manager.findOneBy(FeeRecordCorrectionEntity, { id: correctionId });
191+
192+
const expectedPreviousValues = {
193+
facilityId: incorrectFacilityId,
194+
feesPaidToUkefForThePeriod: null,
195+
feesPaidToUkefForThePeriodCurrency: null,
196+
facilityUtilisation: null,
197+
};
198+
199+
expect(correction?.previousValues).toEqual(expectedPreviousValues);
200+
201+
const expectedCorrectedValues = {
202+
facilityId: correctFacilityId,
203+
feesPaidToUkefForThePeriod: null,
204+
feesPaidToUkefForThePeriodCurrency: null,
205+
facilityUtilisation: null,
206+
};
207+
208+
expect(correction?.correctedValues).toEqual(expectedCorrectedValues);
209+
210+
expect(correction?.isCompleted).toEqual(true);
211+
});
212+
152213
it('should delete the transient form data', async () => {
153214
// Arrange
154215
const requestBody = aValidRequestBody();
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
const REPORT_RECONCILED = 'f6a10d2f-a1bb-4640-9bf0-0699ef442551';
22
const FEE_RECORD_CORRECTION_REQUEST = 'c32528aa-4e12-43c1-9ff0-11f327513b9e';
3+
const FEE_RECORD_CORRECTION_RECEIVED_BANK_NOTIFICATION = 'c60489c5-a2e8-4100-a63a-3f5e691bdb20';
4+
const FEE_RECORD_CORRECTION_RECEIVED_UKEF_NOTIFICATION = '2af491e6-2968-4476-8db9-74202138dfad';
35
const REPORT_INSERTION_CRON_FAILURE = 'a8a2b0db-67a8-409b-b8b7-7104b137acfd';
46

5-
export default { REPORT_RECONCILED, FEE_RECORD_CORRECTION_REQUEST, REPORT_INSERTION_CRON_FAILURE };
7+
export default {
8+
REPORT_RECONCILED,
9+
FEE_RECORD_CORRECTION_REQUEST,
10+
FEE_RECORD_CORRECTION_RECEIVED_BANK_NOTIFICATION,
11+
FEE_RECORD_CORRECTION_RECEIVED_UKEF_NOTIFICATION,
12+
REPORT_INSERTION_CRON_FAILURE,
13+
};

dtfs-central-api/src/helpers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export { calculateUkefShareOfUtilisation } from './calculate-ukef-share-of-utili
1212
export { getKeyingSheetCalculationFacilityValues } from './get-keying-sheet-calculation-facility-values';
1313
export { getCorrectionPreviousValuesFromFeeRecord } from './get-correction-previous-values-from-fee-record';
1414
export { getCorrectionCorrectedValuesFromFormData } from './get-correction-corrected-values-from-form-data';
15+
export { validateRequiredCorrectionField } from './validate-required-correction-field';
1516
export * from './amendments';

0 commit comments

Comments
 (0)