@defra-fish/sales-api-service 1.24.0-rc.7 → 1.24.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.24.0-rc.7",
3
+ "version": "1.24.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.24.0-rc.7",
39
- "@defra-fish/connectors-lib": "1.24.0-rc.7",
40
- "@defra-fish/dynamics-lib": "1.24.0-rc.7",
38
+ "@defra-fish/business-rules-lib": "1.24.0",
39
+ "@defra-fish/connectors-lib": "1.24.0",
40
+ "@defra-fish/dynamics-lib": "1.24.0",
41
41
  "@hapi/boom": "^9.1.2",
42
42
  "@hapi/hapi": "^20.1.3",
43
43
  "@hapi/inert": "^6.0.3",
@@ -51,5 +51,5 @@
51
51
  "moment": "^2.29.1",
52
52
  "uuid": "^8.3.2"
53
53
  },
54
- "gitHead": "da3683aebd2547d7a8d2be3668c16c258a073328"
54
+ "gitHead": "c138f45936dbae8ebb917599a53b6cf96c73aaa5"
55
55
  }
@@ -66,7 +66,8 @@ export const mockPermissionPayload = () => ({
66
66
  }
67
67
  ],
68
68
  issueDate: MOCK_ISSUE_DATE,
69
- startDate: MOCK_START_DATE
69
+ startDate: MOCK_START_DATE,
70
+ isRenewal: false
70
71
  })
71
72
 
