@defra-fish/recurring-payments-job 1.47.0-rc.1 → 1.47.0-rc.3
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/recurring-payments-job",
|
|
3
|
-
"version": "1.47.0-rc.
|
|
3
|
+
"version": "1.47.0-rc.3",
|
|
4
4
|
"description": "Rod Licensing Recurring Payments Job",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -36,8 +36,10 @@
|
|
|
36
36
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@defra-fish/
|
|
40
|
-
"
|
|
39
|
+
"@defra-fish/business-rules-lib": "1.47.0-rc.3",
|
|
40
|
+
"@defra-fish/connectors-lib": "1.47.0-rc.3",
|
|
41
|
+
"commander": "^7.2.0",
|
|
42
|
+
"moment-timezone": "^0.5.34"
|
|
41
43
|
},
|
|
42
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "2c8279cb9e9b4a31af6b595475663a76ecf9204f"
|
|
43
45
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { salesApi } from '@defra-fish/connectors-lib'
|
|
2
2
|
import { processRecurringPayments } from '../recurring-payments-processor.js'
|
|
3
3
|
|
|
4
|
+
jest.mock('@defra-fish/business-rules-lib')
|
|
4
5
|
jest.mock('@defra-fish/connectors-lib', () => ({
|
|
5
|
-
salesApi: {
|
|
6
|
+
salesApi: {
|
|
7
|
+
getDueRecurringPayments: jest.fn(() => []),
|
|
8
|
+
preparePermissionDataForRenewal: jest.fn(() => ({
|
|
9
|
+
licensee: { countryCode: 'GB-ENG' }
|
|
10
|
+
})),
|
|
11
|
+
createTransaction: jest.fn()
|
|
12
|
+
}
|
|
6
13
|
}))
|
|
7
14
|
|
|
8
15
|
describe('recurring-payments-processor', () => {
|
|
@@ -40,11 +47,176 @@ describe('recurring-payments-processor', () => {
|
|
|
40
47
|
it('console log displays "Recurring Payments found: " when env is true', async () => {
|
|
41
48
|
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
42
49
|
const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(jest.fn())
|
|
43
|
-
const rpSymbol = Symbol('rp')
|
|
44
|
-
salesApi.getDueRecurringPayments.mockReturnValueOnce(rpSymbol)
|
|
45
50
|
|
|
46
51
|
await processRecurringPayments()
|
|
47
52
|
|
|
48
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('Recurring Payments found: ',
|
|
53
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Recurring Payments found: ', [])
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('prepares the data for found recurring payments', async () => {
|
|
57
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
58
|
+
const referenceNumber = Symbol('reference')
|
|
59
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce([{ expanded: { activePermission: { entity: { referenceNumber } } } }])
|
|
60
|
+
|
|
61
|
+
await processRecurringPayments()
|
|
62
|
+
|
|
63
|
+
expect(salesApi.preparePermissionDataForRenewal).toHaveBeenCalledWith(referenceNumber)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('creates a transaction with the correct data', async () => {
|
|
67
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
68
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce([{ expanded: { activePermission: { entity: { referenceNumber: '1' } } } }])
|
|
69
|
+
|
|
70
|
+
const isLicenceForYou = Symbol('isLicenceForYou')
|
|
71
|
+
const isRenewal = Symbol('isRenewal')
|
|
72
|
+
const country = Symbol('country')
|
|
73
|
+
const permitId = Symbol('permitId')
|
|
74
|
+
const firstName = Symbol('firstName')
|
|
75
|
+
const lastName = Symbol('lastName')
|
|
76
|
+
|
|
77
|
+
salesApi.preparePermissionDataForRenewal.mockReturnValueOnce({
|
|
78
|
+
isLicenceForYou,
|
|
79
|
+
isRenewal,
|
|
80
|
+
licensee: {
|
|
81
|
+
firstName,
|
|
82
|
+
lastName,
|
|
83
|
+
country,
|
|
84
|
+
countryCode: 'GB-ENG'
|
|
85
|
+
},
|
|
86
|
+
licenceStartDate: '2020-01-01',
|
|
87
|
+
licenceStartTime: 3,
|
|
88
|
+
permitId
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const expectedData = {
|
|
92
|
+
dataSource: 'Recurring Payment',
|
|
93
|
+
permissions: [
|
|
94
|
+
{
|
|
95
|
+
isLicenceForYou,
|
|
96
|
+
isRenewal,
|
|
97
|
+
issueDate: null,
|
|
98
|
+
licensee: {
|
|
99
|
+
firstName,
|
|
100
|
+
lastName,
|
|
101
|
+
country
|
|
102
|
+
},
|
|
103
|
+
permitId,
|
|
104
|
+
startDate: '2020-01-01T03:00:00.000Z'
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await processRecurringPayments()
|
|
110
|
+
|
|
111
|
+
expect(salesApi.createTransaction).toHaveBeenCalledWith(expectedData)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('assigns the correct startDate when licenceStartTime is present', async () => {
|
|
115
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
116
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce([{ expanded: { activePermission: { entity: { referenceNumber: '1' } } } }])
|
|
117
|
+
|
|
118
|
+
salesApi.preparePermissionDataForRenewal.mockReturnValueOnce({
|
|
119
|
+
licensee: { countryCode: 'GB-ENG' },
|
|
120
|
+
licenceStartDate: '2020-03-14',
|
|
121
|
+
licenceStartTime: 15
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
await processRecurringPayments()
|
|
125
|
+
|
|
126
|
+
expect(salesApi.createTransaction).toHaveBeenCalledWith(
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
permissions: [expect.objectContaining({ startDate: '2020-03-14T15:00:00.000Z' })]
|
|
129
|
+
})
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('assigns the correct startDate when licenceStartTime is not present', async () => {
|
|
134
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
135
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce([{ expanded: { activePermission: { entity: { referenceNumber: '1' } } } }])
|
|
136
|
+
|
|
137
|
+
salesApi.preparePermissionDataForRenewal.mockReturnValueOnce({
|
|
138
|
+
licensee: { countryCode: 'GB-ENG' },
|
|
139
|
+
licenceStartDate: '2020-03-14'
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
await processRecurringPayments()
|
|
143
|
+
|
|
144
|
+
expect(salesApi.createTransaction).toHaveBeenCalledWith(
|
|
145
|
+
expect.objectContaining({
|
|
146
|
+
permissions: [expect.objectContaining({ startDate: '2020-03-14T00:00:00.000Z' })]
|
|
147
|
+
})
|
|
148
|
+
)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it('raises an error if createTransaction fails', async () => {
|
|
152
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
153
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce([{ expanded: { activePermission: { entity: { referenceNumber: '1' } } } }])
|
|
154
|
+
const error = 'Wuh-oh!'
|
|
155
|
+
salesApi.createTransaction.mockImplementationOnce(() => {
|
|
156
|
+
throw new Error(error)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
await expect(processRecurringPayments()).rejects.toThrowError(error)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe.each([2, 3, 10])('if there are %d recurring payments', count => {
|
|
163
|
+
it('prepares the data for each one', async () => {
|
|
164
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
165
|
+
const references = []
|
|
166
|
+
for (let i = 0; i < count; i++) {
|
|
167
|
+
references.push(Symbol('reference' + i))
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const mockGetDueRecurringPayments = []
|
|
171
|
+
references.forEach(reference => {
|
|
172
|
+
mockGetDueRecurringPayments.push({ expanded: { activePermission: { entity: { referenceNumber: reference } } } })
|
|
173
|
+
})
|
|
174
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce(mockGetDueRecurringPayments)
|
|
175
|
+
|
|
176
|
+
const expectedData = []
|
|
177
|
+
references.forEach(reference => {
|
|
178
|
+
expectedData.push([reference])
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
await processRecurringPayments()
|
|
182
|
+
|
|
183
|
+
expect(salesApi.preparePermissionDataForRenewal.mock.calls).toEqual(expectedData)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('creates a transaction for each one', async () => {
|
|
187
|
+
process.env.RUN_RECURRING_PAYMENTS = 'true'
|
|
188
|
+
|
|
189
|
+
const mockGetDueRecurringPayments = []
|
|
190
|
+
for (let i = 0; i < count; i++) {
|
|
191
|
+
mockGetDueRecurringPayments.push({ expanded: { activePermission: { entity: { referenceNumber: i } } } })
|
|
192
|
+
}
|
|
193
|
+
salesApi.getDueRecurringPayments.mockReturnValueOnce(mockGetDueRecurringPayments)
|
|
194
|
+
|
|
195
|
+
const permits = []
|
|
196
|
+
for (let i = 0; i < count; i++) {
|
|
197
|
+
permits.push(Symbol('permit' + i))
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
permits.forEach(permit => {
|
|
201
|
+
salesApi.preparePermissionDataForRenewal.mockReturnValueOnce({
|
|
202
|
+
licensee: { countryCode: 'GB-ENG' },
|
|
203
|
+
permitId: permit
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
const expectedData = []
|
|
208
|
+
permits.forEach(permit => {
|
|
209
|
+
expectedData.push([
|
|
210
|
+
{
|
|
211
|
+
dataSource: 'Recurring Payment',
|
|
212
|
+
permissions: [expect.objectContaining({ permitId: permit })]
|
|
213
|
+
}
|
|
214
|
+
])
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
await processRecurringPayments()
|
|
218
|
+
|
|
219
|
+
expect(salesApi.createTransaction.mock.calls).toEqual(expectedData)
|
|
220
|
+
})
|
|
49
221
|
})
|
|
50
222
|
})
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import moment from 'moment-timezone'
|
|
2
|
+
import { SERVICE_LOCAL_TIME } from '@defra-fish/business-rules-lib'
|
|
1
3
|
import { salesApi } from '@defra-fish/connectors-lib'
|
|
2
4
|
|
|
3
5
|
export const processRecurringPayments = async () => {
|
|
@@ -6,7 +8,48 @@ export const processRecurringPayments = async () => {
|
|
|
6
8
|
const date = new Date().toISOString().split('T')[0]
|
|
7
9
|
const response = await salesApi.getDueRecurringPayments(date)
|
|
8
10
|
console.log('Recurring Payments found: ', response)
|
|
11
|
+
await Promise.all(response.map(record => processRecurringPayment(record)))
|
|
9
12
|
} else {
|
|
10
13
|
console.log('Recurring Payments job disabled')
|
|
11
14
|
}
|
|
12
15
|
}
|
|
16
|
+
|
|
17
|
+
const processRecurringPayment = async record => {
|
|
18
|
+
const referenceNumber = record.expanded.activePermission.entity.referenceNumber
|
|
19
|
+
const transactionData = await processPermissionData(referenceNumber)
|
|
20
|
+
console.log('Creating new transaction based on', referenceNumber)
|
|
21
|
+
try {
|
|
22
|
+
const response = await salesApi.createTransaction(transactionData)
|
|
23
|
+
console.log('New transaction created:', response)
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.log('Error creating transaction', JSON.stringify(transactionData))
|
|
26
|
+
throw e
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const processPermissionData = async referenceNumber => {
|
|
31
|
+
console.log('Preparing data based on', referenceNumber)
|
|
32
|
+
const data = await salesApi.preparePermissionDataForRenewal(referenceNumber)
|
|
33
|
+
const licenseeWithoutCountryCode = Object.assign((({ countryCode: _countryCode, ...l }) => l)(data.licensee))
|
|
34
|
+
return {
|
|
35
|
+
dataSource: 'Recurring Payment',
|
|
36
|
+
permissions: [
|
|
37
|
+
{
|
|
38
|
+
isLicenceForYou: data.isLicenceForYou,
|
|
39
|
+
isRenewal: data.isRenewal,
|
|
40
|
+
issueDate: null,
|
|
41
|
+
licensee: licenseeWithoutCountryCode,
|
|
42
|
+
permitId: data.permitId,
|
|
43
|
+
startDate: prepareStartDate(data)
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const prepareStartDate = permission => {
|
|
50
|
+
return moment
|
|
51
|
+
.tz(permission.licenceStartDate, 'YYYY-MM-DD', SERVICE_LOCAL_TIME)
|
|
52
|
+
.add(permission.licenceStartTime ?? 0, 'hours')
|
|
53
|
+
.utc()
|
|
54
|
+
.toISOString()
|
|
55
|
+
}
|