@defra-fish/sales-api-service 1.35.0-rc.8 → 1.35.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.35.0-rc.8",
3
+ "version": "1.35.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.35.0-rc.8",
39
- "@defra-fish/connectors-lib": "1.35.0-rc.8",
40
- "@defra-fish/dynamics-lib": "1.35.0-rc.8",
38
+ "@defra-fish/business-rules-lib": "1.35.0",
39
+ "@defra-fish/connectors-lib": "1.35.0",
40
+ "@defra-fish/dynamics-lib": "1.35.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": "53f316d007d53e66ac57c4fbfe421f5c3fe6f2f5"
55
+ "gitHead": "be7f472adf337fc2e5b16431f2767defcab16d92"
56
56
  }
@@ -6,6 +6,8 @@ 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 DATE_STRING_DESCRIPTION = 'An ISO8601 compatible date string defining when the permission commences'
10
+
9
11
  const dateSchema = Joi.string().isoDate().required().example(new Date().toISOString())
10
12
 
11
13
  const TRANSACTION_DATE = dateSchema.description('An ISO8601 compatible date string defining when the transaction was completed')
@@ -74,16 +76,18 @@ export const poclValidationErrorItemSchema = Joi.object({
74
76
  preferredMethodOfReminder: optionSetOption,
75
77
  postalFulfilment: Joi.boolean().required(),
76
78
  concessions: concessionProofSchema.optional(),
77
- startDate: dateSchema.description('An ISO8601 compatible date string defining when the permission commences'),
79
+ startDate: dateSchema.description(DATE_STRING_DESCRIPTION),
80
+ newStartDate: dateSchema.description(DATE_STRING_DESCRIPTION),
78
81
  serialNumber: Joi.string().trim().required(),
79
82
  transactionFile: Joi.string().trim().required(),
80
83
  permitId: Joi.string().guid().required(),
81
84
  amount: Joi.number().required(),
82
85
  transactionDate: TRANSACTION_DATE,
83
86
  paymentSource: Joi.string().trim().required(),
87
+ newPaymentSource: buildJoiOptionSetValidator('defra_financialtransactionsource', 'Direct Debit'),
84
88
  channelId: Joi.string().trim().required().description('Channel specific identifier'),
85
89
  methodOfPayment: buildJoiOptionSetValidator('defra_paymenttype', 'Debit card'),
86
- dataSource: buildJoiOptionSetValidator('defra_datasource', 'Post Office Sales'),
90
+ dataSource: buildJoiOptionSetValidator('defra_datasource', 'DDE File'),
87
91
  status: buildJoiOptionSetValidator('defra_status', 'Ready for Processing'),
88
92
  stateCode: Joi.number().required()
89
93
  }).label('pocl-validation-error-item')
@@ -105,7 +109,7 @@ export const updatePoclValidationErrorPayload = Joi.object({
105
109
  Joi.object({
106
110
  licensee: Joi.object(),
107
111
  issueDate: TRANSACTION_DATE,
108
- startDate: dateSchema.description('An ISO8601 compatible date string defining when the permission commences'),
112
+ startDate: dateSchema.description(DATE_STRING_DESCRIPTION),
109
113
  permitId: Joi.string().guid().required(),
110
114
  concessions: Joi.array()
111
115
  .items(
@@ -122,12 +126,12 @@ export const updatePoclValidationErrorPayload = Joi.object({
122
126
  )
123
127
  },
124
128
  finaliseTransactionPayload: {
125
- transactionFile: Joi.string().required(),
129
+ transactionFile: Joi.string().optional(),
126
130
  payment: {
127
131
  timestamp: TRANSACTION_DATE,
128
132
  amount: Joi.number().required(),
129
133
  source: Joi.string().trim().required(),
130
- channelId: Joi.string().trim().required().description('Channel specific identifier'),
134
+ channelId: Joi.string().trim().optional().description('Channel specific identifier'),
131
135
  method: Joi.string().trim().required()
132
136
  }
133
137
  },
@@ -377,5 +377,26 @@ describe('validators', () => {
377
377
  ).resolves.toEqual(undefined)
378
378
  expect(spy).toHaveBeenCalledWith(PermitConcession)
379
379
  })
380
+
381
+ it('returns a validation function which does not throw an error for Postal Order Sales even if the permit requires a concession and none is supplied', async () => {
382
+ const spy = jest.spyOn(referenceData, 'getReferenceDataForEntity').mockImplementation(async () => [
383
+ {
384
+ permitId: 'test-1',
385
+ concessionId: 'test-1'
386
+ }
387
+ ])
388
+ const validationFunction = createPermitConcessionValidator()
389
+ await expect(
390
+ validationFunction({
391
+ dataSource: 'Postal Order Sales',
392
+ permissions: [
393
+ {
394
+ permitId: 'test-1'
395
+ }
396
+ ]
397
+ })
398
+ ).resolves.toEqual(undefined)
399
+ expect(spy).toHaveBeenCalledWith(PermitConcession)
400
+ })
380
401
  })
381
402
  })
