@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 +5 -5
- package/src/schema/staging-exception.schema.js +9 -5
- package/src/schema/validators/__tests__/validators.spec.js +21 -0
- package/src/schema/validators/validators.js +2 -1
- package/src/server/routes/transactions.js +1 -6
- package/src/services/exceptions/__tests__/__snapshots__/pocl-validation-errors.service.spec.js.snap +69 -53
- package/src/services/exceptions/__tests__/pocl-validation-errors.service.spec.js +107 -35
- package/src/services/exceptions/pocl-validation-errors.service.js +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/sales-api-service",
|
|
3
|
-
"version": "1.35.0
|
|
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
|
|
39
|
-
"@defra-fish/connectors-lib": "1.35.0
|
|
40
|
-
"@defra-fish/dynamics-lib": "1.35.0
|
|
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": "
|
|
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(
|
|
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', '
|
|
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(
|
|
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().
|
|
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().
|
|
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 [
|
package/src/services/exceptions/__tests__/__snapshots__/pocl-validation-errors.service.spec.js.snap
CHANGED
|
@@ -8,13 +8,13 @@ Object {
|
|
|
8
8
|
"concessions": "[{\\"type\\":\\"Blue Badge\\",\\"referenceNumber\\":\\"123456789\\"}]",
|
|
9
9
|
"country": Object {
|
|
10
10
|
"description": "GB-ENG",
|
|
11
|
-
"id":
|
|
12
|
-
"label": "
|
|
11
|
+
"id": 1050,
|
|
12
|
+
"label": "uk_eng",
|
|
13
13
|
},
|
|
14
14
|
"dataSource": Object {
|
|
15
|
-
"description": "
|
|
16
|
-
"id":
|
|
17
|
-
"label": "
|
|
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":
|
|
26
|
-
"label": "
|
|
25
|
+
"id": 1010,
|
|
26
|
+
"label": "cash",
|
|
27
27
|
},
|
|
28
28
|
"mobilePhone": "07722 123456",
|
|
29
29
|
"organisation": "Fishy Endeavours",
|
|
30
|
-
"paymentSource":
|
|
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":
|
|
37
|
-
"label": "
|
|
40
|
+
"id": 1030,
|
|
41
|
+
"label": "e-mail",
|
|
38
42
|
},
|
|
39
43
|
"preferredMethodOfNewsletter": Object {
|
|
40
44
|
"description": "Prefer not to be contacted",
|
|
41
|
-
"id":
|
|
42
|
-
"label": "
|
|
45
|
+
"id": 1031,
|
|
46
|
+
"label": "prefer_no_contact",
|
|
43
47
|
},
|
|
44
48
|
"preferredMethodOfReminder": Object {
|
|
45
49
|
"description": "Text",
|
|
46
|
-
"id":
|
|
47
|
-
"label": "
|
|
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":
|
|
55
|
-
"label": "
|
|
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
|
|
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":
|
|
84
|
-
"label": "
|
|
87
|
+
"id": 1050,
|
|
88
|
+
"label": "uk_eng",
|
|
85
89
|
},
|
|
86
90
|
"dataSource": Object {
|
|
87
|
-
"description": "
|
|
88
|
-
"id":
|
|
89
|
-
"label": "
|
|
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":
|
|
98
|
-
"label": "
|
|
101
|
+
"id": 1010,
|
|
102
|
+
"label": "cash",
|
|
99
103
|
},
|
|
100
104
|
"mobilePhone": "07722 123456",
|
|
101
105
|
"organisation": "Fishy Endeavours",
|
|
102
|
-
"paymentSource":
|
|
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":
|
|
109
|
-
"label": "
|
|
117
|
+
"id": 1030,
|
|
118
|
+
"label": "e-mail",
|
|
110
119
|
},
|
|
111
120
|
"preferredMethodOfNewsletter": Object {
|
|
112
121
|
"description": "Prefer not to be contacted",
|
|
113
|
-
"id":
|
|
114
|
-
"label": "
|
|
122
|
+
"id": 1031,
|
|
123
|
+
"label": "prefer_no_contact",
|
|
115
124
|
},
|
|
116
125
|
"preferredMethodOfReminder": Object {
|
|
117
126
|
"description": "Text",
|
|
118
|
-
"id":
|
|
119
|
-
"label": "
|
|
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
|
-
"
|
|
133
|
+
"startDateUnvalidated": "2021-06-15",
|
|
125
134
|
"status": Object {
|
|
126
|
-
"description": "
|
|
127
|
-
"id":
|
|
128
|
-
"label": "
|
|
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
|
|
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":
|
|
147
|
-
"label": "
|
|
155
|
+
"id": 1050,
|
|
156
|
+
"label": "uk_eng",
|
|
148
157
|
},
|
|
149
158
|
"dataSource": Object {
|
|
150
|
-
"description": "
|
|
151
|
-
"id":
|
|
152
|
-
"label": "
|
|
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":
|
|
161
|
-
"label": "
|
|
169
|
+
"id": 1010,
|
|
170
|
+
"label": "cash",
|
|
162
171
|
},
|
|
163
172
|
"mobilePhone": "07722 123456",
|
|
164
173
|
"organisation": "Fishy Endeavours",
|
|
165
|
-
"paymentSource":
|
|
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":
|
|
172
|
-
"label": "
|
|
185
|
+
"id": 1030,
|
|
186
|
+
"label": "e-mail",
|
|
173
187
|
},
|
|
174
188
|
"preferredMethodOfNewsletter": Object {
|
|
175
189
|
"description": "Prefer not to be contacted",
|
|
176
|
-
"id":
|
|
177
|
-
"label": "
|
|
190
|
+
"id": 1031,
|
|
191
|
+
"label": "prefer_no_contact",
|
|
178
192
|
},
|
|
179
193
|
"preferredMethodOfReminder": Object {
|
|
180
194
|
"description": "Text",
|
|
181
|
-
"id":
|
|
182
|
-
"label": "
|
|
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": "
|
|
189
|
-
"id":
|
|
190
|
-
"label": "
|
|
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: '
|
|
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: '
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
payload = getPayload()
|
|
112
|
+
const getPayloadWithoutTransactionFile = () => {
|
|
113
|
+
const payload = getPayload()
|
|
85
114
|
delete payload.finaliseTransactionPayload.transactionFile
|
|
86
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
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
|
|
135
|
-
|
|
196
|
+
describe('and status is processed', () => {
|
|
197
|
+
const getProcessedPayload = () => {
|
|
198
|
+
const payload = getPayloadWithoutCreateTransactionError()
|
|
136
199
|
payload.status = 'Processed'
|
|
137
|
-
|
|
138
|
-
}
|
|
200
|
+
return payload
|
|
201
|
+
}
|
|
139
202
|
|
|
140
|
-
|
|
203
|
+
const updateAndRetrieveError = async () => {
|
|
204
|
+
const payload = getProcessedPayload()
|
|
205
|
+
await updatePoclValidationError('pocl-validation-error-id', payload)
|
|
141
206
|
const [[[poclValidationError]]] = persist.mock.calls
|
|
142
|
-
|
|
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
|
|
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
|
|
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.
|
|
230
|
+
findById.mockResolvedValueOnce(null)
|
|
160
231
|
})
|
|
161
232
|
|
|
162
233
|
it('throws a 404 error', async () => {
|
|
163
|
-
await expect(updatePoclValidationError('pocl-validation-error-id',
|
|
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',
|
|
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
|
-
|
|
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
|
}
|