@defra-fish/sales-api-service 1.49.0-rc.4 → 1.49.0-rc.6
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/validators/validators.js +1 -3
- package/src/server/routes/__tests__/__snapshots__/renewals.spec.js.snap +87 -0
- package/src/server/routes/__tests__/renewals.spec.js +23 -8
- package/src/server/routes/renewals.js +15 -6
- package/src/services/__tests__/concession.service.spec.js +315 -0
- package/src/services/__tests__/permit.service.spec.js +131 -0
- package/src/services/concession.service.js +61 -0
- package/src/services/constants.js +13 -0
- package/src/services/permit.service.js +41 -0
- package/src/services/renewals/__tests__/renewals.service.spec.js +99 -8
- package/src/services/renewals/renewals.service.js +31 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/sales-api-service",
|
|
3
|
-
"version": "1.49.0-rc.
|
|
3
|
+
"version": "1.49.0-rc.6",
|
|
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.49.0-rc.
|
|
39
|
-
"@defra-fish/connectors-lib": "1.49.0-rc.
|
|
40
|
-
"@defra-fish/dynamics-lib": "1.49.0-rc.
|
|
38
|
+
"@defra-fish/business-rules-lib": "1.49.0-rc.6",
|
|
39
|
+
"@defra-fish/connectors-lib": "1.49.0-rc.6",
|
|
40
|
+
"@defra-fish/dynamics-lib": "1.49.0-rc.6",
|
|
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": "fc3df7fb041ef8127454aee7c535b85f2e04114a"
|
|
56
56
|
}
|
|
@@ -130,9 +130,7 @@ const validatePermissionConcession = async (permission, transaction) => {
|
|
|
130
130
|
if (
|
|
131
131
|
concessionsRequiredForPermit.length &&
|
|
132
132
|
!hasConcessionProofs &&
|
|
133
|
-
|
|
134
|
-
transaction.dataSource !== 'DDE File' &&
|
|
135
|
-
transaction.dataSource !== 'Postal Order Sales'
|
|
133
|
+
!['Post Office Sales', 'DDE File', 'Postal Order Sales'].includes(transaction.dataSource)
|
|
136
134
|
) {
|
|
137
135
|
throw new Error(`The permit '${permission.permitId}' requires proof of concession however none were supplied`)
|
|
138
136
|
} else if (!concessionsRequiredForPermit.length && hasConcessionProofs) {
|
|
@@ -453,3 +453,90 @@ Object {
|
|
|
453
453
|
},
|
|
454
454
|
}
|
|
455
455
|
`;
|
|
456
|
+
|
|
457
|
+
exports[`permissionRenewalData should call preparePermissionDataForRenewal with the expected data 1`] = `
|
|
458
|
+
[MockFunction] {
|
|
459
|
+
"calls": Array [
|
|
460
|
+
Array [
|
|
461
|
+
Object {
|
|
462
|
+
"concessions": Array [
|
|
463
|
+
Object {
|
|
464
|
+
"id": "d0ece997-ef65-e611-80dc-c4346bad4004",
|
|
465
|
+
"name": "Senior",
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
"dataSource": Object {
|
|
469
|
+
"description": "Web Sales",
|
|
470
|
+
"id": 910400003,
|
|
471
|
+
"label": "Web Sales",
|
|
472
|
+
},
|
|
473
|
+
"endDate": "2020-12-13T23:59:59Z",
|
|
474
|
+
"id": "347a9083-361e-ea11-a810-000d3a25c5d6",
|
|
475
|
+
"issueDate": "2019-12-13T09:00:00Z",
|
|
476
|
+
"licensee": Object {
|
|
477
|
+
"birthDate": "1946-01-01",
|
|
478
|
+
"country": Object {
|
|
479
|
+
"description": "GB-ENG",
|
|
480
|
+
"id": 910400195,
|
|
481
|
+
"label": "England",
|
|
482
|
+
},
|
|
483
|
+
"email": "fester@tester.com",
|
|
484
|
+
"firstName": "Fester",
|
|
485
|
+
"id": "1329a866-d175-ea11-a811-000d3a64905b",
|
|
486
|
+
"lastName": "Tester",
|
|
487
|
+
"locality": "Testville",
|
|
488
|
+
"mobilePhone": "01234 567890",
|
|
489
|
+
"organisation": "Test Organisation",
|
|
490
|
+
"postalFulfilment": true,
|
|
491
|
+
"postcode": "AB12 3CD",
|
|
492
|
+
"preferredMethodOfConfirmation": Object {
|
|
493
|
+
"description": "Email",
|
|
494
|
+
"id": 910400000,
|
|
495
|
+
"label": "Email",
|
|
496
|
+
},
|
|
497
|
+
"premises": "1",
|
|
498
|
+
"street": "Tester Avenue",
|
|
499
|
+
"town": "Tersterton",
|
|
500
|
+
},
|
|
501
|
+
"permit": Object {
|
|
502
|
+
"availableFrom": "2017-03-31T23:00:00Z",
|
|
503
|
+
"availableTo": "2021-03-31T22:59:00Z",
|
|
504
|
+
"cost": 6,
|
|
505
|
+
"description": "Coarse 1 day 2 Rod Licence (Senior)",
|
|
506
|
+
"durationDesignator": Object {
|
|
507
|
+
"description": "D",
|
|
508
|
+
"id": 910400000,
|
|
509
|
+
"label": "Day(s)",
|
|
510
|
+
},
|
|
511
|
+
"durationMagnitude": 1,
|
|
512
|
+
"id": "9f1b34a0-0c66-e611-80dc-c4346bad0190",
|
|
513
|
+
"isCounterSales": true,
|
|
514
|
+
"isForFulfilment": false,
|
|
515
|
+
"isRecurringPaymentSupported": false,
|
|
516
|
+
"itemId": "42290",
|
|
517
|
+
"numberOfRods": 2,
|
|
518
|
+
"permitSubtype": Object {
|
|
519
|
+
"description": "C",
|
|
520
|
+
"id": 910400001,
|
|
521
|
+
"label": "Trout and coarse",
|
|
522
|
+
},
|
|
523
|
+
"permitType": Object {
|
|
524
|
+
"description": "Rod Fishing Licence",
|
|
525
|
+
"id": 910400000,
|
|
526
|
+
"label": "Rod Fishing Licence",
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
"referenceNumber": "00000000-2WC3FDR-CD379B",
|
|
530
|
+
"stagingId": "71ad9a25-2a03-406b-a0e3-f4ff37799374",
|
|
531
|
+
"startDate": "2019-12-14T00:00:00Z",
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
],
|
|
535
|
+
"results": Array [
|
|
536
|
+
Object {
|
|
537
|
+
"type": "return",
|
|
538
|
+
"value": undefined,
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
}
|
|
542
|
+
`;
|
|
@@ -16,6 +16,7 @@ jest.mock('../../../services/renewals/renewals.service.js', () => ({
|
|
|
16
16
|
|
|
17
17
|
jest.mock('@defra-fish/dynamics-lib', () => ({
|
|
18
18
|
...jest.requireActual('@defra-fish/dynamics-lib'),
|
|
19
|
+
concessionsByIds: jest.fn(),
|
|
19
20
|
permissionForFullReferenceNumber: jest.fn(),
|
|
20
21
|
executeQuery: jest.fn()
|
|
21
22
|
}))
|
|
@@ -32,16 +33,25 @@ const permissionForFullReferenceNumberMock = () => ({
|
|
|
32
33
|
entity: MOCK_EXISTING_PERMISSION_ENTITY,
|
|
33
34
|
expanded: {
|
|
34
35
|
licensee: { entity: MOCK_EXISTING_CONTACT_ENTITY, expanded: {} },
|
|
35
|
-
concessionProofs: [{ entity: MOCK_CONCESSION_PROOF_ENTITY
|
|
36
|
+
concessionProofs: [{ entity: MOCK_CONCESSION_PROOF_ENTITY }],
|
|
36
37
|
permit: { entity: MOCK_1DAY_SENIOR_PERMIT_ENTITY, expanded: {} }
|
|
37
38
|
}
|
|
38
39
|
})
|
|
39
40
|
|
|
41
|
+
const concessionMock = () => ({
|
|
42
|
+
expanded: {
|
|
43
|
+
concession: {
|
|
44
|
+
entity: MOCK_CONCESSION
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
40
49
|
describe('permissionRenewalData', () => {
|
|
41
50
|
beforeEach(jest.clearAllMocks)
|
|
42
51
|
|
|
43
52
|
it('should call permissionForFullReferenceNumber with referenceNumber', async () => {
|
|
44
53
|
executeQuery.mockResolvedValueOnce([permissionForFullReferenceNumberMock()])
|
|
54
|
+
executeQuery.mockResolvedValueOnce([concessionMock()])
|
|
45
55
|
|
|
46
56
|
const referenceNumber = 'REFERENCE123'
|
|
47
57
|
const request = getMockRequest(referenceNumber)
|
|
@@ -53,22 +63,27 @@ describe('permissionRenewalData', () => {
|
|
|
53
63
|
})
|
|
54
64
|
|
|
55
65
|
it('should call preparePermissionDataForRenewal with the expected data', async () => {
|
|
66
|
+
executeQuery.mockResolvedValueOnce([permissionForFullReferenceNumberMock()])
|
|
67
|
+
executeQuery.mockResolvedValueOnce([concessionMock()])
|
|
68
|
+
|
|
69
|
+
await permissionRenewalData[0].options.handler(getMockRequest(), getMockResponseToolkit())
|
|
70
|
+
|
|
71
|
+
expect(preparePermissionDataForRenewal).toMatchSnapshot()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('should set concessions to an empty array if concessions is empty', async () => {
|
|
56
75
|
const permissionMock = permissionForFullReferenceNumberMock()
|
|
76
|
+
permissionMock.expanded.concessionProofs = []
|
|
57
77
|
executeQuery.mockResolvedValueOnce([permissionMock])
|
|
58
78
|
|
|
59
79
|
await permissionRenewalData[0].options.handler(getMockRequest(), getMockResponseToolkit())
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
...permissionMock.entity.toJSON(),
|
|
63
|
-
licensee: permissionMock.expanded.licensee.entity.toJSON(),
|
|
64
|
-
concessions: [],
|
|
65
|
-
permit: permissionMock.expanded.permit.entity.toJSON()
|
|
66
|
-
}
|
|
67
|
-
expect(preparePermissionDataForRenewal).toHaveBeenCalledWith(expectedData)
|
|
81
|
+
expect(preparePermissionDataForRenewal.mock.calls[0][0].concessions).toEqual([])
|
|
68
82
|
})
|
|
69
83
|
|
|
70
84
|
it('should return continue response', async () => {
|
|
71
85
|
executeQuery.mockResolvedValueOnce([permissionForFullReferenceNumberMock()])
|
|
86
|
+
executeQuery.mockResolvedValueOnce([concessionMock()])
|
|
72
87
|
const request = getMockRequest({})
|
|
73
88
|
const responseToolkit = getMockResponseToolkit()
|
|
74
89
|
|
|
@@ -2,7 +2,7 @@ import Boom from '@hapi/boom'
|
|
|
2
2
|
import { preparePermissionDataForRenewal } from '../../services/renewals/renewals.service.js'
|
|
3
3
|
import { permissionRenewalDataRequestParamsSchema, permissionRenewalDataResponseSchema } from '../../schema/renewals.schema.js'
|
|
4
4
|
import db from 'debug'
|
|
5
|
-
import { permissionForFullReferenceNumber, executeQuery } from '@defra-fish/dynamics-lib'
|
|
5
|
+
import { concessionsByIds, permissionForFullReferenceNumber, executeQuery } from '@defra-fish/dynamics-lib'
|
|
6
6
|
const debug = db('sales:permission-renewal-data')
|
|
7
7
|
|
|
8
8
|
const executeWithErrorLog = async query => {
|
|
@@ -14,6 +14,14 @@ const executeWithErrorLog = async query => {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const getConcessions = async permission => {
|
|
18
|
+
if (permission.expanded.concessionProofs.length) {
|
|
19
|
+
const concessionProofs = await executeWithErrorLog(concessionsByIds(permission.expanded.concessionProofs.map(cp => cp.entity.id)))
|
|
20
|
+
return concessionProofs.map(cp => cp.expanded.concession.entity.toJSON())
|
|
21
|
+
}
|
|
22
|
+
return []
|
|
23
|
+
}
|
|
24
|
+
|
|
17
25
|
export default [
|
|
18
26
|
{
|
|
19
27
|
method: 'GET',
|
|
@@ -23,11 +31,12 @@ export default [
|
|
|
23
31
|
const results = await executeWithErrorLog(permissionForFullReferenceNumber(request.params.referenceNumber))
|
|
24
32
|
|
|
25
33
|
if (results.length === 1) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
const [permission] = results
|
|
35
|
+
const permissionData = await preparePermissionDataForRenewal({
|
|
36
|
+
...permission.entity.toJSON(),
|
|
37
|
+
licensee: permission.expanded.licensee.entity.toJSON(),
|
|
38
|
+
concessions: await getConcessions(permission),
|
|
39
|
+
permit: permission.expanded.permit.entity.toJSON()
|
|
31
40
|
})
|
|
32
41
|
return h.response(permissionData)
|
|
33
42
|
} else if (results.length === 0) {
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import * as concessionService from '../concession.service.js'
|
|
2
|
+
import { CONCESSION, CONCESSION_PROOF } from '../constants.js'
|
|
3
|
+
import { getReferenceDataForEntity, getReferenceDataForEntityAndId } from '../reference-data.service.js'
|
|
4
|
+
|
|
5
|
+
jest.mock('@defra-fish/connectors-lib')
|
|
6
|
+
jest.mock('../reference-data.service.js')
|
|
7
|
+
|
|
8
|
+
getReferenceDataForEntity.mockImplementation(() => [
|
|
9
|
+
{
|
|
10
|
+
id: 'aaa-111-bbb-222',
|
|
11
|
+
name: CONCESSION.JUNIOR
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'ccc-333-ddd-444',
|
|
15
|
+
name: CONCESSION.SENIOR
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'eee-555-fff-666',
|
|
19
|
+
name: CONCESSION.DISABLED
|
|
20
|
+
}
|
|
21
|
+
])
|
|
22
|
+
|
|
23
|
+
getReferenceDataForEntityAndId.mockImplementation((_e, id) => {
|
|
24
|
+
if (id === 'aaa-111-bbb-222') {
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
name: CONCESSION.JUNIOR
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (id === 'ccc-333-ddd-444') {
|
|
31
|
+
return {
|
|
32
|
+
id,
|
|
33
|
+
name: CONCESSION.SENIOR
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (id === 'eee-555-fff-666') {
|
|
37
|
+
return {
|
|
38
|
+
id,
|
|
39
|
+
name: CONCESSION.DISABLED
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
throw Error('Unrecognised concession id')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const getMockPermission = () => ({})
|
|
46
|
+
|
|
47
|
+
const getJuniorConcession = () => ({
|
|
48
|
+
id: 'aaa-111-bbb-222',
|
|
49
|
+
name: CONCESSION.JUNIOR,
|
|
50
|
+
proof: {
|
|
51
|
+
type: CONCESSION_PROOF.none
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const getSeniorConcession = () => ({
|
|
56
|
+
id: 'ccc-333-ddd-444',
|
|
57
|
+
name: CONCESSION.SENIOR,
|
|
58
|
+
proof: {
|
|
59
|
+
type: CONCESSION_PROOF.none
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const getDisabledBlueBadgeConcession = () => ({
|
|
64
|
+
id: 'eee-555-fff-666',
|
|
65
|
+
name: CONCESSION.DISABLED,
|
|
66
|
+
proof: {
|
|
67
|
+
type: CONCESSION_PROOF.blueBadge,
|
|
68
|
+
referenceNumber: 'blue-badge-123'
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const getDisabledNiConcession = () => ({
|
|
73
|
+
id: 'eee-555-fff-666',
|
|
74
|
+
name: CONCESSION.DISABLED,
|
|
75
|
+
proof: {
|
|
76
|
+
type: CONCESSION_PROOF.NI,
|
|
77
|
+
referenceNumber: 'national-insurance-456'
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
describe('preparePermissionDataForRenewal', () => {
|
|
82
|
+
describe('Disabled', () => {
|
|
83
|
+
describe('addDisabled', () => {
|
|
84
|
+
it('add blue badge', async () => {
|
|
85
|
+
const permission = getMockPermission()
|
|
86
|
+
await concessionService.addDisabled(permission, CONCESSION_PROOF.blueBadge, 'bb-111')
|
|
87
|
+
expect(permission.concessions).toContainEqual(
|
|
88
|
+
expect.objectContaining({
|
|
89
|
+
id: 'eee-555-fff-666',
|
|
90
|
+
name: CONCESSION.DISABLED,
|
|
91
|
+
proof: {
|
|
92
|
+
type: CONCESSION_PROOF.blueBadge,
|
|
93
|
+
referenceNumber: 'bb-111'
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('add NI', async () => {
|
|
100
|
+
const permission = getMockPermission()
|
|
101
|
+
await concessionService.addDisabled(permission, CONCESSION_PROOF.NI, 'national-insurance-456')
|
|
102
|
+
expect(permission.concessions).toContainEqual(expect.objectContaining(getDisabledNiConcession()))
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('add blue badge to senior licence', async () => {
|
|
106
|
+
const permission = getMockPermission()
|
|
107
|
+
const seniorConcession = getSeniorConcession()
|
|
108
|
+
permission.concessions = [seniorConcession]
|
|
109
|
+
await concessionService.addDisabled(permission, CONCESSION_PROOF.blueBadge, 'blue-badge-123')
|
|
110
|
+
expect(permission.concessions).toEqual(
|
|
111
|
+
expect.arrayContaining([expect.objectContaining(getDisabledBlueBadgeConcession()), expect.objectContaining(seniorConcession)])
|
|
112
|
+
)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('add NI to senior licence', async () => {
|
|
116
|
+
const permission = getMockPermission()
|
|
117
|
+
const seniorConcession = getSeniorConcession()
|
|
118
|
+
permission.concessions = [seniorConcession]
|
|
119
|
+
await concessionService.addDisabled(permission, CONCESSION_PROOF.NI, 'national-insurance-456')
|
|
120
|
+
expect(permission.concessions).toEqual(
|
|
121
|
+
expect.arrayContaining([expect.objectContaining(getDisabledNiConcession()), expect.objectContaining(seniorConcession)])
|
|
122
|
+
)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
describe('removeDisabled', () => {
|
|
127
|
+
it.each([
|
|
128
|
+
['blue badge', []],
|
|
129
|
+
['blue badge and senior', [getSeniorConcession()]]
|
|
130
|
+
])('remove disabled concession from array with %s concession(s)', async (_d, additionalConcessions) => {
|
|
131
|
+
const permission = getMockPermission()
|
|
132
|
+
const disabledConcession = getDisabledBlueBadgeConcession()
|
|
133
|
+
permission.concessions = [disabledConcession, ...additionalConcessions]
|
|
134
|
+
await concessionService.removeDisabled(permission)
|
|
135
|
+
expect(permission.concessions).toEqual(expect.not.arrayContaining([expect.objectContaining(disabledConcession)]))
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it.each([
|
|
139
|
+
['NI', []],
|
|
140
|
+
['NI and senior', [getSeniorConcession()]]
|
|
141
|
+
])('remove disabled concession from array with %s concession(s)', async (_d, additionalConcessions) => {
|
|
142
|
+
const permission = getMockPermission()
|
|
143
|
+
const disabledConcession = getDisabledNiConcession()
|
|
144
|
+
permission.concessions = [disabledConcession, ...additionalConcessions]
|
|
145
|
+
await concessionService.removeDisabled(permission)
|
|
146
|
+
expect(permission.concessions).toEqual(expect.not.arrayContaining([expect.objectContaining(disabledConcession)]))
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it.each([
|
|
150
|
+
['senior', 'blue badge', getSeniorConcession(), getDisabledBlueBadgeConcession()],
|
|
151
|
+
['junior', 'blue badge', getJuniorConcession(), getDisabledBlueBadgeConcession()],
|
|
152
|
+
['senior', 'NI', getSeniorConcession(), getDisabledNiConcession()],
|
|
153
|
+
['junior', 'NI', getJuniorConcession(), getDisabledNiConcession()]
|
|
154
|
+
])('leaves remaining %s concession when removing a disabled %s concession', async (_cd, _dcd, concession, disabledConcession) => {
|
|
155
|
+
const permission = getMockPermission()
|
|
156
|
+
permission.concessions = [disabledConcession, concession]
|
|
157
|
+
await concessionService.removeDisabled(permission)
|
|
158
|
+
expect(permission.concessions).toEqual(expect.arrayContaining([expect.objectContaining(concession)]))
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe('hasDisabled', () => {
|
|
163
|
+
it('returns true if have disabled blue badge', async () => {
|
|
164
|
+
const permission = getMockPermission()
|
|
165
|
+
permission.concessions = [getDisabledBlueBadgeConcession()]
|
|
166
|
+
const result = await concessionService.hasDisabled(permission)
|
|
167
|
+
expect(result).toBe(true)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('returns true if have disabled NI', async () => {
|
|
171
|
+
const permission = getMockPermission()
|
|
172
|
+
permission.concessions = [getDisabledNiConcession()]
|
|
173
|
+
const result = await concessionService.hasDisabled(permission)
|
|
174
|
+
expect(result).toBe(true)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('returns false if do not have disabled', async () => {
|
|
178
|
+
const permission = getMockPermission()
|
|
179
|
+
permission.concessions = []
|
|
180
|
+
const result = await concessionService.hasDisabled(permission)
|
|
181
|
+
expect(result).toBe(false)
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
describe('Senior', () => {
|
|
187
|
+
describe('addSenior', () => {
|
|
188
|
+
it('add concession', async () => {
|
|
189
|
+
const permission = getMockPermission()
|
|
190
|
+
await concessionService.addSenior(permission)
|
|
191
|
+
expect(permission.concessions).toContainEqual(getSeniorConcession())
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it("doesn't add second senior concession if one's already present", async () => {
|
|
195
|
+
const seniorConcession = getSeniorConcession()
|
|
196
|
+
const permission = getMockPermission()
|
|
197
|
+
permission.concessions = [seniorConcession]
|
|
198
|
+
await concessionService.addSenior(permission)
|
|
199
|
+
expect(permission.concessions).toEqual([expect.objectContaining(seniorConcession)])
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('add senior to blue badge', async () => {
|
|
203
|
+
const permission = getMockPermission()
|
|
204
|
+
const disabledConcession = getDisabledNiConcession()
|
|
205
|
+
permission.concessions = [disabledConcession]
|
|
206
|
+
await concessionService.addSenior(permission)
|
|
207
|
+
expect(permission.concessions).toEqual([disabledConcession, getSeniorConcession()])
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('add senior to NI', async () => {
|
|
211
|
+
const permission = getMockPermission()
|
|
212
|
+
const disabledConcession = getDisabledBlueBadgeConcession()
|
|
213
|
+
permission.concessions = [disabledConcession]
|
|
214
|
+
await concessionService.addSenior(permission)
|
|
215
|
+
expect(permission.concessions).toEqual([disabledConcession, getSeniorConcession()])
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
describe('removeSenior', () => {
|
|
220
|
+
it.each([
|
|
221
|
+
['has only a senior concession', [getSeniorConcession()], []],
|
|
222
|
+
[
|
|
223
|
+
'has senior and disabled concessions',
|
|
224
|
+
[getSeniorConcession(), getDisabledBlueBadgeConcession()],
|
|
225
|
+
[getDisabledBlueBadgeConcession()]
|
|
226
|
+
]
|
|
227
|
+
])('removes senior concession if permission %s', async (_desc, concessions, expectedConcessions) => {
|
|
228
|
+
const permission = getMockPermission()
|
|
229
|
+
permission.concessions = concessions
|
|
230
|
+
await concessionService.removeSenior(permission)
|
|
231
|
+
expect(permission.concessions).toEqual(expectedConcessions)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it.each([
|
|
235
|
+
['is empty', []],
|
|
236
|
+
['has junior concession', [getJuniorConcession()]],
|
|
237
|
+
['has junior and disabled concession', [getJuniorConcession(), getDisabledBlueBadgeConcession()]],
|
|
238
|
+
['has disabled concession', [getDisabledNiConcession()]]
|
|
239
|
+
])('leaves concessions unmodified if senior concession not present and concessions %s', async (_desc, concessions) => {
|
|
240
|
+
const permission = getMockPermission()
|
|
241
|
+
permission.concessions = concessions
|
|
242
|
+
await concessionService.removeSenior(permission)
|
|
243
|
+
expect(permission.concessions).toEqual(concessions)
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
describe('hasSenior', () => {
|
|
248
|
+
it.each(['senior'])('is true if licensee has senior concession', async () => {
|
|
249
|
+
const permission = getMockPermission()
|
|
250
|
+
permission.concessions = [getSeniorConcession()]
|
|
251
|
+
const isSenior = await concessionService.hasSenior(permission)
|
|
252
|
+
expect(isSenior).toBe(true)
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it.each([
|
|
256
|
+
['empty array', []],
|
|
257
|
+
['array with disabled concession', [getDisabledBlueBadgeConcession()]]
|
|
258
|
+
])("is false if licensee doesn't have senior concession in %s", async (_d, concessions) => {
|
|
259
|
+
const permission = getMockPermission()
|
|
260
|
+
permission.concessions = concessions
|
|
261
|
+
const isSenior = await concessionService.hasSenior(permission)
|
|
262
|
+
expect(isSenior).toBe(false)
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
describe('Junior', () => {
|
|
268
|
+
describe('removeJunior', () => {
|
|
269
|
+
it.each([
|
|
270
|
+
['has only a junior concession', [getJuniorConcession()], []],
|
|
271
|
+
[
|
|
272
|
+
'has junior and disabled concessions',
|
|
273
|
+
[getJuniorConcession(), getDisabledBlueBadgeConcession()],
|
|
274
|
+
[getDisabledBlueBadgeConcession()]
|
|
275
|
+
]
|
|
276
|
+
])('removes junior concession if concessions %s', async (_desc, concessions, expectedConcessions) => {
|
|
277
|
+
const permission = getMockPermission()
|
|
278
|
+
permission.concessions = concessions
|
|
279
|
+
await concessionService.removeJunior(permission)
|
|
280
|
+
expect(permission.concessions).toEqual(expectedConcessions)
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
it.each([
|
|
284
|
+
['is empty', []],
|
|
285
|
+
['has senior concession', [getSeniorConcession()]],
|
|
286
|
+
['has senior and disabled concession', [getSeniorConcession(), getDisabledBlueBadgeConcession()]],
|
|
287
|
+
['has disabled concession', [getDisabledNiConcession()]]
|
|
288
|
+
])('leaves concessions unmodified if junior concession not present and concessions %s', async (_desc, concessions) => {
|
|
289
|
+
const permission = getMockPermission()
|
|
290
|
+
permission.concessions = concessions
|
|
291
|
+
await concessionService.removeJunior(permission)
|
|
292
|
+
expect(permission.concessions).toEqual(concessions)
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
describe('hasJunior', () => {
|
|
297
|
+
it('returns true if permission has a junior concession', async () => {
|
|
298
|
+
const permission = getMockPermission()
|
|
299
|
+
permission.concessions = [getJuniorConcession()]
|
|
300
|
+
const result = await concessionService.hasJunior(permission)
|
|
301
|
+
expect(result).toBe(true)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it.each([
|
|
305
|
+
['empty array', []],
|
|
306
|
+
['array with disabled concession', [getDisabledBlueBadgeConcession()]]
|
|
307
|
+
])("is false if licensee doesn't have junior concession in %s", async (_d, concessions) => {
|
|
308
|
+
const permission = getMockPermission()
|
|
309
|
+
permission.concessions = concessions
|
|
310
|
+
const isJunior = await concessionService.hasJunior(permission)
|
|
311
|
+
expect(isJunior).toBe(false)
|
|
312
|
+
})
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
})
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { findPermit } from '../permit.service.js'
|
|
2
|
+
import { Permit, Concession, PermitConcession } from '@defra-fish/dynamics-lib'
|
|
3
|
+
import { getReferenceDataForEntity } from '../reference-data.service.js'
|
|
4
|
+
|
|
5
|
+
jest.mock('../reference-data.service.js')
|
|
6
|
+
|
|
7
|
+
const getSamplePermits = () => {
|
|
8
|
+
const samplePermits = [
|
|
9
|
+
{
|
|
10
|
+
id: 'prm-111',
|
|
11
|
+
numberOfRods: 1,
|
|
12
|
+
durationMagnitude: '12',
|
|
13
|
+
durationDesignator: { description: 'M' },
|
|
14
|
+
permitSubtype: { label: 'type-1' }
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'prm-222',
|
|
18
|
+
numberOfRods: 3,
|
|
19
|
+
durationMagnitude: '12',
|
|
20
|
+
durationDesignator: { description: 'M' },
|
|
21
|
+
permitSubtype: { label: 'type-2' }
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'prm-333',
|
|
25
|
+
numberOfRods: 1,
|
|
26
|
+
durationMagnitude: '12',
|
|
27
|
+
durationDesignator: { description: 'M' },
|
|
28
|
+
permitSubtype: { label: 'type-2' }
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'prm-444',
|
|
32
|
+
numberOfRods: 1,
|
|
33
|
+
durationMagnitude: '12',
|
|
34
|
+
durationDesignator: { description: 'M' },
|
|
35
|
+
permitSubtype: { label: 'type-3' }
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
return samplePermits.map(sp => ({
|
|
39
|
+
...sp,
|
|
40
|
+
toJSON: function () {
|
|
41
|
+
const props = {
|
|
42
|
+
...this
|
|
43
|
+
}
|
|
44
|
+
delete props.toJSON
|
|
45
|
+
return props
|
|
46
|
+
}
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const getSamplePermitConcessions = () => [{ permitId: 'prm-111', concessionId: 'con-111' }]
|
|
51
|
+
|
|
52
|
+
const getSampleConcessions = () => [
|
|
53
|
+
{ id: 'con-111', name: 'concession-type-1' },
|
|
54
|
+
{ id: 'con-222', name: 'concession-type-2' }
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
describe('findPermit', () => {
|
|
58
|
+
beforeAll(() => {
|
|
59
|
+
getReferenceDataForEntity.mockImplementation(async entity => {
|
|
60
|
+
if (entity === Permit) {
|
|
61
|
+
return getSamplePermits()
|
|
62
|
+
}
|
|
63
|
+
if (entity === PermitConcession) {
|
|
64
|
+
return getSamplePermitConcessions()
|
|
65
|
+
}
|
|
66
|
+
if (entity === Concession) {
|
|
67
|
+
return getSampleConcessions()
|
|
68
|
+
}
|
|
69
|
+
return []
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
const getSamplePermission = overrides => ({
|
|
73
|
+
permit: {
|
|
74
|
+
numberOfRods: '1',
|
|
75
|
+
permitSubtype: {
|
|
76
|
+
label: 'type-3'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
durationMagnitude: '12',
|
|
80
|
+
durationDesignator: { description: 'M' },
|
|
81
|
+
...overrides
|
|
82
|
+
})
|
|
83
|
+
const getSamplePermissionWithConcession = () => ({
|
|
84
|
+
concessions: [{ name: 'concession-type-1', id: 'abc-123', proof: {} }],
|
|
85
|
+
permit: {
|
|
86
|
+
numberOfRods: '1',
|
|
87
|
+
permitSubtype: {
|
|
88
|
+
label: 'type-1'
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const createExpectedPermit = ({
|
|
94
|
+
numberOfRods = 1,
|
|
95
|
+
durationMagnitude = '12',
|
|
96
|
+
durationDescription = 'M',
|
|
97
|
+
permitSubtypeLabel = 'type-3',
|
|
98
|
+
...overrides
|
|
99
|
+
} = {}) => ({
|
|
100
|
+
numberOfRods,
|
|
101
|
+
durationMagnitude,
|
|
102
|
+
durationDesignator: { description: durationDescription },
|
|
103
|
+
permitSubtype: { label: permitSubtypeLabel },
|
|
104
|
+
...overrides
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it.each`
|
|
108
|
+
description | expectedPermit | permission
|
|
109
|
+
${'concessions'} | ${createExpectedPermit({ id: 'prm-111', permitSubtypeLabel: 'type-1' })} | ${getSamplePermissionWithConcession()}
|
|
110
|
+
${'licence type'} | ${createExpectedPermit({ id: 'prm-444', permitSubtypeLabel: 'type-3' })} | ${getSamplePermission()}
|
|
111
|
+
${'number of rods'} | ${createExpectedPermit({ id: 'prm-222', numberOfRods: 3, permitSubtypeLabel: 'type-2' })} | ${getSamplePermission({ permit: { permitSubtype: { label: 'type-2' }, numberOfRods: '3' } })}
|
|
112
|
+
`('matches a permission to a permit on $description', async ({ expectedPermit, permission }) => {
|
|
113
|
+
const permit = await findPermit(permission)
|
|
114
|
+
expect(permit).toStrictEqual(expect.objectContaining(expectedPermit))
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it.each([
|
|
118
|
+
['with one element', [{ type: 'concession-type-1', id: 'con-111', proof: {} }]],
|
|
119
|
+
[
|
|
120
|
+
'with two elements, one',
|
|
121
|
+
[
|
|
122
|
+
{ name: 'concession-type-1', id: 'con-111', proof: {} },
|
|
123
|
+
{ type: 'concession-type-2', id: 'abc-123', proof: {} }
|
|
124
|
+
]
|
|
125
|
+
]
|
|
126
|
+
])('throws an error if concessions array %s containing type rather than name', async (_d, concessions) => {
|
|
127
|
+
const perm = getSamplePermissionWithConcession()
|
|
128
|
+
perm.concessions = concessions
|
|
129
|
+
await expect(() => findPermit(perm)).rejects.toThrow("Concession should contain 'name' not 'type'")
|
|
130
|
+
})
|
|
131
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CONCESSION, CONCESSION_PROOF } from './constants.js'
|
|
2
|
+
import { getReferenceDataForEntity } from './reference-data.service.js'
|
|
3
|
+
import { Concession } from '@defra-fish/dynamics-lib'
|
|
4
|
+
|
|
5
|
+
const getTypeConcessionId = async type => {
|
|
6
|
+
const concessions = await getReferenceDataForEntity(Concession)
|
|
7
|
+
const { id } = concessions.find(c => c.name === type)
|
|
8
|
+
return id
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const hasConcessionType = async (permission, type) => {
|
|
12
|
+
const id = await getTypeConcessionId(type)
|
|
13
|
+
return !!permission.concessions && permission.concessions.some(c => c.id === id)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const removeConcessionType = async (permission, type) => {
|
|
17
|
+
if (await hasConcessionType(permission, type)) {
|
|
18
|
+
const id = await getTypeConcessionId(type)
|
|
19
|
+
permission.concessions = permission.concessions.filter(c => c.id !== id)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const addDisabled = async (permission, concessionProof, referenceNumber) => {
|
|
24
|
+
await removeDisabled(permission)
|
|
25
|
+
if (!permission.concessions) {
|
|
26
|
+
permission.concessions = []
|
|
27
|
+
}
|
|
28
|
+
permission.concessions.push({
|
|
29
|
+
id: await getTypeConcessionId(CONCESSION.DISABLED),
|
|
30
|
+
name: CONCESSION.DISABLED,
|
|
31
|
+
proof: {
|
|
32
|
+
type: concessionProof,
|
|
33
|
+
referenceNumber
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const removeDisabled = permission => removeConcessionType(permission, CONCESSION.DISABLED)
|
|
39
|
+
export const hasDisabled = permission => hasConcessionType(permission, CONCESSION.DISABLED)
|
|
40
|
+
|
|
41
|
+
export const addSenior = async permission => {
|
|
42
|
+
if (!(await hasSenior(permission))) {
|
|
43
|
+
await removeJunior(permission)
|
|
44
|
+
if (!permission.concessions) {
|
|
45
|
+
permission.concessions = []
|
|
46
|
+
}
|
|
47
|
+
permission.concessions.push({
|
|
48
|
+
id: await getTypeConcessionId(CONCESSION.SENIOR),
|
|
49
|
+
name: CONCESSION.SENIOR,
|
|
50
|
+
proof: {
|
|
51
|
+
type: CONCESSION_PROOF.none
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const removeSenior = permission => removeConcessionType(permission, CONCESSION.SENIOR)
|
|
58
|
+
export const hasSenior = permission => hasConcessionType(permission, CONCESSION.SENIOR)
|
|
59
|
+
|
|
60
|
+
export const removeJunior = permission => removeConcessionType(permission, CONCESSION.JUNIOR)
|
|
61
|
+
export const hasJunior = permission => hasConcessionType(permission, CONCESSION.JUNIOR)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getReferenceDataForEntity } from './reference-data.service.js'
|
|
2
|
+
import { Permit, Concession, PermitConcession } from '@defra-fish/dynamics-lib'
|
|
3
|
+
|
|
4
|
+
export const findPermit = async existingPermission => {
|
|
5
|
+
const licenseeConcessions = existingPermission.concessions || []
|
|
6
|
+
const permitsJoinPermitConcessions = await getPermitsJoinPermitConcessions()
|
|
7
|
+
|
|
8
|
+
if (licenseeConcessions.some(c => !c.name && !!c.type)) {
|
|
9
|
+
throw new Error("Concession should contain 'name' not 'type'")
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Filter the joined list to include every and only those concessions in licenseeConcessions
|
|
13
|
+
const filteredPermitsJoinPermitConcessions = permitsJoinPermitConcessions.filter(
|
|
14
|
+
pjpc =>
|
|
15
|
+
licenseeConcessions.map(lc => lc.name).every(t => pjpc.concessions.map(c => c.name).includes(t)) &&
|
|
16
|
+
pjpc.concessions.length === licenseeConcessions.length
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
// Filter by the licence length
|
|
20
|
+
const byLicenceLength = filteredPermitsJoinPermitConcessions.filter(
|
|
21
|
+
p => String(p.durationMagnitude + p.durationDesignator.description) === '12M'
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
// Filter by the licence (sub) type
|
|
25
|
+
const byLicenceType = byLicenceLength.filter(p => p.permitSubtype.label === existingPermission.permit.permitSubtype.label)
|
|
26
|
+
|
|
27
|
+
// Filter by the number of rods
|
|
28
|
+
const byNumberOfRods = byLicenceType.filter(r => String(r.numberOfRods) === String(existingPermission.permit.numberOfRods))
|
|
29
|
+
|
|
30
|
+
return byNumberOfRods[0]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const getPermitsJoinPermitConcessions = async () => {
|
|
34
|
+
const permits = await getReferenceDataForEntity(Permit)
|
|
35
|
+
const permitConcessions = await getReferenceDataForEntity(PermitConcession)
|
|
36
|
+
const concessions = await getReferenceDataForEntity(Concession)
|
|
37
|
+
return permits.map(p => ({
|
|
38
|
+
...p.toJSON(),
|
|
39
|
+
concessions: permitConcessions.filter(pc => pc.permitId === p.id).map(pc => concessions.find(c => c.id === pc.concessionId))
|
|
40
|
+
}))
|
|
41
|
+
}
|
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
import moment from 'moment'
|
|
2
2
|
import { preparePermissionDataForRenewal } from '../renewals.service.js'
|
|
3
|
+
import { findPermit } from '../../permit.service.js'
|
|
4
|
+
import { getReferenceDataForEntity } from '../../reference-data.service.js'
|
|
5
|
+
import { CONCESSION, CONCESSION_PROOF } from '../../constants.js'
|
|
6
|
+
|
|
7
|
+
jest.mock('@defra-fish/connectors-lib')
|
|
8
|
+
jest.mock('../../reference-data.service.js')
|
|
9
|
+
|
|
10
|
+
getReferenceDataForEntity.mockResolvedValue([
|
|
11
|
+
{
|
|
12
|
+
id: '3230c68f-ef65-e611-80dc-c4346bad4004',
|
|
13
|
+
name: 'Junior'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: 'd0ece997-ef65-e611-80dc-c4346bad4004',
|
|
17
|
+
name: 'Senior'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'd1ece997-ef65-e611-80dc-c4346bad4004',
|
|
21
|
+
name: 'Disabled'
|
|
22
|
+
}
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
jest.mock('../../permit.service.js', () => ({
|
|
26
|
+
findPermit: jest.fn(() => ({ id: '123456' }))
|
|
27
|
+
}))
|
|
3
28
|
|
|
4
29
|
describe('preparePermissionDataForRenewal', () => {
|
|
5
30
|
const existingPermission = overrides => ({
|
|
@@ -37,9 +62,18 @@ describe('preparePermissionDataForRenewal', () => {
|
|
|
37
62
|
},
|
|
38
63
|
numberOfRods: 1
|
|
39
64
|
},
|
|
65
|
+
concessions: [],
|
|
40
66
|
...overrides
|
|
41
67
|
})
|
|
42
68
|
|
|
69
|
+
const existingSeniorPermission = () =>
|
|
70
|
+
existingPermission({
|
|
71
|
+
licensee: {
|
|
72
|
+
...existingPermission().licensee,
|
|
73
|
+
birthDate: '1958-01-01'
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
43
77
|
it('should assign the correct data to the base permission', async () => {
|
|
44
78
|
const expectedData = {
|
|
45
79
|
isRenewal: true,
|
|
@@ -49,7 +83,7 @@ describe('preparePermissionDataForRenewal', () => {
|
|
|
49
83
|
isLicenceForYou: true,
|
|
50
84
|
permitId: '123456'
|
|
51
85
|
}
|
|
52
|
-
expect(preparePermissionDataForRenewal(existingPermission())).toEqual(expect.objectContaining(expectedData))
|
|
86
|
+
expect(await preparePermissionDataForRenewal(existingPermission())).toEqual(expect.objectContaining(expectedData))
|
|
53
87
|
})
|
|
54
88
|
|
|
55
89
|
it('should copy the relevant licensee data', async () => {
|
|
@@ -67,20 +101,23 @@ describe('preparePermissionDataForRenewal', () => {
|
|
|
67
101
|
preferredMethodOfConfirmation: 'Text',
|
|
68
102
|
preferredMethodOfReminder: 'Letter'
|
|
69
103
|
}
|
|
70
|
-
|
|
104
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
105
|
+
expect(permission.licensee).toEqual(expect.objectContaining(expectedData))
|
|
71
106
|
})
|
|
72
107
|
|
|
73
108
|
it('should not assign shortTermPreferredMethodOfConfirmation to the licensee', async () => {
|
|
74
|
-
const
|
|
75
|
-
expect(
|
|
109
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
110
|
+
expect(permission.licensee.shortTermPreferredMethodOfConfirmation).toBeUndefined()
|
|
76
111
|
})
|
|
77
112
|
|
|
78
113
|
it('should remove null values from the licensee object', async () => {
|
|
79
|
-
|
|
114
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
115
|
+
expect(permission.licensee).toEqual(expect.not.objectContaining({ mobilePhone: null }))
|
|
80
116
|
})
|
|
81
117
|
|
|
82
118
|
it('should keep false values on the licensee object', async () => {
|
|
83
|
-
|
|
119
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
120
|
+
expect(permission.licensee).toEqual(expect.objectContaining({ postalFulfilment: false }))
|
|
84
121
|
})
|
|
85
122
|
|
|
86
123
|
describe('when the original permission has expired', () => {
|
|
@@ -93,7 +130,7 @@ describe('preparePermissionDataForRenewal', () => {
|
|
|
93
130
|
licenceStartTime: 0,
|
|
94
131
|
renewedEndDate: endDate.toISOString()
|
|
95
132
|
}
|
|
96
|
-
expect(preparePermissionDataForRenewal(existingPermission({ endDate }))).toEqual(expect.objectContaining(expectedData))
|
|
133
|
+
expect(await preparePermissionDataForRenewal(existingPermission({ endDate }))).toEqual(expect.objectContaining(expectedData))
|
|
97
134
|
})
|
|
98
135
|
})
|
|
99
136
|
|
|
@@ -107,7 +144,61 @@ describe('preparePermissionDataForRenewal', () => {
|
|
|
107
144
|
licenceStartTime: endDate.hours(),
|
|
108
145
|
renewedEndDate: endDate.toISOString()
|
|
109
146
|
}
|
|
110
|
-
expect(preparePermissionDataForRenewal(existingPermission({ endDate }))).toEqual(expect.objectContaining(expectedData))
|
|
147
|
+
expect(await preparePermissionDataForRenewal(existingPermission({ endDate }))).toEqual(expect.objectContaining(expectedData))
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('prepareConcessionsData', () => {
|
|
152
|
+
it('should add senior concession if the licensee is senior', async () => {
|
|
153
|
+
const samplePermission = existingSeniorPermission()
|
|
154
|
+
const ppd = await preparePermissionDataForRenewal(samplePermission)
|
|
155
|
+
const senior = { name: 'Senior', id: 'd0ece997-ef65-e611-80dc-c4346bad4004', proof: { type: 'No Proof' } }
|
|
156
|
+
expect(ppd.concessions[0]).toEqual(senior)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it("doesn't add senior concession if the licensee is not senior", async () => {
|
|
160
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
161
|
+
expect(permission.concessions).toEqual([])
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('should remove noLicenceRequired from licensee', async () => {
|
|
165
|
+
const permission = existingPermission()
|
|
166
|
+
permission.licensee.noLicenceRequired = true
|
|
167
|
+
const preparedPermission = await preparePermissionDataForRenewal(existingPermission())
|
|
168
|
+
expect(preparedPermission.licensee.noLicenceRequired).toBeUndefined()
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it.each([
|
|
172
|
+
['adult', existingPermission()],
|
|
173
|
+
['senior', existingSeniorPermission()]
|
|
174
|
+
])('should leave disabled concession unmodified on %s permission', async (_d, permission) => {
|
|
175
|
+
const disabledConcession = {
|
|
176
|
+
id: 'eee-555-fff-666',
|
|
177
|
+
name: CONCESSION.DISABLED,
|
|
178
|
+
proof: {
|
|
179
|
+
type: CONCESSION_PROOF.blueBadge,
|
|
180
|
+
referenceNumber: 'blue-badge-123'
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
permission.concessions = [disabledConcession]
|
|
184
|
+
|
|
185
|
+
const preparedPermission = await preparePermissionDataForRenewal(permission)
|
|
186
|
+
expect(preparedPermission.concessions).toEqual(expect.arrayContaining([expect.objectContaining(disabledConcession)]))
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
describe('preparePermit', () => {
|
|
191
|
+
it('permitId should match the return of findPermit.id', async () => {
|
|
192
|
+
const mockPermit = {
|
|
193
|
+
id: '101010',
|
|
194
|
+
permitSubtype: {
|
|
195
|
+
label: 'Salmon and sea trout'
|
|
196
|
+
},
|
|
197
|
+
numberOfRods: 1
|
|
198
|
+
}
|
|
199
|
+
findPermit.mockResolvedValueOnce(mockPermit)
|
|
200
|
+
const permission = await preparePermissionDataForRenewal(existingPermission())
|
|
201
|
+
expect(permission.permitId).toEqual(mockPermit.id)
|
|
111
202
|
})
|
|
112
203
|
})
|
|
113
204
|
})
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { SERVICE_LOCAL_TIME } from '@defra-fish/business-rules-lib'
|
|
1
|
+
import { isSenior, SERVICE_LOCAL_TIME } from '@defra-fish/business-rules-lib'
|
|
2
2
|
import moment from 'moment-timezone'
|
|
3
|
+
import { addSenior } from '../concession.service.js'
|
|
4
|
+
import { findPermit } from '../permit.service.js'
|
|
3
5
|
|
|
4
6
|
// Replicated from GAFL - need to decide whether to move
|
|
5
7
|
const cacheDateFormat = 'YYYY-MM-DD'
|
|
@@ -8,12 +10,17 @@ const licenceToStart = {
|
|
|
8
10
|
ANOTHER_DATE: 'another-date'
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export const preparePermissionDataForRenewal = existingPermission =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
export const preparePermissionDataForRenewal = async existingPermission => {
|
|
14
|
+
const dateData = prepareDateData(existingPermission)
|
|
15
|
+
const concessions = await prepareConcessionsData(existingPermission, dateData)
|
|
16
|
+
return {
|
|
17
|
+
...prepareBasePermissionData(existingPermission),
|
|
18
|
+
...dateData,
|
|
19
|
+
licensee: prepareLicenseeData(existingPermission),
|
|
20
|
+
concessions,
|
|
21
|
+
permitId: await preparePermit(existingPermission)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
17
24
|
|
|
18
25
|
const prepareBasePermissionData = existingPermission => ({
|
|
19
26
|
isRenewal: true,
|
|
@@ -83,4 +90,20 @@ const dateDataIfNotExpired = endDateMoment => {
|
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
const
|
|
93
|
+
const preparePermit = async existingPermission => {
|
|
94
|
+
const permit = await findPermit(existingPermission)
|
|
95
|
+
return permit.id
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const prepareConcessionsData = async (existingPermission, dateData) => {
|
|
99
|
+
delete existingPermission.licensee.noLicenceRequired
|
|
100
|
+
const ageAtLicenceStartDate = moment(dateData.licenceStartDate)
|
|
101
|
+
.add(1, 'year')
|
|
102
|
+
.diff(moment(existingPermission.licensee.birthDate), 'years')
|
|
103
|
+
|
|
104
|
+
if (isSenior(ageAtLicenceStartDate)) {
|
|
105
|
+
await addSenior(existingPermission)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return existingPermission.concessions
|
|
109
|
+
}
|