@defra-fish/sales-api-service 1.60.0-rc.3 → 1.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/sales-api-service",
|
|
3
|
-
"version": "1.60.0
|
|
3
|
+
"version": "1.60.0",
|
|
4
4
|
"description": "Rod Licensing Sales API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@defra-fish/business-rules-lib": "1.60.0
|
|
39
|
-
"@defra-fish/connectors-lib": "1.60.0
|
|
40
|
-
"@defra-fish/dynamics-lib": "1.60.0
|
|
38
|
+
"@defra-fish/business-rules-lib": "1.60.0",
|
|
39
|
+
"@defra-fish/connectors-lib": "1.60.0",
|
|
40
|
+
"@defra-fish/dynamics-lib": "1.60.0",
|
|
41
41
|
"@hapi/boom": "^9.1.2",
|
|
42
42
|
"@hapi/hapi": "^20.1.3",
|
|
43
43
|
"@hapi/inert": "^6.0.3",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"moment-timezone": "^0.5.34",
|
|
53
53
|
"uuid": "^8.3.2"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "417b6030d76dace0415cf9b4d1e7cddecb93df99"
|
|
56
56
|
}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { getRecurringPayments } from '../../../services/recurring-payments.service.js'
|
|
1
|
+
import recurringPayments from '../recurring-payments.js'
|
|
2
|
+
import { getRecurringPayments, processRPResult } from '../../../services/recurring-payments.service.js'
|
|
3
3
|
|
|
4
4
|
const [
|
|
5
5
|
{
|
|
6
6
|
options: { handler: drpHandler }
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
options: { handler: prpHandler }
|
|
7
10
|
}
|
|
8
|
-
] =
|
|
11
|
+
] = recurringPayments
|
|
9
12
|
|
|
10
13
|
jest.mock('../../../services/recurring-payments.service.js', () => ({
|
|
11
|
-
getRecurringPayments: jest.fn()
|
|
14
|
+
getRecurringPayments: jest.fn(),
|
|
15
|
+
processRPResult: jest.fn()
|
|
12
16
|
}))
|
|
13
17
|
|
|
14
|
-
const getMockRequest = ({
|
|
15
|
-
|
|
18
|
+
const getMockRequest = ({
|
|
19
|
+
date = '2023-10-19',
|
|
20
|
+
transactionId = 'transaction-id',
|
|
21
|
+
paymentId = 'payment-id',
|
|
22
|
+
createdDate = 'created-date'
|
|
23
|
+
}) => ({
|
|
24
|
+
params: { date, transactionId, paymentId, createdDate }
|
|
16
25
|
})
|
|
17
26
|
|
|
18
27
|
const getMockResponseToolkit = () => ({
|
|
@@ -22,16 +31,35 @@ const getMockResponseToolkit = () => ({
|
|
|
22
31
|
describe('recurring payments', () => {
|
|
23
32
|
beforeEach(jest.clearAllMocks)
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
describe('dueRecurringPayments', () => {
|
|
35
|
+
it('handler should return continue response', async () => {
|
|
36
|
+
const request = getMockRequest({})
|
|
37
|
+
const responseToolkit = getMockResponseToolkit()
|
|
38
|
+
expect(await drpHandler(request, responseToolkit)).toEqual(responseToolkit.continue)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should call getRecurringPayments with date', async () => {
|
|
42
|
+
const date = Symbol('date')
|
|
43
|
+
const request = getMockRequest({ date })
|
|
44
|
+
await drpHandler(request, getMockResponseToolkit())
|
|
45
|
+
expect(getRecurringPayments).toHaveBeenCalledWith(date)
|
|
46
|
+
})
|
|
29
47
|
})
|
|
30
48
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
describe('processRPResult', () => {
|
|
50
|
+
it('handler should return continue response', async () => {
|
|
51
|
+
const request = getMockRequest({})
|
|
52
|
+
const responseToolkit = getMockResponseToolkit()
|
|
53
|
+
expect(await prpHandler(request, responseToolkit)).toEqual(responseToolkit.continue)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should call processRPResult with transaction id, payment id and createdDate', async () => {
|
|
57
|
+
const transactionId = Symbol('transaction-id')
|
|
58
|
+
const paymentId = Symbol('payment-id')
|
|
59
|
+
const createdDate = Symbol('created-date')
|
|
60
|
+
const request = getMockRequest({ transactionId, paymentId, createdDate })
|
|
61
|
+
await prpHandler(request, getMockResponseToolkit())
|
|
62
|
+
expect(processRPResult).toHaveBeenCalledWith(transactionId, paymentId, createdDate)
|
|
63
|
+
})
|
|
36
64
|
})
|
|
37
65
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { dueRecurringPaymentsResponseSchema } from '../../schema/recurring-payments.schema.js'
|
|
2
|
-
import { getRecurringPayments } from '../../services/recurring-payments.service.js'
|
|
2
|
+
import { getRecurringPayments, processRPResult } from '../../services/recurring-payments.service.js'
|
|
3
|
+
|
|
3
4
|
export default [
|
|
4
5
|
{
|
|
5
6
|
method: 'GET',
|
|
@@ -21,5 +22,26 @@ export default [
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
method: 'GET',
|
|
28
|
+
path: '/processRPResult/{transactionId}/{paymentId}/{createdDate}',
|
|
29
|
+
options: {
|
|
30
|
+
handler: async (request, h) => {
|
|
31
|
+
const { transactionId, paymentId, createdDate } = request.params
|
|
32
|
+
const result = await processRPResult(transactionId, paymentId, createdDate)
|
|
33
|
+
return h.response(result)
|
|
34
|
+
},
|
|
35
|
+
description: 'Generate a permission from a recurring payment record',
|
|
36
|
+
tags: ['api', 'recurring-payments'],
|
|
37
|
+
plugins: {
|
|
38
|
+
'hapi-swagger': {
|
|
39
|
+
responses: {
|
|
40
|
+
200: { description: 'New permission from recurring payment record generated successfully' }
|
|
41
|
+
},
|
|
42
|
+
order: 2
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
24
46
|
}
|
|
25
47
|
]
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { findDueRecurringPayments, Permission } from '@defra-fish/dynamics-lib'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getRecurringPayments,
|
|
4
|
+
processRecurringPayment,
|
|
5
|
+
generateRecurringPaymentRecord,
|
|
6
|
+
processRPResult
|
|
7
|
+
} from '../recurring-payments.service.js'
|
|
8
|
+
import { calculateEndDate, generatePermissionNumber } from '../permissions.service.js'
|
|
9
|
+
import { getObfuscatedDob } from '../contacts.service.js'
|
|
3
10
|
import { createHash } from 'node:crypto'
|
|
11
|
+
import { AWS } from '@defra-fish/connectors-lib'
|
|
12
|
+
import { TRANSACTION_STAGING_TABLE, TRANSACTION_QUEUE } from '../../config.js'
|
|
13
|
+
import { TRANSACTION_STATUS } from '../../services/transactions/constants.js'
|
|
14
|
+
import { retrieveStagedTransaction } from '../../services/transactions/retrieve-transaction.js'
|
|
15
|
+
import { createPaymentJournal, getPaymentJournal, updatePaymentJournal } from '../../services/paymentjournals/payment-journals.service.js'
|
|
16
|
+
import { PAYMENT_JOURNAL_STATUS_CODES, TRANSACTION_SOURCE, PAYMENT_TYPE } from '@defra-fish/business-rules-lib'
|
|
17
|
+
const AWSMocks = {}
|
|
4
18
|
|
|
5
19
|
jest.mock('@defra-fish/dynamics-lib', () => ({
|
|
6
20
|
...jest.requireActual('@defra-fish/dynamics-lib'),
|
|
@@ -9,6 +23,15 @@ jest.mock('@defra-fish/dynamics-lib', () => ({
|
|
|
9
23
|
findDueRecurringPayments: jest.fn()
|
|
10
24
|
}))
|
|
11
25
|
|
|
26
|
+
jest.mock('@defra-fish/connectors-lib', () => {
|
|
27
|
+
const realConnectors = jest.requireActual('@defra-fish/connectors-lib')
|
|
28
|
+
return {
|
|
29
|
+
...realConnectors,
|
|
30
|
+
AWS: jest.fn(() => realConnectors.AWS()),
|
|
31
|
+
receiver: jest.fn()
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
12
35
|
jest.mock('node:crypto', () => ({
|
|
13
36
|
createHash: jest.fn(() => ({
|
|
14
37
|
update: () => {},
|
|
@@ -16,6 +39,42 @@ jest.mock('node:crypto', () => ({
|
|
|
16
39
|
}))
|
|
17
40
|
}))
|
|
18
41
|
|
|
42
|
+
jest.mock('../contacts.service.js', () => ({
|
|
43
|
+
getObfuscatedDob: jest.fn()
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
jest.mock('../permissions.service.js', () => ({
|
|
47
|
+
calculateEndDate: jest.fn(),
|
|
48
|
+
generatePermissionNumber: jest.fn()
|
|
49
|
+
}))
|
|
50
|
+
|
|
51
|
+
jest.mock('../../services/transactions/retrieve-transaction.js', () => ({
|
|
52
|
+
retrieveStagedTransaction: jest.fn()
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
jest.mock('../../services/paymentjournals/payment-journals.service.js', () => ({
|
|
56
|
+
createPaymentJournal: jest.fn(),
|
|
57
|
+
getPaymentJournal: jest.fn(),
|
|
58
|
+
updatePaymentJournal: jest.fn()
|
|
59
|
+
}))
|
|
60
|
+
|
|
61
|
+
jest.mock('@defra-fish/business-rules-lib', () => ({
|
|
62
|
+
ADVANCED_PURCHASE_MAX_DAYS: 30,
|
|
63
|
+
PAYMENT_JOURNAL_STATUS_CODES: {
|
|
64
|
+
InProgress: 'InProgressCode',
|
|
65
|
+
Cancelled: 'CancelledCode',
|
|
66
|
+
Failed: 'FailedCode',
|
|
67
|
+
Expired: 'ExpiredCode',
|
|
68
|
+
Completed: 'CompletedCode'
|
|
69
|
+
},
|
|
70
|
+
TRANSACTION_SOURCE: {
|
|
71
|
+
govPay: Symbol('govpay')
|
|
72
|
+
},
|
|
73
|
+
PAYMENT_TYPE: {
|
|
74
|
+
debit: Symbol('debit')
|
|
75
|
+
}
|
|
76
|
+
}))
|
|
77
|
+
|
|
19
78
|
const dynamicsLib = jest.requireMock('@defra-fish/dynamics-lib')
|
|
20
79
|
|
|
21
80
|
const getMockRecurringPayment = () => ({
|
|
@@ -88,6 +147,21 @@ const getMockPermission = () => ({
|
|
|
88
147
|
}
|
|
89
148
|
})
|
|
90
149
|
|
|
150
|
+
const getMockTransaction = (id = 'test-id') => ({
|
|
151
|
+
id,
|
|
152
|
+
dataSource: 'RCP',
|
|
153
|
+
permissions: [
|
|
154
|
+
{
|
|
155
|
+
issueDate: new Date('2024-01-01'),
|
|
156
|
+
startDate: new Date('2024-01-01'),
|
|
157
|
+
licensee: {
|
|
158
|
+
firstName: 'Test',
|
|
159
|
+
lastName: 'User'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
})
|
|
164
|
+
|
|
91
165
|
describe('recurring payments service', () => {
|
|
92
166
|
const createSimpleSampleTransactionRecord = () => ({ payment: { recurring: true }, permissions: [{}] })
|
|
93
167
|
const createSamplePermission = overrides => {
|
|
@@ -106,6 +180,19 @@ describe('recurring payments service', () => {
|
|
|
106
180
|
}
|
|
107
181
|
|
|
108
182
|
beforeEach(jest.clearAllMocks)
|
|
183
|
+
beforeAll(() => {
|
|
184
|
+
TRANSACTION_QUEUE.Url = 'TestUrl'
|
|
185
|
+
TRANSACTION_STAGING_TABLE.TableName = 'TestTable'
|
|
186
|
+
const [
|
|
187
|
+
{
|
|
188
|
+
value: { docClient, sqs }
|
|
189
|
+
}
|
|
190
|
+
] = AWS.mock.results
|
|
191
|
+
AWSMocks.docClient = docClient
|
|
192
|
+
AWSMocks.sqs = sqs
|
|
193
|
+
Object.freeze(AWSMocks)
|
|
194
|
+
})
|
|
195
|
+
|
|
109
196
|
describe('getRecurringPayments', () => {
|
|
110
197
|
it('should equal result of findDueRecurringPayments query', async () => {
|
|
111
198
|
const mockRecurringPayments = [getMockRecurringPayment()]
|
|
@@ -339,4 +426,197 @@ describe('recurring payments service', () => {
|
|
|
339
426
|
expect(rpRecord.payment.recurring).toBeFalsy()
|
|
340
427
|
})
|
|
341
428
|
})
|
|
429
|
+
|
|
430
|
+
describe.each(['abc-123', 'hyt678iuhy78uijhgtrfg', 'jhu7i8u7yh-jhu78u'])('processRPResult with transaction id %s', transactionId => {
|
|
431
|
+
beforeEach(() => {
|
|
432
|
+
jest.useFakeTimers().setSystemTime(new Date('2024-03-12T09:57:23.745Z'))
|
|
433
|
+
})
|
|
434
|
+
afterEach(() => {
|
|
435
|
+
jest.useRealTimers()
|
|
436
|
+
})
|
|
437
|
+
it('should call retrieveStagedTransaction with transaction id', async () => {
|
|
438
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
439
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
440
|
+
await processRPResult(transactionId, '123', '2025-01-01')
|
|
441
|
+
|
|
442
|
+
expect(retrieveStagedTransaction).toHaveBeenCalledWith(transactionId)
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
it('should call await getPaymentJournal with transaction id', async () => {
|
|
446
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
447
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
448
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
449
|
+
|
|
450
|
+
expect(retrieveStagedTransaction).toHaveBeenCalledWith(mockTransaction.id)
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('if getPaymentJournal is true then updatePaymentJournal is called with expected params', async () => {
|
|
454
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
455
|
+
const paymentId = Symbol('payment-id')
|
|
456
|
+
const createdDate = Symbol('created-date')
|
|
457
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
458
|
+
getPaymentJournal.mockResolvedValueOnce(true)
|
|
459
|
+
const expctedParams = {
|
|
460
|
+
paymentReference: paymentId,
|
|
461
|
+
paymentTimestamp: createdDate,
|
|
462
|
+
paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.InProgress
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
await processRPResult(mockTransaction.id, paymentId, createdDate)
|
|
466
|
+
|
|
467
|
+
expect(updatePaymentJournal).toHaveBeenCalledWith(mockTransaction.id, expctedParams)
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
it('if getPaymentJournal is false then updatePaymentJournal is not called', async () => {
|
|
471
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
472
|
+
const paymentId = Symbol('payment-id')
|
|
473
|
+
const createdDate = Symbol('created-date')
|
|
474
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
475
|
+
getPaymentJournal.mockResolvedValueOnce(false)
|
|
476
|
+
|
|
477
|
+
await processRPResult(mockTransaction.id, paymentId, createdDate)
|
|
478
|
+
|
|
479
|
+
expect(updatePaymentJournal).not.toHaveBeenCalled()
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
it('if getPaymentJournal is false then createPaymentJournal is called with expected params', async () => {
|
|
483
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
484
|
+
const paymentId = Symbol('payment-id')
|
|
485
|
+
const createdDate = Symbol('created-date')
|
|
486
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
487
|
+
getPaymentJournal.mockResolvedValueOnce(false)
|
|
488
|
+
const expctedParams = {
|
|
489
|
+
paymentReference: paymentId,
|
|
490
|
+
paymentTimestamp: createdDate,
|
|
491
|
+
paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.InProgress
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
await processRPResult(mockTransaction.id, paymentId, createdDate)
|
|
495
|
+
|
|
496
|
+
expect(createPaymentJournal).toHaveBeenCalledWith(mockTransaction.id, expctedParams)
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
it('if getPaymentJournal is true then createPaymentJournal is not called', async () => {
|
|
500
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
501
|
+
const paymentId = Symbol('payment-id')
|
|
502
|
+
const createdDate = Symbol('created-date')
|
|
503
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
504
|
+
getPaymentJournal.mockResolvedValueOnce(true)
|
|
505
|
+
|
|
506
|
+
await processRPResult(mockTransaction.id, paymentId, createdDate)
|
|
507
|
+
|
|
508
|
+
expect(createPaymentJournal).not.toHaveBeenCalled()
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
it('should call calculateEndDate with permission', async () => {
|
|
512
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
513
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
514
|
+
const {
|
|
515
|
+
permissions: [permission]
|
|
516
|
+
} = mockTransaction
|
|
517
|
+
|
|
518
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
519
|
+
|
|
520
|
+
expect(calculateEndDate).toHaveBeenCalledWith(permission)
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
it('should call generatePermissionNumber with permission and data source', async () => {
|
|
524
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
525
|
+
mockTransaction.dataSource = Symbol('data-source')
|
|
526
|
+
const {
|
|
527
|
+
permissions: [permission]
|
|
528
|
+
} = mockTransaction
|
|
529
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
530
|
+
|
|
531
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
532
|
+
|
|
533
|
+
expect(generatePermissionNumber).toHaveBeenCalledWith(permission, mockTransaction.dataSource)
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
it('should call getObfuscatedDob with licensee', async () => {
|
|
537
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
538
|
+
const {
|
|
539
|
+
permissions: [permission]
|
|
540
|
+
} = mockTransaction
|
|
541
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
542
|
+
|
|
543
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
544
|
+
|
|
545
|
+
expect(getObfuscatedDob).toHaveBeenCalledWith(permission.licensee)
|
|
546
|
+
})
|
|
547
|
+
|
|
548
|
+
it('should call AWSMocks.docClient.createUpdateExpression with payload, permissions, status and payment details', async () => {
|
|
549
|
+
jest.spyOn(AWSMocks.docClient, 'createUpdateExpression')
|
|
550
|
+
const fakeNow = '2024-03-19T14:09:00.000Z'
|
|
551
|
+
jest.setSystemTime(new Date(fakeNow))
|
|
552
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
553
|
+
const permission = {
|
|
554
|
+
issueDate: fakeNow,
|
|
555
|
+
dataSource: 'RCP',
|
|
556
|
+
licensee: {
|
|
557
|
+
firstName: 'Brenin',
|
|
558
|
+
lastName: 'Pysgotwr',
|
|
559
|
+
obfuscatedDob: '987654678'
|
|
560
|
+
},
|
|
561
|
+
startDate: '2025-03-19T00:00:00.000Z'
|
|
562
|
+
}
|
|
563
|
+
const expectedPermission = {
|
|
564
|
+
...permission,
|
|
565
|
+
startDate: '2025-03-19T00:00:00.000Z',
|
|
566
|
+
endDate: '2026-03-18T23:59:59.999Z',
|
|
567
|
+
referenceNumber: '123abc'
|
|
568
|
+
}
|
|
569
|
+
mockTransaction.cost = 23.46
|
|
570
|
+
mockTransaction.permissions = [permission]
|
|
571
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
572
|
+
generatePermissionNumber.mockReturnValueOnce(expectedPermission.referenceNumber)
|
|
573
|
+
calculateEndDate.mockReturnValueOnce(expectedPermission.endDate)
|
|
574
|
+
|
|
575
|
+
await processRPResult(transactionId, '123abc', '2025-01-01')
|
|
576
|
+
|
|
577
|
+
expect(AWSMocks.docClient.createUpdateExpression).toHaveBeenCalledWith({
|
|
578
|
+
payload: expect.objectContaining(expectedPermission),
|
|
579
|
+
permissions: expect.arrayContaining([expectedPermission]),
|
|
580
|
+
status: expect.objectContaining({ id: TRANSACTION_STATUS.FINALISED }),
|
|
581
|
+
payment: expect.objectContaining({
|
|
582
|
+
amount: mockTransaction.cost,
|
|
583
|
+
method: TRANSACTION_SOURCE.govPay,
|
|
584
|
+
source: PAYMENT_TYPE.debit,
|
|
585
|
+
timestamp: fakeNow
|
|
586
|
+
})
|
|
587
|
+
})
|
|
588
|
+
})
|
|
589
|
+
|
|
590
|
+
it('should call AWSMocks.docClient.update with expected params', async () => {
|
|
591
|
+
jest.spyOn(AWSMocks.docClient, 'createUpdateExpression')
|
|
592
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
593
|
+
mockTransaction.cost = 38.72
|
|
594
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
595
|
+
const updateExpression = { expression: Symbol('update expression') }
|
|
596
|
+
AWSMocks.docClient.createUpdateExpression.mockReturnValue(updateExpression)
|
|
597
|
+
|
|
598
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
599
|
+
|
|
600
|
+
expect(AWSMocks.docClient.update).toHaveBeenCalledWith({
|
|
601
|
+
TableName: TRANSACTION_STAGING_TABLE.TableName,
|
|
602
|
+
Key: { id: transactionId },
|
|
603
|
+
...updateExpression,
|
|
604
|
+
ReturnValues: 'ALL_NEW'
|
|
605
|
+
})
|
|
606
|
+
})
|
|
607
|
+
|
|
608
|
+
it('should call AWSMocks.sqs.sendMessage with expected params', async () => {
|
|
609
|
+
const mockTransaction = getMockTransaction(transactionId)
|
|
610
|
+
retrieveStagedTransaction.mockResolvedValueOnce(mockTransaction)
|
|
611
|
+
|
|
612
|
+
await processRPResult(mockTransaction.id, '123', '2025-01-01')
|
|
613
|
+
|
|
614
|
+
expect(AWSMocks.sqs.sendMessage).toHaveBeenCalledWith({
|
|
615
|
+
QueueUrl: TRANSACTION_QUEUE.Url,
|
|
616
|
+
MessageGroupId: transactionId,
|
|
617
|
+
MessageDeduplicationId: transactionId,
|
|
618
|
+
MessageBody: JSON.stringify({ id: transactionId })
|
|
619
|
+
})
|
|
620
|
+
})
|
|
621
|
+
})
|
|
342
622
|
})
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { executeQuery, findDueRecurringPayments, RecurringPayment } from '@defra-fish/dynamics-lib'
|
|
2
|
+
import { calculateEndDate, generatePermissionNumber } from './permissions.service.js'
|
|
3
|
+
import { getObfuscatedDob } from './contacts.service.js'
|
|
2
4
|
import { createHash } from 'node:crypto'
|
|
3
|
-
import { ADVANCED_PURCHASE_MAX_DAYS } from '@defra-fish/business-rules-lib'
|
|
5
|
+
import { ADVANCED_PURCHASE_MAX_DAYS, PAYMENT_JOURNAL_STATUS_CODES, PAYMENT_TYPE, TRANSACTION_SOURCE } from '@defra-fish/business-rules-lib'
|
|
6
|
+
import { TRANSACTION_STAGING_TABLE, TRANSACTION_QUEUE } from '../config.js'
|
|
7
|
+
import { TRANSACTION_STATUS } from '../services/transactions/constants.js'
|
|
8
|
+
import { retrieveStagedTransaction } from '../services/transactions/retrieve-transaction.js'
|
|
9
|
+
import { createPaymentJournal, getPaymentJournal, updatePaymentJournal } from '../services/paymentjournals/payment-journals.service.js'
|
|
4
10
|
import moment from 'moment'
|
|
11
|
+
import { AWS } from '@defra-fish/connectors-lib'
|
|
12
|
+
const { sqs, docClient } = AWS()
|
|
5
13
|
|
|
6
14
|
export const getRecurringPayments = date => executeQuery(findDueRecurringPayments(date))
|
|
7
15
|
|
|
@@ -65,3 +73,56 @@ export const processRecurringPayment = async (transactionRecord, contact) => {
|
|
|
65
73
|
}
|
|
66
74
|
return { recurringPayment: null }
|
|
67
75
|
}
|
|
76
|
+
|
|
77
|
+
export const processRPResult = async (transactionId, paymentId, createdDate) => {
|
|
78
|
+
const transactionRecord = await retrieveStagedTransaction(transactionId)
|
|
79
|
+
if (await getPaymentJournal(transactionId)) {
|
|
80
|
+
await updatePaymentJournal(transactionId, {
|
|
81
|
+
paymentReference: paymentId,
|
|
82
|
+
paymentTimestamp: createdDate,
|
|
83
|
+
paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.InProgress
|
|
84
|
+
})
|
|
85
|
+
} else {
|
|
86
|
+
await createPaymentJournal(transactionId, {
|
|
87
|
+
paymentReference: paymentId,
|
|
88
|
+
paymentTimestamp: createdDate,
|
|
89
|
+
paymentStatus: PAYMENT_JOURNAL_STATUS_CODES.InProgress
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
const [permission] = transactionRecord.permissions
|
|
93
|
+
permission.issueDate = new Date().toISOString()
|
|
94
|
+
|
|
95
|
+
permission.endDate = await calculateEndDate(permission)
|
|
96
|
+
permission.referenceNumber = await generatePermissionNumber(permission, transactionRecord.dataSource)
|
|
97
|
+
permission.licensee.obfuscatedDob = await getObfuscatedDob(permission.licensee)
|
|
98
|
+
|
|
99
|
+
await docClient
|
|
100
|
+
.update({
|
|
101
|
+
TableName: TRANSACTION_STAGING_TABLE.TableName,
|
|
102
|
+
Key: { id: transactionId },
|
|
103
|
+
...docClient.createUpdateExpression({
|
|
104
|
+
payload: permission,
|
|
105
|
+
permissions: transactionRecord.permissions,
|
|
106
|
+
status: { id: TRANSACTION_STATUS.FINALISED },
|
|
107
|
+
payment: {
|
|
108
|
+
amount: transactionRecord.cost,
|
|
109
|
+
method: TRANSACTION_SOURCE.govPay,
|
|
110
|
+
source: PAYMENT_TYPE.debit,
|
|
111
|
+
timestamp: new Date().toISOString()
|
|
112
|
+
}
|
|
113
|
+
}),
|
|
114
|
+
ReturnValues: 'ALL_NEW'
|
|
115
|
+
})
|
|
116
|
+
.promise()
|
|
117
|
+
|
|
118
|
+
await sqs
|
|
119
|
+
.sendMessage({
|
|
120
|
+
QueueUrl: TRANSACTION_QUEUE.Url,
|
|
121
|
+
MessageGroupId: transactionId,
|
|
122
|
+
MessageDeduplicationId: transactionId,
|
|
123
|
+
MessageBody: JSON.stringify({ id: transactionId })
|
|
124
|
+
})
|
|
125
|
+
.promise()
|
|
126
|
+
|
|
127
|
+
return { permission }
|
|
128
|
+
}
|