72
73
  export const mockTransactionPayload = () => ({
@@ -36,25 +36,17 @@ export const stagedPermissionSchema = Joi.object({
36
36
  concessions: concessionProofSchema.optional(),
37
37
  issueDate: issueDateSchema.allow(null),
38
38
  startDate: startDateSchema.allow(null),
39
- isLicenceForYou: Joi.boolean()
40
- .optional()
41
- .allow(null)
42
- .example('true')
39
+ isRenewal: Joi.boolean(),
40
+ isLicenceForYou: Joi.boolean().optional().allow(null).example('true')
43
41
  }).label('staged-permission')
44
42
 
45
43
  export const finalisedPermissionSchemaContent = {
46
- id: Joi.string()
47
- .guid()
48
- .required()
49
- .example(uuid()),
44
+ id: Joi.string().guid().required().example(uuid()),
50
45
  referenceNumber: validation.permission.createPermissionNumberValidator(Joi),
51
46
  issueDate: issueDateSchema,
52
47
  startDate: startDateSchema,
53
48
  endDate: endDateSchema,
54
- stagingId: Joi.string()
55
- .guid()
56
- .required()
57
- .example(uuid()),
49
+ stagingId: Joi.string().guid().required().example(uuid()),
58
50
  dataSource: optionSetOption
59
51
  }
60
52
 
@@ -6,10 +6,7 @@ import { concessionProofSchema } from './concession-proof.schema.js'
6
6
  import { buildJoiOptionSetValidator, createAlternateKeyValidator } from './validators/validators.js'
7
7
  import { PoclFile, PoclStagingException } from '@defra-fish/dynamics-lib'
8
8
 
9
- const dateSchema = Joi.string()
10
- .isoDate()
11
- .required()
12
- .example(new Date().toISOString())
9
+ const dateSchema = Joi.string().isoDate().required().example(new Date().toISOString())
13
10
 
14
11
  const TRANSACTION_DATE = dateSchema.description('An ISO8601 compatible date string defining when the transaction was completed')
15
12
 
@@ -26,9 +23,7 @@ const schemaObject = {
26
23
  json: Joi.string().required(),
27
24
  notes: Joi.string(),
28
25
  type: buildJoiOptionSetValidator(PoclStagingException.definition.mappings.type.ref, 'Failure'),
29
- transactionFile: Joi.string()
30
- .external(createAlternateKeyValidator(PoclFile))
31
- .required(),
26
+ transactionFile: Joi.string().external(createAlternateKeyValidator(PoclFile)).required(),
32
27
  permissionId: Joi.string()
33
28
  }),
34
29
  record: Joi.object({
@@ -80,77 +75,45 @@ export const poclValidationErrorItemSchema = Joi.object({
80
75
  postalFulfilment: Joi.boolean().required(),
81
76
  concessions: concessionProofSchema.optional(),
82
77
  startDate: dateSchema.description('An ISO8601 compatible date string defining when the permission commences'),
83
- serialNumber: Joi.string()
84
- .trim()
85
- .required(),
86
- transactionFile: Joi.string()
87
- .trim()
88
- .required(),
89
- permitId: Joi.string()
90
- .guid()
91
- .required(),
78
+ serialNumber: Joi.string().trim().required(),
79
+ transactionFile: Joi.string().trim().required(),
80
+ permitId: Joi.string().guid().required(),
92
81
  amount: Joi.number().required(),
93
82
  transactionDate: TRANSACTION_DATE,
94
- paymentSource: Joi.string()
95
- .trim()
96
- .required(),
97
- channelId: Joi.string()
98
- .trim()
99
- .required()
100
- .description('Channel specific identifier'),
83
+ paymentSource: Joi.string().trim().required(),
84
+ channelId: Joi.string().trim().required().description('Channel specific identifier'),
101
85
  methodOfPayment: buildJoiOptionSetValidator('defra_paymenttype', 'Debit card'),
102
86
  dataSource: buildJoiOptionSetValidator('defra_datasource', 'Post Office Sales'),
103
87
  status: buildJoiOptionSetValidator('defra_status', 'Ready for Processing'),
104
88
  stateCode: Joi.number().required()
105
89
  }).label('pocl-validation-error-item')
106
90
 
107
- export const poclValidationErrorListSchema = Joi.array()
108
- .items(poclValidationErrorItemSchema)
109
- .label('pocl-validation-error-item-list')
91
+ export const poclValidationErrorListSchema = Joi.array().items(poclValidationErrorItemSchema).label('pocl-validation-error-item-list')
110
92
 
111
93
  export const poclValidationErrorParamsSchema = Joi.object({
112
- id: Joi.string()
113
- .trim()
114
- .guid()
115
- .required()
116
- .description('The POCL validation error identifier')
117
- .example(uuidv4())
94
+ id: Joi.string().trim().guid().required().description('The POCL validation error identifier').example(uuidv4())
118
95
  })
119
96
 
120
97
  // There may be further issues in the record data at this point
121
98
  export const updatePoclValidationErrorPayload = Joi.object({
122
- poclValidationErrorId: Joi.string()
123
- .trim()
124
- .guid()
125
- .required()
126
- .description('The POCL validation error identifier')
127
- .example(uuidv4()),
99
+ poclValidationErrorId: Joi.string().trim().guid().required().description('The POCL validation error identifier').example(uuidv4()),
128
100
  createTransactionPayload: {
129
101
  dataSource: Joi.string().optional(),
130
102
  journalId: Joi.string().optional(),
131
- serialNumber: Joi.string()
132
- .trim()
133
- .required(),
103
+ serialNumber: Joi.string().trim().required(),
134
104
  permissions: Joi.array().items(
135
105
  Joi.object({
136
106
  licensee: Joi.object(),
137
107
  issueDate: TRANSACTION_DATE,
138
108
  startDate: dateSchema.description('An ISO8601 compatible date string defining when the permission commences'),
139
- permitId: Joi.string()
140
- .guid()
141
- .required(),
109
+ permitId: Joi.string().guid().required(),
142
110
  concessions: Joi.array()
143
111
  .items(
144
112
  Joi.object({
145
- id: Joi.string()
146
- .guid()
147
- .required()
148
- .example(uuidv4()),
113
+ id: Joi.string().guid().required().example(uuidv4()),
149
114
  proof: Joi.object({
150
115
  type: Joi.string().required(),
151
- referenceNumber: Joi.string()
152
- .optional()
153
- .example('QQ 12 34 56 C')
116
+ referenceNumber: Joi.string().optional().example('QQ 12 34 56 C')
154
117
  }).required()
155
118
  })
156
119
  )
@@ -163,16 +126,9 @@ export const updatePoclValidationErrorPayload = Joi.object({
163
126
  payment: {
164
127
  timestamp: TRANSACTION_DATE,
165
128
  amount: Joi.number().required(),
166
- source: Joi.string()
167
- .trim()
168
- .required(),
169
- channelId: Joi.string()
170
- .trim()
171
- .required()
172
- .description('Channel specific identifier'),
173
- method: Joi.string()
174
- .trim()
175
- .required()
129
+ source: Joi.string().trim().required(),
130
+ channelId: Joi.string().trim().required().description('Channel specific identifier'),
131
+ method: Joi.string().trim().required()
176
132
  }
177
133
  },
178
134
  createTransactionError: Joi.object().optional(),
@@ -29,10 +29,7 @@ const createTransactionRequestSchemaContent = {
29
29
  dataSource: buildJoiOptionSetValidator('defra_datasource', 'Web Sales'),
30
30
  serialNumber: Joi.when('dataSource', {
31
31
  is: Joi.valid(...POCL_TRANSACTION_SOURCES),
32
- then: Joi.string()
33
- .trim()
34
- .min(1)
35
- .required()
32
+ then: Joi.string().trim().min(1).required()
36
33
  }),
37
34
  createdBy: Joi.string().optional(),
38
35
  journalId: Joi.string().optional()
@@ -55,33 +52,19 @@ export const createTransactionSchema = Joi.object(createTransactionRequestSchema
55
52
  export const createTransactionBatchSchema = Joi.array()
56
53
  .min(1)
57
54
  .max(BATCH_CREATE_MAX_COUNT)
58
- .items(
59
- Joi.object()
60
- .required()
61
- .label('create-transaction-batch-item')
62
- .description('See create-transaction-request for proper structure')
63
- )
55
+ .items(Joi.object().required().label('create-transaction-batch-item').description('See create-transaction-request for proper structure'))
64
56
  .required()
65
57
  .label('create-transaction-batch-request')
66
58
 
67
59
  const createTransactionResponseSchemaContent = {
68
- id: Joi.string()
69
- .trim()
70
- .guid()
71
- .required(),
60
+ id: Joi.string().trim().guid().required(),
72
61
  expires: Joi.number().required(),
73
62
  ...createTransactionRequestSchemaContent,
74
- permissions: Joi.array()
75
- .min(1)
76
- .items(stagedPermissionSchema)
77
- .required()
78
- .label('create-transaction-response-permissions'),
63
+ permissions: Joi.array().min(1).items(stagedPermissionSchema).required().label('create-transaction-response-permissions'),
79
64
  cost: Joi.number().required(),
80
65
  isRecurringPaymentSupported: Joi.boolean().required(),
81
66
  status: Joi.object({
82
- id: Joi.string()
83
- .valid('STAGED')
84
- .required()
67
+ id: Joi.string().valid('STAGED').required()
85
68
  })
86
69
  .label('create-transaction-status')
87
70
  .required()
@@ -101,9 +84,7 @@ export const createTransactionBatchResponseSchema = Joi.array()
101
84
  .items(
102
85
  Joi.object({
103
86
  statusCode: Joi.number().required(),
104
- response: Joi.object(createTransactionResponseSchemaContent)
105
- .label('create-transaction-batch-item-response')
106
- .optional(),
87
+ response: Joi.object(createTransactionResponseSchemaContent).label('create-transaction-batch-item-response').optional(),
107
88
  error: Joi.string().optional(),
108
89
  message: Joi.string().optional()
109
90
  }).label('create-transaction-batch-response-item')
@@ -122,21 +103,12 @@ const finaliseTransactionRequestSchemaContent = {
122
103
  .description('An ISO8601 compatible date string defining when the transaction was completed')
123
104
  .example(new Date().toISOString()),
124
105
  source: buildJoiOptionSetValidator('defra_financialtransactionsource', 'Gov Pay'),
125
- channelId: Joi.string()
126
- .trim()
127
- .optional()
128
- .description('Channel specific identifier'),
106
+ channelId: Joi.string().trim().optional().description('Channel specific identifier'),
129
107
  method: buildJoiOptionSetValidator('defra_paymenttype', 'Debit card'),
130
108
  recurring: Joi.object({
131
109
  payer: contactRequestSchema,
132
- referenceNumber: Joi.string()
133
- .required()
134
- .description('The reference number associated with the recurring payment')
135
- .example(uuidv4()),
136
- mandate: Joi.string()
137
- .required()
138
- .description('The mandate identifier associated with the recurring payment')
139
- .example(uuidv4())
110
+ referenceNumber: Joi.string().required().description('The reference number associated with the recurring payment').example(uuidv4()),
111
+ mandate: Joi.string().required().description('The mandate identifier associated with the recurring payment').example(uuidv4())
140
112
  })
141
113
  .label('finalise-transaction-recurring-payment-details')
142
114
  .description('Used to establish a recurring payment (e.g. via Direct Debit)')
@@ -155,15 +127,9 @@ export const finaliseTransactionRequestSchema = Joi.object(finaliseTransactionRe
155
127
  export const finaliseTransactionResponseSchema = Joi.object({
156
128
  ...createTransactionResponseSchemaContent,
157
129
  ...finaliseTransactionRequestSchemaContent,
158
- permissions: Joi.array()
159
- .min(1)
160
- .items(finalisePermissionResponseSchema)
161
- .required()
162
- .label('finalise-transaction-response-permissions'),
130
+ permissions: Joi.array().min(1).items(finalisePermissionResponseSchema).required().label('finalise-transaction-response-permissions'),
163
131
  status: Joi.object({
164
- id: Joi.string()
165
- .valid('FINALISED')
166
- .required(),
132
+ id: Joi.string().valid('FINALISED').required(),
167
133
  messageId: Joi.string().required()
168
134
  })
169
135
  .required()
@@ -34,12 +34,8 @@ const getStagedTransactionRecord = () => {
34
34
  const {
35
35
  permissions: [permission]
36
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
+ permission.issueDate = moment(permission.issueDate).year(2021).toISOString()
38
+ permission.startDate = moment(permission.startDate).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
43
39
  return record
44
40
  }
45
41
 
@@ -98,11 +94,7 @@ describe('transaction service', () => {
98
94
  ':permissions': mockRecord.permissions.map(p => ({
99
95
  ...p,
100
96
  issueDate: p.issueDate ?? completionFields.payment.timestamp,
101
- startDate:
102
- p.startDate ??
103
- moment(completionFields.payment.timestamp)
104
- .add(START_AFTER_PAYMENT_MINUTES, 'minutes')
105
- .toISOString(),
97
+ startDate: p.startDate ?? moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString(),
106
98
  endDate: expect.any(String),
107
99
  referenceNumber: expect.any(String)
108
100
  })),
@@ -261,9 +253,7 @@ describe('transaction service', () => {
261
253
  ':permissions': expect.arrayContaining([
262
254
  expect.objectContaining({
263
255
  permitId: mockPermission.permitId,
264
- startDate: moment(issueDate)
265
- .add(startAfterPaymentMinutes, 'minutes')
266
- .toISOString()
256
+ startDate: moment(issueDate).add(startAfterPaymentMinutes, 'minutes').toISOString()
267
257
  })
268
258
  ])
269
259
  })
@@ -317,7 +307,6 @@ describe('transaction service', () => {
317
307
  const [mockPermission] = mockRecord.permissions
318
308
  mockPermission.issueDate = issueDate
319
309
  mockPermission.startDate = startDate
320
- const licenceLength = moment(endDate).subtract(moment(startDate))
321
310
  const completionFields = getCompletionFields()
322
311
  AwsMock.DynamoDB.DocumentClient.__setResponse('update', {
323
312
  Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } }
@@ -441,9 +430,7 @@ describe('transaction service', () => {
441
430
  expect(permission).toEqual(
442
431
  expect.objectContaining({
443
432
  permitId: mockPermission.permitId,
444
- startDate: moment(completionFields.payment.timestamp)
445
- .add(START_AFTER_PAYMENT_MINUTES, 'minutes')
446
- .toISOString()
433
+ startDate: moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
447
434
  })
448
435
  )
449
436
  })
@@ -252,7 +252,7 @@ describe('transaction service', () => {
252
252
  ['123456', 2020],
253
253
  ['654321', 2021],
254
254
  ['567890', 2022]
255
- ])('and it\'s a DDE File, and has a journal id, returns journal id', (journalId, year) => {
255
+ ])("and it's a DDE File, and has a journal id, returns journal id", (journalId, year) => {
256
256
  jest.useFakeTimers()
257
257
  jest.setSystemTime(new Date(year, 1, 1, 10, 0, 0, 0))
258
258
  const mockRecord = getSampleRecord({
@@ -264,7 +264,7 @@ describe('transaction service', () => {
264
264
  jest.useRealTimers()
265
265
  })
266
266
 
267
- it('and it\'s a POCL file, and has a journal id and a serial number, returns serial number', () => {
267
+ it("and it's a POCL file, and has a journal id and a serial number, returns serial number", () => {
268
268
  const mockRecord = getSampleRecord()
269
269
  mockRecord.journalId = '123456'
270
270
  const refNumber = getTransactionJournalRefNumber(mockRecord, 'Payment')
@@ -15,9 +15,7 @@ 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)
19
- .add(START_AFTER_PAYMENT_MINUTES, 'minutes')
20
- .toISOString()
18
+ return moment(issueDate).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
21
19
  }
22
20
  return startDate
23
21
  }
@@ -39,11 +37,7 @@ export async function finaliseTransaction ({ id, ...payload }) {
39
37
  // Generate derived fields
40
38
  for (const permission of transactionRecord.permissions) {
41
39
  permission.issueDate = permission.issueDate ?? payload.payment.timestamp
42
- const startDate =
43
- permission.startDate ??
44
- moment(payload.payment.timestamp)
45
- .add(START_AFTER_PAYMENT_MINUTES, 'minutes')
46
- .toISOString()
40
+ const startDate = permission.startDate ?? moment(payload.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString()
47
41
  permission.startDate = getAdjustedStartDate({
48
42
  startDate,
49
43
  dataSource: transactionRecord.dataSource,
@@ -51,6 +51,7 @@ export async function processQueue ({ id }) {
51
51
  issueDate,
52
52
  startDate,
53
53
  endDate,
54
+ isRenewal,
54
55
  isLicenceForYou
55
56
  } of transactionRecord.permissions) {
56
57
  const contact = await resolveContactPayload(licensee)
@@ -58,7 +59,16 @@ export async function processQueue ({ id }) {
58
59
 
59
60
  totalTransactionValue += permit.cost
60
61
 
61
- const permission = await mapToPermission(referenceNumber, transactionRecord, issueDate, startDate, endDate, dataSource, isLicenceForYou)
62
+ const permission = await mapToPermission(
63
+ referenceNumber,
64
+ transactionRecord,
65
+ issueDate,
66
+ startDate,
67
+ endDate,
68
+ dataSource,
69
+ isLicenceForYou,
70
+ isRenewal
71
+ )
62
72
 
63
73
  permission.bindToEntity(Permission.definition.relationships.licensee, contact)
64
74
  permission.bindToEntity(Permission.definition.relationships.permit, permit)
@@ -102,7 +112,16 @@ export async function processQueue ({ id }) {
102
112
  .promise()
103
113
  }
104
114
 
105
- const mapToPermission = async (referenceNumber, transactionRecord, issueDate, startDate, endDate, dataSource, isLicenceForYou) => {
115
+ const mapToPermission = async (
116
+ referenceNumber,
117
+ transactionRecord,
118
+ issueDate,
119
+ startDate,
120
+ endDate,
121
+ dataSource,
122
+ isLicenceForYou,
123
+ isRenewal
124
+ ) => {
106
125
  const permission = new Permission()
107
126
  permission.referenceNumber = referenceNumber
108
127
  permission.stagingId = transactionRecord.id
@@ -110,6 +129,7 @@ const mapToPermission = async (referenceNumber, transactionRecord, issueDate, st
110
129
  permission.startDate = startDate
111
130
  permission.endDate = endDate
112
131
  permission.dataSource = dataSource
132
+ permission.isRenewal = isRenewal
113
133
  if (isLicenceForYou !== null && isLicenceForYou !== undefined) {
114
134
  permission.isLicenceForYou = await getGlobalOptionSetValue(
115
135
  Permission.definition.mappings.isLicenceForYou.ref,
@@ -171,7 +191,7 @@ const createTransactionEntities = async transactionRecord => {
171
191
  export const getTransactionJournalRefNumber = (transactionRecord, type) => {
172
192
  if (POCL_TRANSACTION_SOURCES.includes(transactionRecord.dataSource) && type === 'Payment') {
173
193
  if (transactionRecord.dataSource === DDE_DATA_SOURCE && transactionRecord.journalId) {
174
- return `DDE-${(new Date()).getFullYear()}-${transactionRecord.journalId}`
194
+ return `DDE-${new Date().getFullYear()}-${transactionRecord.journalId}`
175
195
  }
176
196
  return transactionRecord.serialNumber || transactionRecord.id
177
197
  }