@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra-fish/sales-api-service",
3
- "version": "1.22.0-rc.7",
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-rc.7",
39
- "@defra-fish/connectors-lib": "1.22.0-rc.7",
40
- "@defra-fish/dynamics-lib": "1.22.0-rc.7",
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
  }
@@ -34,7 +34,8 @@ const createTransactionRequestSchemaContent = {
34
34
  .min(1)
35
35
  .required()
36
36
  }),
37
- createdBy: Joi.string().optional()
37
+ createdBy: Joi.string().optional(),
38
+ journalId: Joi.string().optional()
38
39
  }
39
40
 
40
41
  /**
@@ -31,9 +31,15 @@ jest.mock('@defra-fish/business-rules-lib', () => ({
31
31
 
32
32
  const getStagedTransactionRecord = () => {
33
33
  const record = mockStagedTransactionRecord()
34
- const { permissions: [permission] } = record
35
- permission.issueDate = moment(permission.issueDate).year(2021).toISOString()
36
- permission.startDate = moment(permission.startDate).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
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
- ])('adjusts startDate if startDate is less than 30 minutes after issueDate', async (issueDate, startDate, endDate, startAfterPaymentMinutes, dataSource) => {
235
- BusinessRulesLib.START_AFTER_PAYMENT_MINUTES = startAfterPaymentMinutes
236
- const mockRecord = mockStagedTransactionRecord()
237
- mockRecord.dataSource = dataSource
238
- const [mockPermission] = mockRecord.permissions
239
- mockPermission.issueDate = issueDate
240
- mockPermission.startDate = startDate
241
- mockPermission.endDate = endDate
242
- const completionFields = getCompletionFields()
243
- AwsMock.DynamoDB.DocumentClient.__setResponse('update', {
244
- Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } }
245
- })
246
- AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord })
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
- ])('leaves start and end time unmodified for any data source type other than Web Sales and Telesales', async (issueDate, startDate, endDate, dataSource) => {
371
- permissionsService.calculateEndDate.mockReturnValueOnce(endDate)
372
- const mockRecord = mockStagedTransactionRecord()
373
- mockRecord.dataSource = dataSource
374
- const [mockPermission] = mockRecord.permissions
375
- mockPermission.issueDate = issueDate
376
- mockPermission.startDate = startDate
377
- mockPermission.endDate = endDate
378
- const completionFields = getCompletionFields()
379
- AwsMock.DynamoDB.DocumentClient.__setResponse('update', {
380
- Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } }
381
- })
382
- AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord })
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).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
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
- POCL_TRANSACTION_SOURCES: ['Post Office Sales', 'DDE File'],
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).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
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