@defra-fish/sales-api-service 1.22.0-rc.7 → 1.22.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 +5 -6
- package/src/schema/transaction.schema.js +2 -1
- package/src/services/transactions/__tests__/finalise-transaction.spec.js +77 -61
- package/src/services/transactions/__tests__/process-transaction-queue.spec.js +37 -6
- package/src/services/transactions/finalise-transaction.js +3 -1
- package/src/services/transactions/process-transaction-queue.js +5 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/sales-api-service",
|
|
3
|
-
"version": "1.22.0
|
|
3
|
+
"version": "1.22.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.22.0
|
|
39
|
-
"@defra-fish/connectors-lib": "1.22.0
|
|
40
|
-
"@defra-fish/dynamics-lib": "1.22.0
|
|
38
|
+
"@defra-fish/business-rules-lib": "1.22.0",
|
|
39
|
+
"@defra-fish/connectors-lib": "1.22.0",
|
|
40
|
+
"@defra-fish/dynamics-lib": "1.22.0",
|
|
41
41
|
"@hapi/boom": "^9.1.2",
|
|
42
42
|
"@hapi/hapi": "^20.1.3",
|
|
43
43
|
"@hapi/inert": "^6.0.3",
|
|
@@ -50,6 +50,5 @@
|
|
|
50
50
|
"joi": "^17.4.0",
|
|
51
51
|
"moment": "^2.29.1",
|
|
52
52
|
"uuid": "^8.3.2"
|
|
53
|
-
}
|
|
54
|
-
"gitHead": "4840a94a046213c95478ea8ce84c086a81d5b2fb"
|
|
53
|
+
}
|
|
55
54
|
}
|
|
@@ -31,9 +31,15 @@ jest.mock('@defra-fish/business-rules-lib', () => ({
|
|
|
31
31
|
|
|
32
32
|
const getStagedTransactionRecord = () => {
|
|
33
33
|
const record = mockStagedTransactionRecord()
|
|
34
|
-
const {
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const {
|
|
35
|
+
permissions: [permission]
|
|
36
|
+
} = record
|
|
37
|
+
permission.issueDate = moment(permission.issueDate)
|
|
38
|
+
.year(2021)
|
|
39
|
+
.toISOString()
|
|
40
|
+
permission.startDate = moment(permission.startDate)
|
|
41
|
+
.add(START_AFTER_PAYMENT_MINUTES, 'minutes')
|
|
42
|
+
.toISOString()
|
|
37
43
|
return record
|
|
38
44
|
}
|
|
39
45
|
|
|
@@ -231,35 +237,40 @@ describe('transaction service', () => {
|
|
|
231
237
|
['2021-09-30T22:14:01.892Z', '2021-09-30T21:44:01.892Z', '2021-09-08T21:44:01.892Z', 47, 'Web Sales'],
|
|
232
238
|
['2021-09-30T00:14:01.892Z', '2021-09-29T17:14:01.892Z', '2022-09-30T17:14:01.892Z', 12, 'Telesales'],
|
|
233
239
|
['2021-11-30T23:14:01.892Z', '2021-11-30T22:22:01.892Z', '2022-11-30T22:22:01.892Z', 1, 'Telesales']
|
|
234
|
-
])(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
await finaliseTransaction({ id: mockRecord.id, ...completionFields })
|
|
249
|
-
|
|
250
|
-
expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith(
|
|
251
|
-
expect.objectContaining({
|
|
252
|
-
ExpressionAttributeValues: expect.objectContaining({
|
|
253
|
-
':permissions': expect.arrayContaining([
|
|
254
|
-
expect.objectContaining({
|
|
255
|
-
permitId: mockPermission.permitId,
|
|
256
|
-
startDate: moment(issueDate).add(startAfterPaymentMinutes, 'minutes').toISOString()
|
|
257
|
-
})
|
|
258
|
-
])
|
|
259
|
-
})
|
|
240
|
+
])(
|
|
241
|
+
'adjusts startDate if startDate is less than 30 minutes after issueDate',
|
|
242
|
+
async (issueDate, startDate, endDate, startAfterPaymentMinutes, dataSource) => {
|
|
243
|
+
BusinessRulesLib.START_AFTER_PAYMENT_MINUTES = startAfterPaymentMinutes
|
|
244
|
+
const mockRecord = mockStagedTransactionRecord()
|
|
245
|
+
mockRecord.dataSource = dataSource
|
|
246
|
+
const [mockPermission] = mockRecord.permissions
|
|
247
|
+
mockPermission.issueDate = issueDate
|
|
248
|
+
mockPermission.startDate = startDate
|
|
249
|
+
mockPermission.endDate = endDate
|
|
250
|
+
const completionFields = getCompletionFields()
|
|
251
|
+
AwsMock.DynamoDB.DocumentClient.__setResponse('update', {
|
|
252
|
+
Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } }
|
|
260
253
|
})
|
|
261
|
-
|
|
262
|
-
|
|
254
|
+
AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord })
|
|
255
|
+
|
|
256
|
+
await finaliseTransaction({ id: mockRecord.id, ...completionFields })
|
|
257
|
+
|
|
258
|
+
expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith(
|
|
259
|
+
expect.objectContaining({
|
|
260
|
+
ExpressionAttributeValues: expect.objectContaining({
|
|
261
|
+
':permissions': expect.arrayContaining([
|
|
262
|
+
expect.objectContaining({
|
|
263
|
+
permitId: mockPermission.permitId,
|
|
264
|
+
startDate: moment(issueDate)
|
|
265
|
+
.add(startAfterPaymentMinutes, 'minutes')
|
|
266
|
+
.toISOString()
|
|
267
|
+
})
|
|
268
|
+
])
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
)
|
|
263
274
|
|
|
264
275
|
it.each([
|
|
265
276
|
['2021-09-30T17:14:01.892Z', '2021-09-30T17:44:02.892Z', '2022-09-30T17:44:02.892Z'],
|
|
@@ -367,36 +378,39 @@ describe('transaction service', () => {
|
|
|
367
378
|
['2021-09-30T23:14:01.892Z', '2021-09-30T23:00:49.892Z', '2022-09-30T23:00:49.892Z', 'Post Office Sales'],
|
|
368
379
|
['2021-09-30T22:14:01.892Z', '2021-09-30T21:44:01.892Z', '2022-09-30T21:44:01.892Z', 'DDE File'],
|
|
369
380
|
['2021-09-30T00:14:01.892Z', '2021-09-29T17:14:01.892Z', '2022-09-29T17:14:01.892Z', 'DDE File']
|
|
370
|
-
])(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
await finaliseTransaction({ id: mockRecord.id, ...completionFields })
|
|
385
|
-
|
|
386
|
-
expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith(
|
|
387
|
-
expect.objectContaining({
|
|
388
|
-
ExpressionAttributeValues: expect.objectContaining({
|
|
389
|
-
':permissions': expect.arrayContaining([
|
|
390
|
-
expect.objectContaining({
|
|
391
|
-
permitId: mockPermission.permitId,
|
|
392
|
-
startDate,
|
|
393
|
-
endDate
|
|
394
|
-
})
|
|
395
|
-
])
|
|
396
|
-
})
|
|
381
|
+
])(
|
|
382
|
+
'leaves start and end time unmodified for any data source type other than Web Sales and Telesales',
|
|
383
|
+
async (issueDate, startDate, endDate, dataSource) => {
|
|
384
|
+
permissionsService.calculateEndDate.mockReturnValueOnce(endDate)
|
|
385
|
+
const mockRecord = mockStagedTransactionRecord()
|
|
386
|
+
mockRecord.dataSource = dataSource
|
|
387
|
+
const [mockPermission] = mockRecord.permissions
|
|
388
|
+
mockPermission.issueDate = issueDate
|
|
389
|
+
mockPermission.startDate = startDate
|
|
390
|
+
mockPermission.endDate = endDate
|
|
391
|
+
const completionFields = getCompletionFields()
|
|
392
|
+
AwsMock.DynamoDB.DocumentClient.__setResponse('update', {
|
|
393
|
+
Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } }
|
|
397
394
|
})
|
|
398
|
-
|
|
399
|
-
|
|
395
|
+
AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord })
|
|
396
|
+
|
|
397
|
+
await finaliseTransaction({ id: mockRecord.id, ...completionFields })
|
|
398
|
+
|
|
399
|
+
expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith(
|
|
400
|
+
expect.objectContaining({
|
|
401
|
+
ExpressionAttributeValues: expect.objectContaining({
|
|
402
|
+
':permissions': expect.arrayContaining([
|
|
403
|
+
expect.objectContaining({
|
|
404
|
+
permitId: mockPermission.permitId,
|
|
405
|
+
startDate,
|
|
406
|
+
endDate
|
|
407
|
+
})
|
|
408
|
+
])
|
|
409
|
+
})
|
|
410
|
+
})
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
)
|
|
400
414
|
|
|
401
415
|
it.each([
|
|
402
416
|
['2021-09-30T17:14:01.892Z', '2021-09-30T17:14:01.892Z'],
|
|
@@ -427,7 +441,9 @@ describe('transaction service', () => {
|
|
|
427
441
|
expect(permission).toEqual(
|
|
428
442
|
expect.objectContaining({
|
|
429
443
|
permitId: mockPermission.permitId,
|
|
430
|
-
startDate: moment(completionFields.payment.timestamp)
|
|
444
|
+
startDate: moment(completionFields.payment.timestamp)
|
|
445
|
+
.add(START_AFTER_PAYMENT_MINUTES, 'minutes')
|
|
446
|
+
.toISOString()
|
|
431
447
|
})
|
|
432
448
|
)
|
|
433
449
|
})
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from '../../../__mocks__/test-data.js'
|
|
25
25
|
import { TRANSACTION_STAGING_TABLE, TRANSACTION_STAGING_HISTORY_TABLE } from '../../../config.js'
|
|
26
26
|
import AwsMock from 'aws-sdk'
|
|
27
|
+
import { POCL_DATA_SOURCE, DDE_DATA_SOURCE } from '@defra-fish/business-rules-lib'
|
|
27
28
|
|
|
28
29
|
jest.mock('../../reference-data.service.js', () => ({
|
|
29
30
|
...jest.requireActual('../../reference-data.service.js'),
|
|
@@ -56,7 +57,9 @@ jest.mock('../../contacts.service.js', () => ({
|
|
|
56
57
|
}))
|
|
57
58
|
|
|
58
59
|
jest.mock('@defra-fish/business-rules-lib', () => ({
|
|
59
|
-
|
|
60
|
+
POCL_DATA_SOURCE: 'POCL_DATA_SOURCE',
|
|
61
|
+
DDE_DATA_SOURCE: 'DDE_DATA_SOURCE',
|
|
62
|
+
POCL_TRANSACTION_SOURCES: ['POCL_DATA_SOURCE', 'DDE_DATA_SOURCE'],
|
|
60
63
|
START_AFTER_PAYMENT_MINUTES: 30
|
|
61
64
|
}))
|
|
62
65
|
|
|
@@ -244,18 +247,38 @@ describe('transaction service', () => {
|
|
|
244
247
|
})
|
|
245
248
|
|
|
246
249
|
describe('.getTransactionJournalRefNumber', () => {
|
|
247
|
-
let mockRecord
|
|
248
|
-
beforeAll(() => {
|
|
249
|
-
mockRecord = mockFinalisedTransactionRecord()
|
|
250
|
-
mockRecord.dataSource = 'Post Office Sales'
|
|
251
|
-
})
|
|
252
250
|
describe('when the transaction type is "Payment"', () => {
|
|
251
|
+
it.each([
|
|
252
|
+
['123456', 2020],
|
|
253
|
+
['654321', 2021],
|
|
254
|
+
['567890', 2022]
|
|
255
|
+
])('and it\'s a DDE File, and has a journal id, returns journal id', (journalId, year) => {
|
|
256
|
+
jest.useFakeTimers()
|
|
257
|
+
jest.setSystemTime(new Date(year, 1, 1, 10, 0, 0, 0))
|
|
258
|
+
const mockRecord = getSampleRecord({
|
|
259
|
+
dataSource: DDE_DATA_SOURCE,
|
|
260
|
+
journalId
|
|
261
|
+
})
|
|
262
|
+
const refNumber = getTransactionJournalRefNumber(mockRecord, 'Payment')
|
|
263
|
+
expect(refNumber).toBe(`DDE-${year}-${journalId}`)
|
|
264
|
+
jest.useRealTimers()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('and it\'s a POCL file, and has a journal id and a serial number, returns serial number', () => {
|
|
268
|
+
const mockRecord = getSampleRecord()
|
|
269
|
+
mockRecord.journalId = '123456'
|
|
270
|
+
const refNumber = getTransactionJournalRefNumber(mockRecord, 'Payment')
|
|
271
|
+
expect(refNumber).toBe(mockRecord.serialNumber)
|
|
272
|
+
})
|
|
273
|
+
|
|
253
274
|
it('and the serial number is present, returns serial number', () => {
|
|
275
|
+
const mockRecord = getSampleRecord()
|
|
254
276
|
const refNumber = getTransactionJournalRefNumber(mockRecord, 'Payment')
|
|
255
277
|
expect(refNumber).toBe(mockRecord.serialNumber)
|
|
256
278
|
})
|
|
257
279
|
|
|
258
280
|
it('and the serial number is not present, returns id', () => {
|
|
281
|
+
const mockRecord = getSampleRecord()
|
|
259
282
|
const refNumber = getTransactionJournalRefNumber({ ...mockRecord, serialNumber: null }, 'Payment')
|
|
260
283
|
expect(refNumber).toBe(mockRecord.id)
|
|
261
284
|
})
|
|
@@ -263,14 +286,22 @@ describe('transaction service', () => {
|
|
|
263
286
|
|
|
264
287
|
describe('when the transaction type is "Charge"', () => {
|
|
265
288
|
it('and the serial number is present, returns id', () => {
|
|
289
|
+
const mockRecord = getSampleRecord()
|
|
266
290
|
const refNumber = getTransactionJournalRefNumber(mockRecord, 'Charge')
|
|
267
291
|
expect(refNumber).toBe(mockRecord.id)
|
|
268
292
|
})
|
|
269
293
|
|
|
270
294
|
it('and the serial number is not present, returns id', () => {
|
|
295
|
+
const mockRecord = getSampleRecord()
|
|
271
296
|
const refNumber = getTransactionJournalRefNumber({ ...mockRecord, serialNumber: null }, 'Charge')
|
|
272
297
|
expect(refNumber).toBe(mockRecord.id)
|
|
273
298
|
})
|
|
274
299
|
})
|
|
300
|
+
|
|
301
|
+
const getSampleRecord = (overrides = {}) => ({
|
|
302
|
+
...mockFinalisedTransactionRecord(),
|
|
303
|
+
dataSource: POCL_DATA_SOURCE,
|
|
304
|
+
...overrides
|
|
305
|
+
})
|
|
275
306
|
})
|
|
276
307
|
})
|
|
@@ -15,7 +15,9 @@ const getAdjustedStartDate = ({ issueDate, startDate, dataSource }) => {
|
|
|
15
15
|
const startDateTooEarly = moment(startDate).isBefore(moment(issueDate).add(START_AFTER_PAYMENT_MINUTES, 'minutes'))
|
|
16
16
|
const webOrTelesales = !POCL_TRANSACTION_SOURCES.includes(dataSource)
|
|
17
17
|
if (startDateTooEarly && webOrTelesales) {
|
|
18
|
-
return moment(issueDate)
|
|
18
|
+
return moment(issueDate)
|
|
19
|
+
.add(START_AFTER_PAYMENT_MINUTES, 'minutes')
|
|
20
|
+
.toISOString()
|
|
19
21
|
}
|
|
20
22
|
return startDate
|
|
21
23
|
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
RecurringPayment,
|
|
12
12
|
RecurringPaymentInstruction
|
|
13
13
|
} from '@defra-fish/dynamics-lib'
|
|
14
|
-
import { POCL_TRANSACTION_SOURCES } from '@defra-fish/business-rules-lib'
|
|
14
|
+
import { DDE_DATA_SOURCE, POCL_TRANSACTION_SOURCES } from '@defra-fish/business-rules-lib'
|
|
15
15
|
import { getReferenceDataForEntityAndId, getGlobalOptionSetValue, getReferenceDataForEntity } from '../reference-data.service.js'
|
|
16
16
|
import { resolveContactPayload } from '../contacts.service.js'
|
|
17
17
|
import { retrieveStagedTransaction } from './retrieve-transaction.js'
|
|
@@ -30,7 +30,7 @@ const debug = db('sales:transactions')
|
|
|
30
30
|
* @param id
|
|
31
31
|
* @returns {Promise<void>}
|
|
32
32
|
*/
|
|
33
|
-
export async function processQueue({ id }) {
|
|
33
|
+
export async function processQueue ({ id }) {
|
|
34
34
|
debug('Processing message from queue for staging id %s', id)
|
|
35
35
|
const entities = []
|
|
36
36
|
const transactionRecord = await retrieveStagedTransaction(id)
|
|
@@ -170,6 +170,9 @@ const createTransactionEntities = async transactionRecord => {
|
|
|
170
170
|
|
|
171
171
|
export const getTransactionJournalRefNumber = (transactionRecord, type) => {
|
|
172
172
|
if (POCL_TRANSACTION_SOURCES.includes(transactionRecord.dataSource) && type === 'Payment') {
|
|
173
|
+
if (transactionRecord.dataSource === DDE_DATA_SOURCE && transactionRecord.journalId) {
|
|
174
|
+
return `DDE-${(new Date()).getFullYear()}-${transactionRecord.journalId}`
|
|
175
|
+
}
|
|
173
176
|
return transactionRecord.serialNumber || transactionRecord.id
|
|
174
177
|
}
|
|
175
178
|
return transactionRecord.id
|