@darkpos/pricing 1.0.151 → 1.0.153
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/__TEST__/order/applyRefund.test.js +387 -0
- package/__TEST__/order/order-payment-modifier.test.js +2 -0
- package/__TEST__/order/order.test.js +1 -1
- package/__TEST__/payment.test.js +158 -0
- package/lib/invoice/index.js +0 -8
- package/lib/item/capOverPaidItem.js +14 -0
- package/lib/item/index.js +2 -2
- package/lib/order/applyRefund.js +125 -0
- package/lib/order/calculate.js +0 -1
- package/lib/order/getOverPaidAmount.js +13 -0
- package/lib/order/getTotalPaidToRedistribute.js +41 -0
- package/lib/order/index.js +8 -2
- package/lib/order/refundOrderItem.js +29 -0
- package/lib/payment/getMethodLabel.js +7 -0
- package/lib/payment/getOverPaidOrders.js +38 -0
- package/lib/payment/getRefundableOrderAmount.js +21 -0
- package/lib/payment/index.js +6 -0
- package/package.json +2 -2
- package/__TEST__/invoice/refundInvoices.test.js +0 -366
- package/lib/invoice/applyRefundToInvoices.js +0 -52
- package/lib/invoice/buildItemRefund.js +0 -23
- package/lib/invoice/computeRefundables.js +0 -59
- package/lib/invoice/resolveItemState.js +0 -25
- package/lib/item/getOverpaidAmount.js +0 -7
- package/lib/order/getOverpaidAmount.js +0 -13
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
const usePricing = require('../../index');
|
|
2
|
+
const mockStores = require('../mocks/stores');
|
|
3
|
+
|
|
4
|
+
const session = {
|
|
5
|
+
store: mockStores[0],
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const pricingService = usePricing(session);
|
|
9
|
+
|
|
10
|
+
const createOptions = items => ({
|
|
11
|
+
'order-1': {
|
|
12
|
+
items,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('Apply refund', () => {
|
|
17
|
+
test('keeps applyPayment working for positive amounts', () => {
|
|
18
|
+
const options = createOptions({
|
|
19
|
+
'item-1': {
|
|
20
|
+
total: 8,
|
|
21
|
+
totalPaid: 0,
|
|
22
|
+
status: {},
|
|
23
|
+
},
|
|
24
|
+
'item-2': {
|
|
25
|
+
total: 7,
|
|
26
|
+
totalPaid: 0,
|
|
27
|
+
status: {},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const result = pricingService.order.applyPayment(options, 10);
|
|
32
|
+
|
|
33
|
+
expect(result['order-1'].items['item-1']).toMatchObject({
|
|
34
|
+
orderId: 'order-1',
|
|
35
|
+
amount: 8,
|
|
36
|
+
totalPaid: 8,
|
|
37
|
+
status: {
|
|
38
|
+
paid: {
|
|
39
|
+
value: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(result['order-1'].items['item-2']).toMatchObject({
|
|
45
|
+
orderId: 'order-1',
|
|
46
|
+
amount: 2,
|
|
47
|
+
totalPaid: 2,
|
|
48
|
+
status: {
|
|
49
|
+
paid: {
|
|
50
|
+
value: false,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('applies refunds when amount to process is negative', () => {
|
|
57
|
+
const options = createOptions({
|
|
58
|
+
'item-1': {
|
|
59
|
+
total: 8,
|
|
60
|
+
totalPaid: 8,
|
|
61
|
+
status: {
|
|
62
|
+
paid: {
|
|
63
|
+
value: true,
|
|
64
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
'item-2': {
|
|
69
|
+
total: 7,
|
|
70
|
+
totalPaid: 7,
|
|
71
|
+
status: {
|
|
72
|
+
paid: {
|
|
73
|
+
value: true,
|
|
74
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const result = pricingService.order.applyRefund(options, -10);
|
|
81
|
+
|
|
82
|
+
expect(result.refundedAmount).toBe(10);
|
|
83
|
+
|
|
84
|
+
expect(result.options['order-1'].items['item-1']).toMatchObject({
|
|
85
|
+
orderId: 'order-1',
|
|
86
|
+
amount: -8,
|
|
87
|
+
totalPaid: 0,
|
|
88
|
+
status: {
|
|
89
|
+
paid: {
|
|
90
|
+
value: false,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
expect(result.options['order-1'].items['item-2']).toMatchObject({
|
|
96
|
+
orderId: 'order-1',
|
|
97
|
+
amount: -2,
|
|
98
|
+
totalPaid: 5,
|
|
99
|
+
status: {
|
|
100
|
+
paid: {
|
|
101
|
+
value: false,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('accepts positive refund amounts and only applies the visible overpayment on current items', () => {
|
|
108
|
+
const options = createOptions({
|
|
109
|
+
'item-1': {
|
|
110
|
+
total: 1,
|
|
111
|
+
totalPaid: 5,
|
|
112
|
+
status: {
|
|
113
|
+
paid: {
|
|
114
|
+
value: true,
|
|
115
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
'item-2': {
|
|
120
|
+
total: 1,
|
|
121
|
+
totalPaid: 5,
|
|
122
|
+
status: {
|
|
123
|
+
paid: {
|
|
124
|
+
value: true,
|
|
125
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const result = pricingService.order.applyRefund(options, 3);
|
|
132
|
+
|
|
133
|
+
expect(result.refundedAmount).toBe(3);
|
|
134
|
+
|
|
135
|
+
expect(result.options['order-1'].items['item-1']).toMatchObject({
|
|
136
|
+
orderId: 'order-1',
|
|
137
|
+
amount: -3,
|
|
138
|
+
totalPaid: 2,
|
|
139
|
+
status: {
|
|
140
|
+
paid: {
|
|
141
|
+
value: true,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(result.options['order-1'].items['item-2']).toMatchObject({
|
|
147
|
+
orderId: 'order-1',
|
|
148
|
+
amount: 0,
|
|
149
|
+
totalPaid: 5,
|
|
150
|
+
status: {
|
|
151
|
+
paid: {
|
|
152
|
+
value: true,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('normalizes overpaid items after refund so no item keeps totalPaid above total', () => {
|
|
159
|
+
const options = createOptions({
|
|
160
|
+
'698a364799a15511959c9135': {
|
|
161
|
+
status: {
|
|
162
|
+
picked: {
|
|
163
|
+
value: false,
|
|
164
|
+
date: '',
|
|
165
|
+
},
|
|
166
|
+
paid: {
|
|
167
|
+
value: true,
|
|
168
|
+
date: new Date('2026-04-01T16:32:04.514Z'),
|
|
169
|
+
},
|
|
170
|
+
tracker: [],
|
|
171
|
+
},
|
|
172
|
+
total: 1.05,
|
|
173
|
+
totalPaid: 14.7,
|
|
174
|
+
},
|
|
175
|
+
'698a364799a15511959c9130': {
|
|
176
|
+
status: {
|
|
177
|
+
picked: {
|
|
178
|
+
value: false,
|
|
179
|
+
date: '',
|
|
180
|
+
},
|
|
181
|
+
paid: {
|
|
182
|
+
value: false,
|
|
183
|
+
date: new Date('2026-04-01T16:32:04.514Z'),
|
|
184
|
+
},
|
|
185
|
+
tracker: [],
|
|
186
|
+
},
|
|
187
|
+
total: 1.05,
|
|
188
|
+
totalPaid: 0,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const result = pricingService.order.applyRefund(options, -12.6);
|
|
193
|
+
|
|
194
|
+
expect(result.refundedAmount).toBe(12.6);
|
|
195
|
+
|
|
196
|
+
expect(
|
|
197
|
+
result.options['order-1'].items['698a364799a15511959c9135']
|
|
198
|
+
).toMatchObject({
|
|
199
|
+
orderId: 'order-1',
|
|
200
|
+
amount: -13.65,
|
|
201
|
+
totalPaid: 1.05,
|
|
202
|
+
status: {
|
|
203
|
+
paid: {
|
|
204
|
+
value: true,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
expect(
|
|
210
|
+
result.options['order-1'].items['698a364799a15511959c9130']
|
|
211
|
+
).toMatchObject({
|
|
212
|
+
orderId: 'order-1',
|
|
213
|
+
amount: 1.05,
|
|
214
|
+
totalPaid: 1.05,
|
|
215
|
+
status: {
|
|
216
|
+
paid: {
|
|
217
|
+
value: true,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test('ignores refund amounts larger than the refundable balance', () => {
|
|
224
|
+
const options = createOptions({
|
|
225
|
+
'item-1': {
|
|
226
|
+
total: 8,
|
|
227
|
+
totalPaid: 8,
|
|
228
|
+
status: {
|
|
229
|
+
paid: {
|
|
230
|
+
value: true,
|
|
231
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
'item-2': {
|
|
236
|
+
total: 7,
|
|
237
|
+
totalPaid: 2,
|
|
238
|
+
status: {
|
|
239
|
+
paid: {
|
|
240
|
+
value: false,
|
|
241
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const result = pricingService.order.applyRefund(options, -100);
|
|
248
|
+
|
|
249
|
+
expect(result.refundedAmount).toBe(10);
|
|
250
|
+
|
|
251
|
+
expect(result.options['order-1'].items['item-1']).toMatchObject({
|
|
252
|
+
orderId: 'order-1',
|
|
253
|
+
amount: -8,
|
|
254
|
+
totalPaid: 0,
|
|
255
|
+
status: {
|
|
256
|
+
paid: {
|
|
257
|
+
value: false,
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(result.options['order-1'].items['item-2']).toMatchObject({
|
|
263
|
+
orderId: 'order-1',
|
|
264
|
+
amount: -2,
|
|
265
|
+
totalPaid: 0,
|
|
266
|
+
status: {
|
|
267
|
+
paid: {
|
|
268
|
+
value: false,
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('refunds overpaid zero-total items before touching correctly paid items', () => {
|
|
275
|
+
const options = createOptions({
|
|
276
|
+
shorts: {
|
|
277
|
+
total: 6.3,
|
|
278
|
+
totalPaid: 6.3,
|
|
279
|
+
status: {
|
|
280
|
+
paid: {
|
|
281
|
+
value: true,
|
|
282
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
jacket1: {
|
|
287
|
+
total: 0,
|
|
288
|
+
totalPaid: 8.93,
|
|
289
|
+
status: {
|
|
290
|
+
paid: {
|
|
291
|
+
value: true,
|
|
292
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
longJacket: {
|
|
297
|
+
total: 0,
|
|
298
|
+
totalPaid: 12.6,
|
|
299
|
+
status: {
|
|
300
|
+
paid: {
|
|
301
|
+
value: true,
|
|
302
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
jacket2: {
|
|
307
|
+
total: 0,
|
|
308
|
+
totalPaid: 8.93,
|
|
309
|
+
status: {
|
|
310
|
+
paid: {
|
|
311
|
+
value: true,
|
|
312
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
coat: {
|
|
317
|
+
total: 13.65,
|
|
318
|
+
totalPaid: 3.24,
|
|
319
|
+
status: {
|
|
320
|
+
paid: {
|
|
321
|
+
value: false,
|
|
322
|
+
date: new Date('2024-01-01T00:00:00.000Z'),
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const result = pricingService.order.applyRefund(options, 20.05);
|
|
329
|
+
|
|
330
|
+
expect(result.refundedAmount).toBe(20.05);
|
|
331
|
+
|
|
332
|
+
expect(result.options['order-1'].items.shorts).toMatchObject({
|
|
333
|
+
orderId: 'order-1',
|
|
334
|
+
amount: 0,
|
|
335
|
+
totalPaid: 6.3,
|
|
336
|
+
status: {
|
|
337
|
+
paid: {
|
|
338
|
+
value: true,
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
expect(result.options['order-1'].items.jacket1).toMatchObject({
|
|
344
|
+
orderId: 'order-1',
|
|
345
|
+
amount: -8.93,
|
|
346
|
+
totalPaid: 0,
|
|
347
|
+
status: {
|
|
348
|
+
paid: {
|
|
349
|
+
value: true,
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(result.options['order-1'].items.longJacket).toMatchObject({
|
|
355
|
+
orderId: 'order-1',
|
|
356
|
+
amount: -12.6,
|
|
357
|
+
totalPaid: 0,
|
|
358
|
+
status: {
|
|
359
|
+
paid: {
|
|
360
|
+
value: true,
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
expect(result.options['order-1'].items.jacket2).toMatchObject({
|
|
366
|
+
orderId: 'order-1',
|
|
367
|
+
amount: -8.93,
|
|
368
|
+
totalPaid: 0,
|
|
369
|
+
status: {
|
|
370
|
+
paid: {
|
|
371
|
+
value: true,
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
expect(result.options['order-1'].items.coat).toMatchObject({
|
|
377
|
+
orderId: 'order-1',
|
|
378
|
+
amount: 10.41,
|
|
379
|
+
totalPaid: 13.65,
|
|
380
|
+
status: {
|
|
381
|
+
paid: {
|
|
382
|
+
value: true,
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
});
|
|
@@ -574,9 +574,11 @@ describe('Order actions', () => {
|
|
|
574
574
|
lockPaymentModifiers: true,
|
|
575
575
|
});
|
|
576
576
|
|
|
577
|
+
paidOrderWithCredit.totalPaid += 1.25;
|
|
577
578
|
const orderBalanceWithCredit = pricingService.order.getOrdersBalance({
|
|
578
579
|
orders: [paidOrderWithCredit],
|
|
579
580
|
});
|
|
581
|
+
|
|
580
582
|
const itemBalanceWithCredit = pricingService.item.getItemsBalance({
|
|
581
583
|
items: paidOrderWithCredit.items,
|
|
582
584
|
});
|
|
@@ -3818,7 +3818,7 @@ describe('Order actions', () => {
|
|
|
3818
3818
|
const pricing = usePricing({
|
|
3819
3819
|
store: { _settings: { order: { autoMarkAsPaid: false } } },
|
|
3820
3820
|
});
|
|
3821
|
-
const order = { items: [orderItem], status: {} };
|
|
3821
|
+
const order = { items: [orderItem], status: {}, totalPaid: 30 };
|
|
3822
3822
|
const newOrder = pricing.order.calculate(order);
|
|
3823
3823
|
|
|
3824
3824
|
expect(newOrder).toHaveProperty('total', 25);
|
package/__TEST__/payment.test.js
CHANGED
|
@@ -6,6 +6,17 @@ const session = {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
const pricingService = usePricing(session);
|
|
9
|
+
const pricingServiceMethodLabel = usePricing({
|
|
10
|
+
store: {
|
|
11
|
+
_settings: {
|
|
12
|
+
_settings: {
|
|
13
|
+
payment: {
|
|
14
|
+
methods: mockStores[0]._settings.payment.methods,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
9
20
|
|
|
10
21
|
describe('getMaxAmountToRefund tests', () => {
|
|
11
22
|
test('Returns 0 when payment is undefined', () => {
|
|
@@ -49,3 +60,150 @@ describe('getMaxAmountToRefund tests', () => {
|
|
|
49
60
|
expect(pricingService.payment.getMaxAmountToRefund({ payment })).toBe(50);
|
|
50
61
|
});
|
|
51
62
|
});
|
|
63
|
+
|
|
64
|
+
describe('getRefundableOrderAmount tests', () => {
|
|
65
|
+
test('Returns 0 when retained order payment still matches the remaining item total', () => {
|
|
66
|
+
const order = {
|
|
67
|
+
_id: 'order-1',
|
|
68
|
+
totalPaid: 5,
|
|
69
|
+
items: [
|
|
70
|
+
{
|
|
71
|
+
_id: 'item-2',
|
|
72
|
+
name: 'Simple Item 2',
|
|
73
|
+
total: 5,
|
|
74
|
+
totalPaid: 0,
|
|
75
|
+
status: { paid: { value: false } },
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
expect(pricingService.payment.getRefundableOrderAmount({ order })).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('Returns the net order overpayment (totalPaid minus total), regardless of per-item breakdown', () => {
|
|
84
|
+
const order = {
|
|
85
|
+
_id: 'order-2',
|
|
86
|
+
totalPaid: 14.7,
|
|
87
|
+
items: [
|
|
88
|
+
{
|
|
89
|
+
_id: 'item-1',
|
|
90
|
+
name: 'Winter Coat',
|
|
91
|
+
total: 1.05,
|
|
92
|
+
totalPaid: 14.7,
|
|
93
|
+
status: { paid: { value: true } },
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
_id: 'item-2',
|
|
97
|
+
name: 'Coat',
|
|
98
|
+
total: 1.05,
|
|
99
|
+
totalPaid: 0,
|
|
100
|
+
status: { paid: { value: false } },
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
expect(pricingService.payment.getRefundableOrderAmount({ order })).toBe(
|
|
106
|
+
12.6
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('getOverPaidOrders tests', () => {
|
|
112
|
+
const baseOrder = pricingService.order.calculate({
|
|
113
|
+
_id: 'order-1',
|
|
114
|
+
items: [{ price: 30, quantity: 1, modifiers: [] }],
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('includes order and accumulates overpaid amount when customer paid more than the order total', () => {
|
|
118
|
+
const order = { ...baseOrder, totalPaid: 50 };
|
|
119
|
+
|
|
120
|
+
const result = pricingService.payment.getOverPaidOrders({
|
|
121
|
+
orders: [order],
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(result.overPaidOrders).toHaveLength(1);
|
|
125
|
+
expect(result.overPaidAmount).toBe(20);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('returns empty list and zero amount when customer paid exactly the order total', () => {
|
|
129
|
+
const order = { ...baseOrder, totalPaid: 30 };
|
|
130
|
+
|
|
131
|
+
const result = pricingService.payment.getOverPaidOrders({
|
|
132
|
+
orders: [order],
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect(result.overPaidOrders).toHaveLength(0);
|
|
136
|
+
expect(result.overPaidAmount).toBe(0);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('capOverPaidItem tests', () => {
|
|
141
|
+
test('caps totalPaid to item total and returns the excess as amountCapped', () => {
|
|
142
|
+
const item = { total: 10, totalPaid: 15 };
|
|
143
|
+
|
|
144
|
+
const result = pricingService.item.capOverPaidItem({ item });
|
|
145
|
+
|
|
146
|
+
expect(result.item.totalPaid).toBe(10);
|
|
147
|
+
expect(result.amountCapped).toBe(5);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('returns item unchanged and amountCapped 0 when totalPaid does not exceed total', () => {
|
|
151
|
+
const item = { total: 10, totalPaid: 10 };
|
|
152
|
+
|
|
153
|
+
const result = pricingService.item.capOverPaidItem({ item });
|
|
154
|
+
|
|
155
|
+
expect(result.item.totalPaid).toBe(10);
|
|
156
|
+
expect(result.amountCapped).toBe(0);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('getTotalPaidToRedistribute tests', () => {
|
|
161
|
+
test('returns order with redistributableAmount when totalPaid exceeds item totalPaid sum', () => {
|
|
162
|
+
const order = {
|
|
163
|
+
_id: 'order-1',
|
|
164
|
+
totalPaid: 5,
|
|
165
|
+
items: [{ totalPaid: 0 }, { totalPaid: 0 }],
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const result = pricingService.order.getTotalPaidToRedistribute({
|
|
169
|
+
orders: [order],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(result.redistributableOrders).toHaveLength(1);
|
|
173
|
+
expect(result.redistributableOrders[0].redistributableAmount).toBe(5);
|
|
174
|
+
expect(result.redistributableAmount).toBe(5);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('returns empty list and zero amount when all totalPaid is already distributed to items', () => {
|
|
178
|
+
const order = {
|
|
179
|
+
_id: 'order-1',
|
|
180
|
+
totalPaid: 10,
|
|
181
|
+
items: [{ totalPaid: 6 }, { totalPaid: 4 }],
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const result = pricingService.order.getTotalPaidToRedistribute({
|
|
185
|
+
orders: [order],
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
expect(result.redistributableOrders).toHaveLength(0);
|
|
189
|
+
expect(result.redistributableAmount).toBe(0);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('getMethodLabel tests', () => {
|
|
194
|
+
test('Returns the configured label for the payment provider', () => {
|
|
195
|
+
expect(
|
|
196
|
+
pricingServiceMethodLabel.payment.getMethodLabel({
|
|
197
|
+
paymentProvider: 'cash',
|
|
198
|
+
})
|
|
199
|
+
).toBe('Cash');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('Returns empty string when the provider is missing', () => {
|
|
203
|
+
expect(
|
|
204
|
+
pricingServiceMethodLabel.payment.getMethodLabel({
|
|
205
|
+
paymentProvider: 'missing-provider',
|
|
206
|
+
})
|
|
207
|
+
).toBe('');
|
|
208
|
+
});
|
|
209
|
+
});
|
package/lib/invoice/index.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
const getStatusByItems = require('./getStatusByItems');
|
|
2
2
|
const getTotalByItems = require('./getTotalByItems');
|
|
3
|
-
const resolveItemState = require('./resolveItemState');
|
|
4
|
-
const computeRefundables = require('./computeRefundables');
|
|
5
|
-
const buildItemRefund = require('./buildItemRefund');
|
|
6
|
-
const applyRefundToInvoices = require('./applyRefundToInvoices');
|
|
7
3
|
|
|
8
4
|
const invoiceActions = (deps = {}) => {
|
|
9
5
|
const actions = {};
|
|
@@ -16,10 +12,6 @@ const invoiceActions = (deps = {}) => {
|
|
|
16
12
|
const freezedActions = Object.freeze({
|
|
17
13
|
getStatusByItems: getStatusByItems(innerDeps),
|
|
18
14
|
getTotalByItems: getTotalByItems(innerDeps),
|
|
19
|
-
resolveItemState: resolveItemState(innerDeps),
|
|
20
|
-
computeRefundables: computeRefundables(innerDeps),
|
|
21
|
-
buildItemRefund: buildItemRefund(innerDeps),
|
|
22
|
-
applyRefundToInvoices: applyRefundToInvoices(innerDeps),
|
|
23
15
|
});
|
|
24
16
|
|
|
25
17
|
Object.keys(freezedActions).forEach(actionName => {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module.exports = ({ utils }) =>
|
|
2
|
+
function capOverPaidItem({ item }) {
|
|
3
|
+
const total = item.total || 0;
|
|
4
|
+
|
|
5
|
+
const totalPaid = item.totalPaid || 0;
|
|
6
|
+
|
|
7
|
+
if (totalPaid > total)
|
|
8
|
+
return {
|
|
9
|
+
item: { ...item, totalPaid: total },
|
|
10
|
+
amountCapped: utils.math.sub(totalPaid, total),
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return { item, amountCapped: 0 };
|
|
14
|
+
};
|
package/lib/item/index.js
CHANGED
|
@@ -84,7 +84,7 @@ const getAmountToPayById = require('./getAmountToPayById');
|
|
|
84
84
|
const applyPayment = require('./applyPayment');
|
|
85
85
|
const getBalanceForPaymentModifier = require('./getBalanceForPaymentModifier');
|
|
86
86
|
const isOverpaid = require('./isOverpaid');
|
|
87
|
-
const
|
|
87
|
+
const capOverPaidItem = require('./capOverPaidItem');
|
|
88
88
|
|
|
89
89
|
const itemActions = (deps = {}) => {
|
|
90
90
|
const actions = {};
|
|
@@ -182,7 +182,7 @@ const itemActions = (deps = {}) => {
|
|
|
182
182
|
applyPayment: applyPayment(innerDeps),
|
|
183
183
|
getBalanceForPaymentModifier: getBalanceForPaymentModifier(innerDeps),
|
|
184
184
|
isOverpaid: isOverpaid(innerDeps),
|
|
185
|
-
|
|
185
|
+
capOverPaidItem: capOverPaidItem(innerDeps),
|
|
186
186
|
});
|
|
187
187
|
|
|
188
188
|
Object.keys(freezedActions).forEach(actionName => {
|