@@ -131,7 +131,8 @@ const validatePermissionConcession = async (permission, transaction) => {
131
131
  concessionsRequiredForPermit.length &&
132
132
  !hasConcessionProofs &&
133
133
  transaction.dataSource !== 'Post Office Sales' &&
134
- transaction.dataSource !== 'DDE File'
134
+ transaction.dataSource !== 'DDE File' &&
135
+ transaction.dataSource !== 'Postal Order Sales'
135
136
  ) {
136
137
  throw new Error(`The permit '${permission.permitId}' requires proof of concession however none were supplied`)
137
138
  } else if (!concessionsRequiredForPermit.length && hasConcessionProofs) {
@@ -20,12 +20,7 @@ import db from 'debug'
20
20
  const debug = db('sales:routes')
21
21
 
22
22
  const stagingIdSchema = Joi.object({
23
- id: Joi.string()
24
- .trim()
25
- .guid()
26
- .min(1)
27
- .required()
28
- .description('the staging identifier')
23
+ id: Joi.string().trim().guid().min(1).required().description('the staging identifier')
29
24
  }).label('finalise-transaction-request-parameters')
30
25
 
31
26
  export default [
@@ -8,13 +8,13 @@ Object {
8
8
  "concessions": "[{\\"type\\":\\"Blue Badge\\",\\"referenceNumber\\":\\"123456789\\"}]",
9
9
  "country": Object {
10
10
  "description": "GB-ENG",
11
- "id": 910400195,
12
- "label": "England",
11
+ "id": 1050,
12
+ "label": "uk_eng",
13
13
  },
14
14
  "dataSource": Object {
15
- "description": "Post Office Sales",
16
- "id": 910400000,
17
- "label": "Post Office Sales",
15
+ "description": "DDE File",
16
+ "id": 1020,
17
+ "label": "dde_file",
18
18
  },
19
19
  "email": "daniel-ricc@example.com",
20
20
  "errorMessage": "Error",
@@ -22,37 +22,41 @@ Object {
22
22
  "lastName": "Ricciardo",
23
23
  "methodOfPayment": Object {
24
24
  "description": "Cash",
25
- "id": 910400001,
26
- "label": "Cash",
25
+ "id": 1010,
26
+ "label": "cash",
27
27
  },
28
28
  "mobilePhone": "07722 123456",
29
29
  "organisation": "Fishy Endeavours",
30
- "paymentSource": "Post Office Sales",
30
+ "paymentSource": Object {
31
+ "description": "Direct Debit",
32
+ "id": 1040,
33
+ "label": "direct_debit",
34
+ },
31
35
  "permitId": "test-permit-id",
32
36
  "postalFulfilment": true,
33
37
  "postcode": "BS9 1HJ",
34
38
  "preferredMethodOfConfirmation": Object {
35
39
  "description": "Email",
36
- "id": 910400000,
37
- "label": "Email",
40
+ "id": 1030,
41
+ "label": "e-mail",
38
42
  },
39
43
  "preferredMethodOfNewsletter": Object {
40
44
  "description": "Prefer not to be contacted",
41
- "id": 910400003,
42
- "label": "Prefer not to be contacted",
45
+ "id": 1031,
46
+ "label": "prefer_no_contact",
43
47
  },
44
48
  "preferredMethodOfReminder": Object {
45
49
  "description": "Text",
46
- "id": 910400002,
47
- "label": "Text",
50
+ "id": 1032,
51
+ "label": "sms",
48
52
  },
49
53
  "premises": "14 Howecroft Court",
50
54
  "serialNumber": "14345-48457J",
51
55
  "startDate": "2021-06-15",
52
56
  "status": Object {
53
57
  "description": "Needs Review",
54
- "id": 910400000,
55
- "label": "Needs Review",
58
+ "id": 1000,
59
+ "label": "needs_review",
56
60
  },
57
61
  "street": "Eastmead Lane",
58
62
  "town": "Bristol",
@@ -72,7 +76,7 @@ Array [
72
76
  ]
73
77
  `;
74
78
 
75
- exports[`POCL validation error service updatePoclValidationError when validation error record exists and status equals "Processed" updates the validation record 1`] = `
79
+ exports[`POCL validation error service updatePoclValidationError when validation error record exists and status is not provided updates the validation record 1`] = `
76
80
  Object {
77
81
  "amount": 30,
78
82
  "birthDate": "1989-07-01",
@@ -80,13 +84,13 @@ Object {
80
84
  "concessions": "[{\\"type\\":\\"Blue Badge\\",\\"referenceNumber\\":\\"123456789\\"}]",
81
85
  "country": Object {
82
86
  "description": "GB-ENG",
83
- "id": 910400195,
84
- "label": "England",
87
+ "id": 1050,
88
+ "label": "uk_eng",
85
89
  },
86
90
  "dataSource": Object {
87
- "description": "Post Office Sales",
88
- "id": 910400000,
89
- "label": "Post Office Sales",
91
+ "description": "DDE File",
92
+ "id": 1020,
93
+ "label": "dde_file",
90
94
  },
91
95
  "email": "daniel-ricc@example.com",
92
96
  "errorMessage": "Invalid email address",
@@ -94,38 +98,43 @@ Object {
94
98
  "lastName": "Ricciardo",
95
99
  "methodOfPayment": Object {
96
100
  "description": "Cash",
97
- "id": 910400001,
98
- "label": "Cash",
101
+ "id": 1010,
102
+ "label": "cash",
99
103
  },
100
104
  "mobilePhone": "07722 123456",
101
105
  "organisation": "Fishy Endeavours",
102
- "paymentSource": "Post Office Sales",
106
+ "paymentSource": Object {
107
+ "description": "Direct Debit",
108
+ "id": 1040,
109
+ "label": "direct_debit",
110
+ },
111
+ "paymentSourceUnvalidated": "Direct Debit",
103
112
  "permitId": "test-permit-id",
104
113
  "postalFulfilment": true,
105
114
  "postcode": "BS9 1HJ",
106
115
  "preferredMethodOfConfirmation": Object {
107
116
  "description": "Email",
108
- "id": 910400000,
109
- "label": "Email",
117
+ "id": 1030,
118
+ "label": "e-mail",
110
119
  },
111
120
  "preferredMethodOfNewsletter": Object {
112
121
  "description": "Prefer not to be contacted",
113
- "id": 910400003,
114
- "label": "Prefer not to be contacted",
122
+ "id": 1031,
123
+ "label": "prefer_no_contact",
115
124
  },
116
125
  "preferredMethodOfReminder": Object {
117
126
  "description": "Text",
118
- "id": 910400002,
119
- "label": "Text",
127
+ "id": 1032,
128
+ "label": "sms",
120
129
  },
121
130
  "premises": "14 Howecroft Court",
122
131
  "serialNumber": "14345-48457J",
123
132
  "startDate": "2021-06-15",
124
- "stateCode": 1,
133
+ "startDateUnvalidated": "2021-06-15",
125
134
  "status": Object {
126
- "description": "Processed",
127
- "id": 910400002,
128
- "label": "Processed",
135
+ "description": "Needs Review",
136
+ "id": 1000,
137
+ "label": "needs_review",
129
138
  },
130
139
  "street": "Eastmead Lane",
131
140
  "timestamp": "2020-01-01T14:00:00Z",
@@ -135,7 +144,7 @@ Object {
135
144
  }
136
145
  `;
137
146
 
138
- exports[`POCL validation error service updatePoclValidationError when validation error record exists and status is not provided updates the validation record 1`] = `
147
+ exports[`POCL validation error service updatePoclValidationError when validation error record exists and status is processed updates the validation record 1`] = `
139
148
  Object {
140
149
  "amount": 30,
141
150
  "birthDate": "1989-07-01",
@@ -143,13 +152,13 @@ Object {
143
152
  "concessions": "[{\\"type\\":\\"Blue Badge\\",\\"referenceNumber\\":\\"123456789\\"}]",
144
153
  "country": Object {
145
154
  "description": "GB-ENG",
146
- "id": 910400195,
147
- "label": "England",
155
+ "id": 1050,
156
+ "label": "uk_eng",
148
157
  },
149
158
  "dataSource": Object {
150
- "description": "Post Office Sales",
151
- "id": 910400000,
152
- "label": "Post Office Sales",
159
+ "description": "DDE File",
160
+ "id": 1020,
161
+ "label": "dde_file",
153
162
  },
154
163
  "email": "daniel-ricc@example.com",
155
164
  "errorMessage": "Invalid email address",
@@ -157,37 +166,44 @@ Object {
157
166
  "lastName": "Ricciardo",
158
167
  "methodOfPayment": Object {
159
168
  "description": "Cash",
160
- "id": 910400001,
161
- "label": "Cash",
169
+ "id": 1010,
170
+ "label": "cash",
162
171
  },
163
172
  "mobilePhone": "07722 123456",
164
173
  "organisation": "Fishy Endeavours",
165
- "paymentSource": "Post Office Sales",
174
+ "paymentSource": Object {
175
+ "description": "Direct Debit",
176
+ "id": 1040,
177
+ "label": "direct_debit",
178
+ },
179
+ "paymentSourceUnvalidated": "Direct Debit",
166
180
  "permitId": "test-permit-id",
167
181
  "postalFulfilment": true,
168
182
  "postcode": "BS9 1HJ",
169
183
  "preferredMethodOfConfirmation": Object {
170
184
  "description": "Email",
171
- "id": 910400000,
172
- "label": "Email",
185
+ "id": 1030,
186
+ "label": "e-mail",
173
187
  },
174
188
  "preferredMethodOfNewsletter": Object {
175
189
  "description": "Prefer not to be contacted",
176
- "id": 910400003,
177
- "label": "Prefer not to be contacted",
190
+ "id": 1031,
191
+ "label": "prefer_no_contact",
178
192
  },
179
193
  "preferredMethodOfReminder": Object {
180
194
  "description": "Text",
181
- "id": 910400002,
182
- "label": "Text",
195
+ "id": 1032,
196
+ "label": "sms",
183
197
  },
184
198
  "premises": "14 Howecroft Court",
185
199
  "serialNumber": "14345-48457J",
186
200
  "startDate": "2021-06-15",
201
+ "startDateUnvalidated": "2021-06-15",
202
+ "stateCode": 1,
187
203
  "status": Object {
188
- "description": "Needs Review",
189
- "id": 910400000,
190
- "label": "Needs Review",
204
+ "description": "Processed",
205
+ "id": 1001,
206
+ "label": "processed",
191
207
  },
192
208
  "street": "Eastmead Lane",
193
209
  "timestamp": "2020-01-01T14:00:00Z",
@@ -14,7 +14,7 @@ jest.mock('@defra-fish/dynamics-lib', () => ({
14
14
  const getPayload = () => ({
15
15
  id: 'test-id',
16
16
  createTransactionPayload: {
17
- dataSource: 'Post Office Sales',
17
+ dataSource: 'DDE File',
18
18
  serialNumber: '14345-48457J',
19
19
  permissions: [
20
20
  {
@@ -46,7 +46,7 @@ const getPayload = () => ({
46
46
  payment: {
47
47
  timestamp: '2020-01-01T14:00:00Z',
48
48
  amount: 30,
49
- source: 'Post Office Sales',
49
+ source: 'Direct Debit',
50
50
  channelId: '948594',
51
51
  method: 'Cash'
52
52
  }
@@ -64,91 +64,162 @@ const getValidationError = payload => ({
64
64
  dataSource: payload.createTransactionPayload.serialNumber.dataSource,
65
65
  transactionDate: payload.createTransactionPayload.permissions[0].issueDate,
66
66
  permitId: payload.createTransactionPayload.permissions[0].permitId,
67
- startDate: payload.createTransactionPayload.permissions[0].startDate,
67
+ startDateUnvalidated: payload.createTransactionPayload.permissions[0].startDate,
68
+ startDate: payload.createTransactionPayload.permissions[0].newStartDate,
68
69
  concessions: JSON.stringify(payload.createTransactionPayload.permissions[0].concessions),
69
70
  timestamp: payload.finaliseTransactionPayload.payment.timestamp,
70
71
  amount: payload.finaliseTransactionPayload.payment.amount,
71
72
  channelId: payload.finaliseTransactionPayload.payment.channelId,
72
- paymentSource: payload.finaliseTransactionPayload.payment.source,
73
+ paymentSource: payload.finaliseTransactionPayload.payment.newPaymentSource,
74
+ paymentSourceUnvalidated: payload.finaliseTransactionPayload.payment.source,
73
75
  methodOfPayment: payload.finaliseTransactionPayload.payment.method,
74
76
  status: 'Ready for Processing',
75
77
  errorMessage: payload.errorMessage
76
78
  })
77
79
 
80
+ jest.mock('../../reference-data.service.js', () => ({
81
+ getGlobalOptionSetValue: async (name, lookup) => {
82
+ const optionSets = {
83
+ defra_poclvalidationerrorstatus: [
84
+ { id: 1000, label: 'needs_review', description: 'Needs Review' },
85
+ { id: 1001, label: 'processed', description: 'Processed' },
86
+ { id: 1002, label: 'ready_for_processing', description: 'Ready for Processing' }
87
+ ],
88
+ defra_paymenttype: [{ id: 1010, label: 'cash', description: 'Cash' }],
89
+ defra_datasource: [{ id: 1020, label: 'dde_file', description: 'DDE File' }],
90
+ defra_preferredcontactmethod: [
91
+ { id: 1030, label: 'e-mail', description: 'Email' },
92
+ { id: 1031, label: 'prefer_no_contact', description: 'Prefer not to be contacted' },
93
+ { id: 1032, label: 'sms', description: 'Text' }
94
+ ],
95
+ defra_financialtransactionsource: [{ id: 1040, label: 'direct_debit', description: 'Direct Debit' }],
96
+ defra_country: [{ id: 1050, label: 'uk_eng', description: 'GB-ENG' }]
97
+ }
98
+ const optionSet = optionSets[name].find(os => os.description === lookup)
99
+ if (optionSet) {
100
+ return optionSet
101
+ }
102
+ }
103
+ }))
104
+
78
105
  describe('POCL validation error service', () => {
106
+ beforeAll(() => {
107
+ findById.mockImplementation(() => getValidationError(getPayload()))
108
+ })
79
109
  beforeEach(jest.clearAllMocks)
80
110
 
81
111
  describe('createPoclValidationError', () => {
82
- let payload
83
- beforeEach(async () => {
84
- payload = getPayload()
112
+ const getPayloadWithoutTransactionFile = () => {
113
+ const payload = getPayload()
85
114
  delete payload.finaliseTransactionPayload.transactionFile
86
- await createPoclValidationError(payload, 'test-pocl-file.xml')
87
- })
115
+ return payload
116
+ }
88
117
 
89
118
  it('maps the record to an instance of PoclValidationError', async () => {
119
+ await createPoclValidationError(getPayloadWithoutTransactionFile(), 'test-pocl-file.xml')
90
120
  const [[[poclValidationError]]] = persist.mock.calls
91
121
  expect(poclValidationError).toBeInstanceOf(PoclValidationError)
92
122
  })
93
123
 
94
124
  it('creates the validation record', async () => {
125
+ await createPoclValidationError(getPayloadWithoutTransactionFile(), 'test-pocl-file.xml')
95
126
  const [[[poclValidationError]]] = persist.mock.calls
96
127
  expect(poclValidationError).toMatchSnapshot()
97
128
  })
98
129
  })
99
130
 
100
131
  describe('updatePoclValidationError', () => {
101
- let payload
102
- beforeEach(async () => {
103
- payload = getPayload()
132
+ const getPayloadWithoutCreateTransactionError = () => {
133
+ const payload = getPayload()
104
134
  delete payload.createTransactionError
105
135
  payload.errorMessage = 'Invalid email address'
106
- })
136
+ return payload
137
+ }
107
138
 
108
139
  describe('when validation error record exists', () => {
109
- let poclValidationError
110
- beforeEach(async () => {
111
- findById.mockResolvedValue(getValidationError(payload))
140
+ it('retrieves existing record', async () => {
141
+ const payload = getPayloadWithoutCreateTransactionError()
142
+
112
143
  await updatePoclValidationError('pocl-validation-error-id', payload)
113
- poclValidationError = persist.mock.calls[0][0][0]
114
- })
115
144
 
116
- it('retrieves existing record', async () => {
117
145
  expect(findById).toBeCalledWith(PoclValidationError, 'pocl-validation-error-id')
118
146
  })
119
147
 
148
+ it('maps a country not in optionset to countryUnvalidated', async () => {
149
+ const payload = getPayload()
150
+ payload.createTransactionPayload.permissions[0].licensee.country = 'WAK'
151
+
152
+ await updatePoclValidationError('abc-123-def-456', payload)
153
+ const [[[poclValidationError]]] = persist.mock.calls
154
+ expect(poclValidationError.countryUnvalidated).toBe('WAK')
155
+ })
156
+
157
+ it('maps an invalid date to startDateUnvalidated', async () => {
158
+ const payload = getPayload()
159
+ payload.createTransactionPayload.permissions[0].startDate = '15/6/2021'
160
+
161
+ await updatePoclValidationError('abc-123-def-456', payload)
162
+ const [[[poclValidationError]]] = persist.mock.calls
163
+ expect(poclValidationError.startDateUnvalidated).toBe('15/6/2021')
164
+ })
165
+
120
166
  describe('and status is not provided', () => {
121
167
  it('sets the status to "Needs Review"', async () => {
122
- expect(poclValidationError.status.label).toBe('Needs Review')
168
+ const validationErrorNeedsReview = await getGlobalOptionSetValue('defra_poclvalidationerrorstatus', 'Needs Review')
169
+ const payload = getPayloadWithoutCreateTransactionError()
170
+
171
+ await updatePoclValidationError('pocl-validation-error-id', payload)
172
+
173
+ const [[[poclValidationError]]] = persist.mock.calls
174
+ expect(poclValidationError.status.label).toBe(validationErrorNeedsReview.label)
123
175
  })
124
176
 
125
177
  it('the state code is not set', async () => {
178
+ const payload = getPayloadWithoutCreateTransactionError()
179
+
180
+ await updatePoclValidationError('pocl-validation-error-id', payload)
181
+
182
+ const [[[poclValidationError]]] = persist.mock.calls
126
183
  expect(poclValidationError.stateCode).toBe(undefined)
127
184
  })
128
185
 
129
186
  it('updates the validation record', async () => {
187
+ const payload = getPayloadWithoutCreateTransactionError()
188
+
189
+ await updatePoclValidationError('pocl-validation-error-id', payload)
190
+
191
+ const [[[poclValidationError]]] = persist.mock.calls
130
192
  expect(poclValidationError).toMatchSnapshot()
131
193
  })
132
194
  })
133
195
 
134
- describe('and status equals "Processed"', () => {
135
- beforeEach(async () => {
196
+ describe('and status is processed', () => {
197
+ const getProcessedPayload = () => {
198
+ const payload = getPayloadWithoutCreateTransactionError()
136
199
  payload.status = 'Processed'
137
- await updatePoclValidationError('pocl-validation-error-id', payload)
138
- })
200
+ return payload
201
+ }
139
202
 
140
- it('the status is set to "Processed"', async () => {
203
+ const updateAndRetrieveError = async () => {
204
+ const payload = getProcessedPayload()
205
+ await updatePoclValidationError('pocl-validation-error-id', payload)
141
206
  const [[[poclValidationError]]] = persist.mock.calls
142
- expect(poclValidationError.status.label).toBe('Processed')
207
+ return poclValidationError
208
+ }
209
+
210
+ it('the status is set to processed', async () => {
211
+ const validationErrorProcessed = await getGlobalOptionSetValue('defra_poclvalidationerrorstatus', 'Processed')
212
+ const poclValidationError = await updateAndRetrieveError()
213
+ expect(poclValidationError.status.label).toBe(validationErrorProcessed.label)
143
214
  })
144
215
 
145
216
  it('the state code is set to 1', async () => {
146
- const [[[poclValidationError]]] = persist.mock.calls
217
+ const poclValidationError = await updateAndRetrieveError()
147
218
  expect(poclValidationError.stateCode).toBe(1)
148
219
  })
149
220
 
150
221
  it('updates the validation record', async () => {
151
- const [[[poclValidationError]]] = persist.mock.calls
222
+ const poclValidationError = await updateAndRetrieveError()
152
223
  expect(poclValidationError).toMatchSnapshot()
153
224
  })
154
225
  })
@@ -156,18 +227,18 @@ describe('POCL validation error service', () => {
156
227
 
157
228
  describe('when the validation error record does not exist', () => {
158
229
  beforeEach(async () => {
159
- findById.mockResolvedValue(null)
230
+ findById.mockResolvedValueOnce(null)
160
231
  })
161
232
 
162
233
  it('throws a 404 error', async () => {
163
- await expect(updatePoclValidationError('pocl-validation-error-id', payload)).rejects.toEqual(
234
+ await expect(updatePoclValidationError('pocl-validation-error-id', getPayloadWithoutCreateTransactionError())).rejects.toEqual(
164
235
  Boom.notFound('A POCL validation error with the given identifier could not be found')
165
236
  )
166
237
  })
167
238
 
168
239
  it('does not call persist to update record', async () => {
169
240
  try {
170
- await updatePoclValidationError('pocl-validation-error-id', payload)
241
+ await updatePoclValidationError('pocl-validation-error-id', getPayloadWithoutCreateTransactionError())
171
242
  } catch (err) {}
172
243
  expect(persist).not.toBeCalled()
173
244
  })
@@ -175,9 +246,7 @@ describe('POCL validation error service', () => {
175
246
  })
176
247
 
177
248
  describe('getPoclValidationErrors', () => {
178
- let status, result
179
- beforeEach(async () => {
180
- status = await await getGlobalOptionSetValue(PoclValidationError.definition.mappings.status.ref, 'Ready for Processing')
249
+ beforeAll(async () => {
181
250
  findPoclValidationErrors.mockReturnValue({ foo: 'bar' })
182
251
  executeQuery.mockResolvedValue([
183
252
  {
@@ -189,18 +258,21 @@ describe('POCL validation error service', () => {
189
258
  entity: { another: 'result' }
190
259
  }
191
260
  ])
192
- result = await getPoclValidationErrors()
193
261
  })
194
262
 
195
263
  it('passes the "Ready for Processing" status to the findPoclValidationErrors query', async () => {
264
+ const status = await getGlobalOptionSetValue(PoclValidationError.definition.mappings.status.ref, 'Ready for Processing')
265
+ await getPoclValidationErrors()
196
266
  expect(findPoclValidationErrors).toHaveBeenCalledWith(status)
197
267
  })
198
268
 
199
269
  it('executes the output of the Pocl query', async () => {
270
+ await getPoclValidationErrors()
200
271
  expect(executeQuery).toHaveBeenCalledWith({ foo: 'bar' })
201
272
  })
202
273
 
203
274
  it('returns the entities retrieved from Dynamics', async () => {
275
+ const result = await getPoclValidationErrors()
204
276
  expect(result).toMatchSnapshot()
205
277
  })
206
278
  })
@@ -42,6 +42,15 @@ const mapRecordPayload = async (record, transactionFile = null) => {
42
42
  permissions: [permission]
43
43
  } = record.createTransactionPayload
44
44
  const { licensee, issueDate: transactionDate, concessions, ...otherPermissionData } = permission
45
+ const { source: paymentSource } = record.finaliseTransactionPayload.payment
46
+ const country = await getGlobalOptionSetValue(PoclValidationError.definition.mappings.country.ref, licensee.country)
47
+ if (!country) {
48
+ licensee.countryUnvalidated = licensee.country
49
+ }
50
+ if (Number.isNaN(Date.parse(otherPermissionData.startDate))) {
51
+ otherPermissionData.startDateUnvalidated = otherPermissionData.startDate
52
+ }
53
+
45
54
  return {
46
55
  serialNumber,
47
56
  transactionDate,
@@ -65,6 +74,7 @@ const mapRecordPayload = async (record, transactionFile = null) => {
65
74
  PoclValidationError.definition.mappings.preferredMethodOfReminder.ref,
66
75
  licensee.preferredMethodOfReminder
67
76
  ),
77
+ paymentSource: await getGlobalOptionSetValue(PoclValidationError.definition.mappings.paymentSource.ref, paymentSource),
68
78
  country: await getGlobalOptionSetValue(PoclValidationError.definition.mappings.country.ref, licensee.country)
69
79
  }
70
80
  }