@darkpos/pricing 1.0.43 → 1.0.45

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.
Files changed (79) hide show
  1. package/__TEST__/item/getItemsModifierDescription.test.js +75 -78
  2. package/__TEST__/mocks/addItemMock.js +18729 -19357
  3. package/__TEST__/mocks/partially-paid/order-modifiers.json +48 -51
  4. package/__TEST__/mocks/partially-paid/order-partially-paid.json +893 -860
  5. package/__TEST__/mocks/scripts/calculate-partially-paid/index.js +2 -2
  6. package/__TEST__/mocks/scripts/calculate-unpaid/index.js +2 -2
  7. package/__TEST__/mocks/unpaid/order-modifiers.json +48 -52
  8. package/__TEST__/modifier/calculate.test.js +1 -0
  9. package/__TEST__/modifier/getMatchTagsModifiers.test.js +72 -18
  10. package/__TEST__/modifier/getModifierIndex.test.js +10 -7
  11. package/__TEST__/modifier/getRecommendedModifiers.test.js +6 -4
  12. package/__TEST__/modifier/hasAttribute.test.js +11 -5
  13. package/__TEST__/modifier/hasMatchTags.test.js +33 -11
  14. package/__TEST__/modifier/sort.test.js +1 -1
  15. package/__TEST__/order/conditionsNotMet.test.js +133 -0
  16. package/__TEST__/order/manualSplit.test.js +104 -0
  17. package/__TEST__/order/order-payment-modifier.test.js +1117 -0
  18. package/__TEST__/order/order.test.js +53 -105
  19. package/__TEST__/order/pickEndDate.test.js +7 -153
  20. package/__TEST__/order/validateConditionsCalculate.test.js +396 -0
  21. package/lib/constants/index.js +1 -1
  22. package/lib/index.js +11 -2
  23. package/lib/item/calculate.js +93 -18
  24. package/lib/item/getAmounts.js +14 -0
  25. package/lib/item/getBalance.js +0 -1
  26. package/lib/item/getItemModifiersDescription.js +1 -0
  27. package/lib/item/getItemsBalance.js +9 -0
  28. package/lib/item/getItemsTotals.js +27 -0
  29. package/lib/item/getTotal.js +3 -1
  30. package/lib/item/hasPaymentMethodType.js +17 -0
  31. package/lib/item/hasPaymentModifierWithPaymentId.js +9 -0
  32. package/lib/item/index.js +15 -8
  33. package/lib/item/removePaymentModifiersByPaymentId.js +13 -0
  34. package/lib/modifier/areConditionsMet.js +61 -0
  35. package/lib/modifier/calculatePaymentDiscountModifier.js +31 -0
  36. package/lib/modifier/calculatePaymentFeeModifier.js +27 -0
  37. package/lib/modifier/calculatePaymentModifier.js +67 -0
  38. package/lib/modifier/createDiscountModifier.js +2 -1
  39. package/lib/modifier/createFeeModifier.js +2 -1
  40. package/lib/modifier/getChildren.js +8 -0
  41. package/lib/modifier/getComputedAmount.js +9 -0
  42. package/lib/modifier/hasPaymentMethodType.js +14 -0
  43. package/lib/modifier/index.js +33 -9
  44. package/lib/modifier/isCalculatedPaymentModifier.js +4 -0
  45. package/lib/modifier/isChild.js +6 -0
  46. package/lib/modifier/isDiscount.js +6 -2
  47. package/lib/modifier/isFee.js +5 -2
  48. package/lib/modifier/isPaymentMethodModifier.js +4 -1
  49. package/lib/modifier/isPaymentTypeModifier.js +4 -1
  50. package/lib/modifier/isPercentage.js +10 -0
  51. package/lib/modifier/isValid.js +12 -0
  52. package/lib/modifier/sort.js +28 -0
  53. package/lib/modifier/validate.js +14 -0
  54. package/lib/modifier/validateDateDaysDiff.js +30 -0
  55. package/lib/modifier/validateInArr.js +12 -0
  56. package/lib/modifier/validateNumberCondition.js +20 -0
  57. package/lib/modifier/validateRequiredModifiers.js +16 -0
  58. package/lib/order/addItemModifier.js +72 -28
  59. package/lib/order/applyPayment.js +61 -0
  60. package/lib/order/calculate.js +45 -22
  61. package/lib/order/getBalance.js +0 -1
  62. package/lib/order/getOrdersBalance.js +8 -0
  63. package/lib/order/index.js +9 -10
  64. package/lib/order/manualSplit.js +34 -0
  65. package/lib/order/manualSplitByQuantity.js +50 -0
  66. package/lib/store/getRecommendedEndDate.js +13 -0
  67. package/lib/store/index.js +25 -0
  68. package/package.json +6 -4
  69. package/lib/item/getBalanceToPay.js +0 -12
  70. package/lib/item/getTotals.js +0 -40
  71. package/lib/item/markModifiersAsLocked.js +0 -11
  72. package/lib/modifier/createPaymentModifier.js +0 -12
  73. package/lib/modifier/findByPaymentMethod.js +0 -10
  74. package/lib/modifier/findByPaymentType.js +0 -10
  75. package/lib/modifier/getLockedModifiers.js +0 -5
  76. package/lib/order/markModifiersAsLocked.js +0 -14
  77. package/lib/order/removeModifiersWithPaymentMethods.js +0 -29
  78. package/lib/order/removeModifiersWithPaymentTypes.js +0 -27
  79. package/lib/{order → store}/pickEndDate.js +2 -2
@@ -0,0 +1,1117 @@
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
+ describe('Order actions', () => {
11
+ test('1. Calculate order withouth sending payment data. Then Pay with 1 USD, Then Pay with 2 USD, Then Pay with 10 USD (Cash Discount Percentage)', () => {
12
+ const cashDiscountModifier = {
13
+ _id: '670e7cd236bf42091cb35624',
14
+ attributes: [],
15
+ modifierId: '670d7f7e746d1ae0f847aba6',
16
+ _parentId: null,
17
+ locked: false,
18
+ name: 'CASH 10% DISCOUNT',
19
+ sku: '',
20
+ description: '',
21
+ group: 'Offers',
22
+ type: 'discount',
23
+ tags: ['default', 'all'],
24
+ conditions: {
25
+ valid: false,
26
+ rules: [
27
+ {
28
+ key: 'paymentTypes',
29
+ value: ['cash'],
30
+ operand: '$in',
31
+ },
32
+ ],
33
+ },
34
+ compute: {
35
+ type: 'percentage',
36
+ action: 'subtract',
37
+ amount: 10,
38
+ },
39
+ };
40
+ const orderItem = {
41
+ price: 10,
42
+ quantity: 1,
43
+ modifiers: [cashDiscountModifier],
44
+ total: 10,
45
+ totalPaid: 0,
46
+ };
47
+
48
+ let cashPercentageDiscountOrder = pricingService.order.calculate(
49
+ { items: [orderItem] },
50
+ { paymentType: 'cash' }
51
+ );
52
+
53
+ expect(cashPercentageDiscountOrder).toHaveProperty('total', 9);
54
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
55
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
56
+ discount: -1,
57
+ });
58
+ expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(1);
59
+
60
+ expect(cashPercentageDiscountOrder.items[0].modifiers[0]._computed).toEqual(
61
+ expect.objectContaining({
62
+ amount: 0,
63
+ description: 'CASH 10% DISCOUNT ($0.00)',
64
+ })
65
+ );
66
+
67
+ cashPercentageDiscountOrder = pricingService.order.calculate(
68
+ { items: [orderItem] },
69
+ {
70
+ paymentType: 'cash',
71
+ amountToPay: 1,
72
+ lockPaymentModifiers: true,
73
+ paymentId: '111',
74
+ }
75
+ );
76
+ cashPercentageDiscountOrder.items[0].totalPaid = 1;
77
+
78
+ expect(cashPercentageDiscountOrder).toHaveProperty('total', 9.89);
79
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
80
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
81
+ discount: -0.1111111111111112,
82
+ });
83
+ expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(2);
84
+
85
+ cashPercentageDiscountOrder = pricingService.order.calculate(
86
+ cashPercentageDiscountOrder,
87
+ {
88
+ paymentType: 'cash',
89
+ amountToPay: 2,
90
+ lockPaymentModifiers: true,
91
+ paymentId: '222',
92
+ }
93
+ );
94
+ cashPercentageDiscountOrder.items[0].totalPaid = 3;
95
+
96
+ expect(cashPercentageDiscountOrder).toHaveProperty('total', 9.67);
97
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
98
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
99
+ discount: -0.3333333333333335,
100
+ });
101
+ expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(3);
102
+ expect(cashPercentageDiscountOrder.items[0].modifiers[1]._computed).toEqual(
103
+ expect.objectContaining({
104
+ amount: -0.2222222222222223,
105
+ description: '$0.22 discount (-$0.22)',
106
+ })
107
+ );
108
+ expect(
109
+ cashPercentageDiscountOrder.items[0].modifiers[1].properties
110
+ ).toEqual(
111
+ expect.objectContaining({
112
+ isCalculatedPaymentModifier: true,
113
+ paymentId: '222',
114
+ })
115
+ );
116
+ expect(cashPercentageDiscountOrder.items[0].modifiers[2]._computed).toEqual(
117
+ expect.objectContaining({
118
+ amount: -0.1111111111111112,
119
+ description: '$0.11 discount (-$0.11)',
120
+ })
121
+ );
122
+ expect(
123
+ cashPercentageDiscountOrder.items[0].modifiers[2].properties
124
+ ).toEqual(
125
+ expect.objectContaining({
126
+ isCalculatedPaymentModifier: true,
127
+ paymentId: '111',
128
+ })
129
+ );
130
+
131
+ cashPercentageDiscountOrder = pricingService.order.calculate(
132
+ cashPercentageDiscountOrder,
133
+ {
134
+ paymentType: 'cash',
135
+ amountToPay: 7,
136
+ lockPaymentModifiers: true,
137
+ paymentId: '333',
138
+ }
139
+ );
140
+
141
+ expect(cashPercentageDiscountOrder).toHaveProperty('total', 9);
142
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
143
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
144
+ discount: -1.0003333333333333,
145
+ });
146
+ expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(4);
147
+ expect(cashPercentageDiscountOrder.items[0].modifiers[1]._computed).toEqual(
148
+ expect.objectContaining({
149
+ amount: -0.667,
150
+ description: '$0.67 discount (-$0.67)',
151
+ })
152
+ );
153
+ expect(cashPercentageDiscountOrder.items[0].modifiers[2]._computed).toEqual(
154
+ expect.objectContaining({
155
+ amount: -0.2222222222222223,
156
+ description: '$0.22 discount (-$0.22)',
157
+ })
158
+ );
159
+ expect(cashPercentageDiscountOrder.items[0].modifiers[3]._computed).toEqual(
160
+ expect.objectContaining({
161
+ amount: -0.1111111111111112,
162
+ description: '$0.11 discount (-$0.11)',
163
+ })
164
+ );
165
+ });
166
+
167
+ test('2. Calculate order without sending payment data. Then Pay with 1 USD, Then Pay with 2 USD (Cash Discount fixed)', () => {
168
+ const cashDiscountModifier = {
169
+ _id: '670e7cd236bf42091cb35624',
170
+ attributes: [],
171
+ modifierId: '670d7f7e746d1ae0f847aba6',
172
+ _parentId: null,
173
+ locked: false,
174
+ name: 'CASH 2 USD DISCOUNT',
175
+ sku: '',
176
+ description: '',
177
+ group: 'Offers',
178
+ type: 'discount',
179
+ tags: ['default', 'all'],
180
+ conditions: {
181
+ valid: false,
182
+ rules: [
183
+ {
184
+ key: 'paymentTypes',
185
+ value: ['cash'],
186
+ operand: '$in',
187
+ },
188
+ ],
189
+ },
190
+ compute: {
191
+ type: 'fixed',
192
+ action: 'subtract',
193
+ amount: 2,
194
+ },
195
+ };
196
+ const orderItem = {
197
+ price: 10,
198
+ quantity: 1,
199
+ modifiers: [cashDiscountModifier],
200
+ total: 10,
201
+ totalPaid: 0,
202
+ };
203
+
204
+ let cashFixedDiscountOrder = pricingService.order.calculate(
205
+ { items: [orderItem] },
206
+ { paymentType: 'cash' }
207
+ );
208
+
209
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 8);
210
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
211
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
212
+ discount: -2,
213
+ });
214
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(1);
215
+
216
+ cashFixedDiscountOrder = pricingService.order.calculate(
217
+ { items: [orderItem] },
218
+ {
219
+ paymentType: 'cash',
220
+ amountToPay: 1,
221
+ lockPaymentModifiers: true,
222
+ }
223
+ );
224
+ cashFixedDiscountOrder.items[0].totalPaid = 1;
225
+
226
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 8);
227
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
228
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
229
+ discount: -2,
230
+ });
231
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(2);
232
+
233
+ cashFixedDiscountOrder = pricingService.order.calculate(
234
+ cashFixedDiscountOrder,
235
+ {
236
+ paymentType: 'cash',
237
+ amountToPay: 100,
238
+ lockPaymentModifiers: true,
239
+ }
240
+ );
241
+ cashFixedDiscountOrder.items[0].totalPaid = 3;
242
+
243
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 8);
244
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
245
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
246
+ discount: -2,
247
+ });
248
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(2);
249
+ expect(cashFixedDiscountOrder.items[0].modifiers[1]._computed).toEqual(
250
+ expect.objectContaining({
251
+ amount: -2,
252
+ description: '$2.00 discount (-$2.00)',
253
+ })
254
+ );
255
+ });
256
+
257
+ test('3. Calculate order withouth sending payment data. Then Pay with 1 USD, Then Pay with 2 USD (Cash Fee fixed)', () => {
258
+ const cashDiscountModifier = {
259
+ _id: '670e7cd236bf42091cb35624',
260
+ attributes: [],
261
+ modifierId: '670d7f7e746d1ae0f847aba6',
262
+ _parentId: null,
263
+ locked: false,
264
+ name: 'CASH 2 USD FEE',
265
+ sku: '',
266
+ description: '',
267
+ group: 'Offers',
268
+ type: 'fee',
269
+ tags: ['default', 'all'],
270
+ conditions: {
271
+ valid: false,
272
+ rules: [
273
+ {
274
+ key: 'paymentTypes',
275
+ value: ['cash'],
276
+ operand: '$in',
277
+ },
278
+ ],
279
+ },
280
+ compute: {
281
+ type: 'fixed',
282
+ action: 'add',
283
+ amount: 2,
284
+ },
285
+ };
286
+ const orderItem = {
287
+ price: 10,
288
+ quantity: 1,
289
+ modifiers: [cashDiscountModifier],
290
+ total: 10,
291
+ totalPaid: 0,
292
+ };
293
+
294
+ let cashFixedDiscountOrder = pricingService.order.calculate(
295
+ { items: [orderItem] },
296
+ { paymentType: 'cash' }
297
+ );
298
+
299
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 12);
300
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
301
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
302
+ fee: 2,
303
+ });
304
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(1);
305
+
306
+ cashFixedDiscountOrder = pricingService.order.calculate(
307
+ { items: [orderItem] },
308
+ {
309
+ paymentType: 'cash',
310
+ amountToPay: 1,
311
+ lockPaymentModifiers: true,
312
+ }
313
+ );
314
+ cashFixedDiscountOrder.items[0].totalPaid = 1;
315
+
316
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 12);
317
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
318
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
319
+ fee: 2,
320
+ });
321
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(2);
322
+
323
+ cashFixedDiscountOrder = pricingService.order.calculate(
324
+ cashFixedDiscountOrder,
325
+ {
326
+ paymentType: 'cash',
327
+ amountToPay: 100,
328
+ lockPaymentModifiers: true,
329
+ }
330
+ );
331
+ cashFixedDiscountOrder.items[0].totalPaid = 3;
332
+
333
+ expect(cashFixedDiscountOrder).toHaveProperty('total', 12);
334
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotal', 10);
335
+ expect(cashFixedDiscountOrder).toHaveProperty('subTotals', {
336
+ fee: 2,
337
+ });
338
+ expect(cashFixedDiscountOrder.items[0].modifiers).toHaveLength(2);
339
+ expect(cashFixedDiscountOrder.items[0].modifiers[1]._computed).toEqual(
340
+ expect.objectContaining({
341
+ amount: 2,
342
+ description: '$2.00 fee ($2.00)',
343
+ })
344
+ );
345
+ });
346
+
347
+ test('4. Calculate order withouth sending payment data. Then Pay with 1 USD, Then Pay with 2 USD, Then Pay with 10 USD (Cash Discount Percentage)', () => {
348
+ const cashFeeModifier = {
349
+ _id: '670e7cd236bf42091cb35624',
350
+ attributes: [],
351
+ modifierId: '670d7f7e746d1ae0f847aba6',
352
+ _parentId: null,
353
+ locked: false,
354
+ name: 'CASH 10% DISCOUNT',
355
+ sku: '',
356
+ description: '',
357
+ group: 'Offers',
358
+ type: 'fee',
359
+ tags: ['default', 'all'],
360
+ conditions: {
361
+ valid: false,
362
+ rules: [
363
+ {
364
+ key: 'paymentTypes',
365
+ value: ['cash'],
366
+ operand: '$in',
367
+ },
368
+ ],
369
+ },
370
+ compute: {
371
+ type: 'percentage',
372
+ action: 'add',
373
+ amount: 10,
374
+ },
375
+ };
376
+ const orderItem = {
377
+ price: 10,
378
+ quantity: 1,
379
+ modifiers: [cashFeeModifier],
380
+ total: 10,
381
+ totalPaid: 0,
382
+ };
383
+
384
+ const cashPercentageDiscountOrder = pricingService.order.calculate(
385
+ { items: [orderItem] },
386
+ { paymentType: 'cash', amountToPay: 1, lockPaymentModifiers: true }
387
+ );
388
+
389
+ expect(cashPercentageDiscountOrder).toHaveProperty('total', 10.1);
390
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
391
+ expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
392
+ fee: 0.1,
393
+ });
394
+ expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(2);
395
+ });
396
+ test('5. Calculate order withouth sending payment data. Including payment modifiers and others (tax)', () => {
397
+ const cashFeeModifier = {
398
+ _id: '670e7cd236bf42091cb35624',
399
+ attributes: [],
400
+ modifierId: '670d7f7e746d1ae0f847aba6',
401
+ _parentId: null,
402
+ locked: false,
403
+ name: 'CASH 20% DISCOUNT',
404
+ sku: '',
405
+ description: '',
406
+ group: 'Offers',
407
+ type: 'fee',
408
+ tags: ['default', 'all'],
409
+ conditions: {
410
+ valid: false,
411
+ rules: [
412
+ {
413
+ key: 'paymentTypes',
414
+ value: ['cash'],
415
+ operand: '$in',
416
+ },
417
+ ],
418
+ },
419
+ compute: {
420
+ type: 'percentage',
421
+ action: 'subtract',
422
+ amount: 20,
423
+ },
424
+ };
425
+
426
+ const taxModifier = {
427
+ _id: '670e7cd236bf42091cb35626',
428
+ attributes: [],
429
+ modifierId: '670d7f7e746d1ae0f847aba5',
430
+ _parentId: null,
431
+ locked: false,
432
+ name: '5% FEE',
433
+ sku: '',
434
+ description: '',
435
+ group: 'Offers',
436
+ type: 'fee',
437
+ tags: ['default', 'all'],
438
+ compute: {
439
+ type: 'percentage',
440
+ action: 'add',
441
+ amount: 5,
442
+ },
443
+ properties: {
444
+ sort: 1,
445
+ },
446
+ };
447
+ const orderItem = {
448
+ price: 13.5,
449
+ quantity: 1,
450
+ modifiers: [taxModifier, cashFeeModifier],
451
+ total: 13.5,
452
+ totalPaid: 0,
453
+ };
454
+
455
+ let testOrder = pricingService.order.calculate(
456
+ { items: [orderItem] },
457
+ { paymentType: 'cash' }
458
+ );
459
+
460
+ expect(testOrder).toHaveProperty('total', 11.34);
461
+ expect(testOrder).toHaveProperty('subTotal', 13.5);
462
+ expect(testOrder).toHaveProperty('subTotals', {
463
+ discount: -2.835,
464
+ fee: 0.675,
465
+ });
466
+
467
+ expect(testOrder.items[0].modifiers).toHaveLength(2);
468
+
469
+ expect(testOrder.items[0].modifiers[0]._computed).toEqual(
470
+ expect.objectContaining({
471
+ amount: 0,
472
+ description: 'CASH 20% DISCOUNT ($0.00)',
473
+ })
474
+ );
475
+
476
+ expect(testOrder.items[0].modifiers[1]._computed).toEqual(
477
+ expect.objectContaining({
478
+ amount: 0.675,
479
+ description: '5% FEE ($0.68)',
480
+ })
481
+ );
482
+
483
+ testOrder = pricingService.order.calculate(testOrder, {
484
+ paymentType: 'cash',
485
+ amountToPay: 10.34,
486
+ lockPaymentModifiers: true,
487
+ });
488
+ testOrder.items[0].totalPaid = 10.34;
489
+ testOrder.totalPaid = 10.34;
490
+
491
+ expect(testOrder).toHaveProperty('total', 11.59);
492
+ expect(testOrder).toHaveProperty('subTotal', 13.5);
493
+ expect(testOrder).toHaveProperty('subTotals', {
494
+ discount: -2.585,
495
+ fee: 0.675,
496
+ });
497
+
498
+ expect(testOrder.items[0].modifiers).toHaveLength(3);
499
+
500
+ expect(testOrder.items[0].modifiers[0]._computed).toEqual(
501
+ expect.objectContaining({
502
+ amount: 0,
503
+ description: 'CASH 20% DISCOUNT ($0.00)',
504
+ })
505
+ );
506
+
507
+ expect(testOrder.items[0].modifiers[1]._computed).toEqual(
508
+ expect.objectContaining({
509
+ amount: 0.675,
510
+ description: '5% FEE ($0.68)',
511
+ })
512
+ );
513
+
514
+ expect(testOrder.items[0].modifiers[2]._computed).toEqual(
515
+ expect.objectContaining({
516
+ amount: -2.585,
517
+ description: '$2.59 discount (-$2.59)',
518
+ })
519
+ );
520
+
521
+ // calling without payment modifier should return the same result as previous calculate
522
+ testOrder = pricingService.order.calculate(testOrder);
523
+
524
+ expect(testOrder).toHaveProperty('total', 11.59);
525
+ expect(testOrder).toHaveProperty('subTotal', 13.5);
526
+ expect(testOrder).toHaveProperty('subTotals', {
527
+ discount: -2.585,
528
+ fee: 0.675,
529
+ });
530
+
531
+ expect(testOrder.items[0].modifiers).toHaveLength(3);
532
+
533
+ expect(testOrder.items[0].modifiers[0]._computed).toEqual(
534
+ expect.objectContaining({
535
+ amount: 0,
536
+ description: 'CASH 20% DISCOUNT ($0.00)',
537
+ })
538
+ );
539
+
540
+ expect(testOrder.items[0].modifiers[1]._computed).toEqual(
541
+ expect.objectContaining({
542
+ amount: 0.675,
543
+ description: '5% FEE ($0.68)',
544
+ })
545
+ );
546
+
547
+ expect(testOrder.items[0].modifiers[2]._computed).toEqual(
548
+ expect.objectContaining({
549
+ amount: -2.585,
550
+ description: '$2.59 discount (-$2.59)',
551
+ })
552
+ );
553
+
554
+ const orderBalance = pricingService.order.getOrdersBalance({
555
+ orders: [testOrder],
556
+ });
557
+ const itemBalance = pricingService.item.getItemsBalance({
558
+ items: testOrder.items,
559
+ });
560
+
561
+ expect(orderBalance).toEqual(1.25);
562
+ expect(itemBalance).toEqual(1.25);
563
+
564
+ // paying with a paymenttype that doesn match the payment modifiers
565
+ const fullyPaidOrderWithCredit = pricingService.order.calculate(testOrder, {
566
+ paymentType: 'credit',
567
+ amountToPay: 1.25,
568
+ lockPaymentModifiers: true,
569
+ });
570
+ fullyPaidOrderWithCredit.items[0].totalPaid += 1.25;
571
+ fullyPaidOrderWithCredit.totalPaid += 1.25;
572
+
573
+ const orderBalanceWithCredit = pricingService.order.getOrdersBalance({
574
+ orders: [fullyPaidOrderWithCredit],
575
+ });
576
+ const itemBalanceWithCredit = pricingService.item.getItemsBalance({
577
+ items: fullyPaidOrderWithCredit.items,
578
+ });
579
+
580
+ expect(fullyPaidOrderWithCredit).toHaveProperty('total', 11.59);
581
+ expect(fullyPaidOrderWithCredit).toHaveProperty('subTotal', 13.5);
582
+ expect(fullyPaidOrderWithCredit).toHaveProperty('subTotals', {
583
+ discount: -2.585,
584
+ fee: 0.675,
585
+ });
586
+
587
+ expect(fullyPaidOrderWithCredit.items[0].modifiers).toHaveLength(3);
588
+
589
+ expect(fullyPaidOrderWithCredit.items[0].modifiers[0]._computed).toEqual(
590
+ expect.objectContaining({
591
+ amount: 0,
592
+ description: 'CASH 20% DISCOUNT ($0.00)',
593
+ })
594
+ );
595
+
596
+ expect(fullyPaidOrderWithCredit.items[0].modifiers[1]._computed).toEqual(
597
+ expect.objectContaining({
598
+ amount: 0.675,
599
+ description: '5% FEE ($0.68)',
600
+ })
601
+ );
602
+
603
+ expect(fullyPaidOrderWithCredit.items[0].modifiers[2]._computed).toEqual(
604
+ expect.objectContaining({
605
+ amount: -2.585,
606
+ description: '$2.59 discount (-$2.59)',
607
+ })
608
+ );
609
+
610
+ expect(orderBalanceWithCredit).toEqual(0);
611
+ expect(itemBalanceWithCredit).toEqual(0);
612
+
613
+ // paying with a paymenttype that doesn match the payment modifiers
614
+ const fullyPaidOrderWithCash = pricingService.order.calculate(testOrder, {
615
+ paymentType: 'cash',
616
+ amountToPay: 1,
617
+ lockPaymentModifiers: true,
618
+ });
619
+ fullyPaidOrderWithCash.items[0].totalPaid += 1;
620
+ fullyPaidOrderWithCash.totalPaid += 1;
621
+
622
+ const orderBalanceWithCash = pricingService.order.getOrdersBalance({
623
+ orders: [fullyPaidOrderWithCash],
624
+ });
625
+ const itemBalanceWithCash = pricingService.item.getItemsBalance({
626
+ items: fullyPaidOrderWithCash.items,
627
+ });
628
+
629
+ expect(fullyPaidOrderWithCash).toHaveProperty('total', 11.34);
630
+ expect(fullyPaidOrderWithCash).toHaveProperty('subTotal', 13.5);
631
+ expect(fullyPaidOrderWithCash).toHaveProperty('subTotals', {
632
+ discount: -2.835,
633
+ fee: 0.675,
634
+ });
635
+
636
+ expect(fullyPaidOrderWithCash.items[0].modifiers).toHaveLength(4);
637
+
638
+ expect(fullyPaidOrderWithCash.items[0].modifiers[0]._computed).toEqual(
639
+ expect.objectContaining({
640
+ amount: 0,
641
+ description: 'CASH 20% DISCOUNT ($0.00)',
642
+ })
643
+ );
644
+
645
+ expect(fullyPaidOrderWithCash.items[0].modifiers[1]._computed).toEqual(
646
+ expect.objectContaining({
647
+ amount: 0.675,
648
+ description: '5% FEE ($0.68)',
649
+ })
650
+ );
651
+
652
+ expect(fullyPaidOrderWithCash.items[0].modifiers[2]._computed).toEqual(
653
+ expect.objectContaining({
654
+ amount: -0.25,
655
+ description: '$0.25 discount (-$0.25)',
656
+ })
657
+ );
658
+
659
+ expect(fullyPaidOrderWithCash.items[0].modifiers[3]._computed).toEqual(
660
+ expect.objectContaining({
661
+ amount: -2.585,
662
+ description: '$2.59 discount (-$2.59)',
663
+ })
664
+ );
665
+
666
+ expect(orderBalanceWithCash).toEqual(0);
667
+ expect(itemBalanceWithCash).toEqual(0);
668
+ });
669
+ test('6. Calculate partially paid order with tax and paymend modifiers', () => {
670
+ const partiallyPaidOrder = {
671
+ _id: '671818e11381a2923de66631',
672
+ displayId: '1156-1',
673
+ items: [
674
+ {
675
+ _id: '671818d30e5dd150d9830901',
676
+ name: "Men's 3pc Tuxedo",
677
+ subTotals: {
678
+ _included: 0,
679
+ _xincluded: -1.91,
680
+ _direct: -1.91,
681
+ _xdirect: 0,
682
+ _simple: 13.5,
683
+ _actual: 13.5,
684
+ null: 0,
685
+ '': 0,
686
+ tax: 0.675,
687
+ discount: -2.585,
688
+ },
689
+ modifiers: [
690
+ {
691
+ _id: '671818d40e5dd150d9830904',
692
+ attributes: ['override'],
693
+ modifierId: '62cdbfd01ee1b4001932818f',
694
+ _parentId: null,
695
+ locked: null,
696
+ name: 'Alice Blue',
697
+ sku: '',
698
+ description: 'Color: White',
699
+ group: 'Color',
700
+ type: '',
701
+ tags: [],
702
+ order: 0,
703
+ included: false,
704
+ direct: true,
705
+ hidden: false,
706
+ print: true,
707
+ required: false,
708
+ recommended: false,
709
+ default: false,
710
+ code: '',
711
+ properties: {
712
+ override: {
713
+ field: 'price',
714
+ type: 'manual',
715
+ multiplier: true,
716
+ },
717
+ group: null,
718
+ sort: null,
719
+ },
720
+ _computed: {
721
+ amount: 0,
722
+ description: 'Alice Blue ($0.00)',
723
+ },
724
+ addModifiers: [],
725
+ delModifiers: [],
726
+ conditions: {
727
+ valid: true,
728
+ rules: [],
729
+ },
730
+ compute: null,
731
+ _createdAt: '2024-10-22T21:30:43.071Z',
732
+ _updatedAt: '2024-10-22T21:30:43.071Z',
733
+ },
734
+ {
735
+ _id: '671818d60e5dd150d983090a',
736
+ attributes: [],
737
+ modifierId: '670d7f7e746d1ae0f847aba6',
738
+ _parentId: null,
739
+ locked: false,
740
+ name: 'CASH 20% DISCOUNT',
741
+ sku: '',
742
+ description: '',
743
+ group: 'Offers',
744
+ type: 'discount',
745
+ tags: ['default', 'all'],
746
+ order: null,
747
+ included: false,
748
+ direct: true,
749
+ hidden: false,
750
+ print: true,
751
+ required: false,
752
+ recommended: false,
753
+ default: false,
754
+ code: '',
755
+ properties: {
756
+ override: null,
757
+ group: {
758
+ items: [],
759
+ modifiers: [],
760
+ },
761
+ sort: null,
762
+ },
763
+ _computed: {
764
+ amount: 0,
765
+ description: 'CASH 20% DISCOUNT ($0.00)',
766
+ },
767
+ addModifiers: [],
768
+ delModifiers: [],
769
+ conditions: {
770
+ valid: false,
771
+ rules: [
772
+ {
773
+ key: 'paymentTypes',
774
+ value: ['cash'],
775
+ operand: '$in',
776
+ },
777
+ ],
778
+ },
779
+ compute: {
780
+ type: 'percentage',
781
+ action: 'subtract',
782
+ amount: 20,
783
+ },
784
+ _createdAt: '2024-10-22T21:30:43.071Z',
785
+ _updatedAt: '2024-10-22T21:30:43.071Z',
786
+ },
787
+ {
788
+ _id: '671819031381a2923de66638',
789
+ attributes: [],
790
+ modifierId: '62cdbfd01ee1b4001932822e',
791
+ _parentId: '62cdbfd01ee1b4001932822e',
792
+ locked: null,
793
+ name: 'Light',
794
+ sku: '',
795
+ description: '',
796
+ group: 'Starch',
797
+ type: null,
798
+ tags: [],
799
+ order: 2,
800
+ included: false,
801
+ direct: false,
802
+ hidden: false,
803
+ print: true,
804
+ required: false,
805
+ recommended: false,
806
+ default: false,
807
+ code: 'L',
808
+ properties: {
809
+ ignoreQuantity: false,
810
+ },
811
+ _computed: {
812
+ amount: 0,
813
+ description: 'Light ($0.00)',
814
+ },
815
+ addModifiers: [],
816
+ delModifiers: [],
817
+ conditions: {
818
+ valid: true,
819
+ rules: [],
820
+ },
821
+ compute: {
822
+ type: 'fixed',
823
+ action: 'subtract',
824
+ amount: 0,
825
+ },
826
+ _createdAt: '2024-10-22T21:30:43.071Z',
827
+ _updatedAt: '2024-10-22T21:30:43.071Z',
828
+ },
829
+ {
830
+ _id: '671819031381a2923de66639',
831
+ attributes: [],
832
+ modifierId: '66cd14a4b74b7da4b9f195d3',
833
+ _parentId: '66cd14a4b74b7da4b9f195d3',
834
+ locked: false,
835
+ name: 'Box',
836
+ sku: '',
837
+ description: 'Packing in a box.',
838
+ group: 'Packing',
839
+ type: '',
840
+ tags: ['default'],
841
+ order: 0,
842
+ included: false,
843
+ direct: false,
844
+ hidden: false,
845
+ print: true,
846
+ required: false,
847
+ recommended: false,
848
+ default: false,
849
+ code: '',
850
+ properties: {
851
+ ignoreQuantity: false,
852
+ group: {
853
+ modifiers: [],
854
+ items: [],
855
+ },
856
+ sort: null,
857
+ },
858
+ _computed: {
859
+ amount: 0,
860
+ description: 'Box ($0.00)',
861
+ },
862
+ addModifiers: [],
863
+ delModifiers: [],
864
+ conditions: {
865
+ valid: true,
866
+ rules: [],
867
+ },
868
+ compute: {
869
+ type: 'fixed',
870
+ action: 'subtract',
871
+ amount: 0,
872
+ },
873
+ _createdAt: '2024-10-22T21:30:43.071Z',
874
+ _updatedAt: '2024-10-22T21:30:43.071Z',
875
+ },
876
+ {
877
+ _id: '671818d40e5dd150d9830907',
878
+ attributes: [],
879
+ modifierId: '63eac132206c79815373e426',
880
+ _parentId: null,
881
+ locked: false,
882
+ name: 'Sales Tax v2',
883
+ sku: '',
884
+ description: 'test',
885
+ group: '',
886
+ type: 'tax',
887
+ tags: ['default'],
888
+ order: 0,
889
+ included: false,
890
+ direct: true,
891
+ hidden: true,
892
+ print: true,
893
+ required: true,
894
+ recommended: false,
895
+ default: false,
896
+ code: '',
897
+ properties: {
898
+ group: {
899
+ items: [],
900
+ modifiers: [],
901
+ },
902
+ sort: 1,
903
+ },
904
+ _computed: {
905
+ amount: 0.675,
906
+ description: 'Sales Tax v2 ($0.68)',
907
+ },
908
+ addModifiers: [],
909
+ delModifiers: [],
910
+ conditions: {
911
+ valid: true,
912
+ rules: [],
913
+ },
914
+ compute: {
915
+ type: 'percentage',
916
+ action: 'add',
917
+ amount: 5,
918
+ },
919
+ _createdAt: '2024-10-22T21:30:43.071Z',
920
+ _updatedAt: '2024-10-22T21:30:43.071Z',
921
+ },
922
+ {
923
+ _id: '671819061381a2923de6663a',
924
+ attributes: [],
925
+ modifierId: '670d7f7e746d1ae0f847aba6',
926
+ _parentId: '671818d60e5dd150d983090a',
927
+ locked: false,
928
+ name: '$2.59 discount',
929
+ sku: '',
930
+ description: '',
931
+ group: '',
932
+ type: 'discount',
933
+ tags: [],
934
+ order: 0,
935
+ included: false,
936
+ direct: true,
937
+ hidden: false,
938
+ print: true,
939
+ required: false,
940
+ recommended: false,
941
+ default: false,
942
+ code: '',
943
+ properties: {
944
+ override: null,
945
+ group: {
946
+ items: [],
947
+ modifiers: [],
948
+ },
949
+ sort: null,
950
+ isCalculatedPaymentModifier: true,
951
+ },
952
+ _computed: {
953
+ amount: -2.585,
954
+ description: '$2.59 discount (-$2.59)',
955
+ },
956
+ addModifiers: [],
957
+ delModifiers: [],
958
+ conditions: null,
959
+ compute: {
960
+ type: 'fixed',
961
+ action: 'subtract',
962
+ amount: 2.585,
963
+ },
964
+ _createdAt: '2024-10-22T21:30:43.071Z',
965
+ _updatedAt: '2024-10-22T21:30:43.071Z',
966
+ },
967
+ ],
968
+ price: 13.5,
969
+ quantity: 1,
970
+ pieces: 3,
971
+ status: {
972
+ picked: {
973
+ value: false,
974
+ date: '',
975
+ },
976
+ paid: {
977
+ value: false,
978
+ date: '2024-10-22T21:28:36.505Z',
979
+ },
980
+ tracker: [],
981
+ },
982
+ totalPaid: 10.34,
983
+ itemId: '62cdbfd01ee1b400193281ee',
984
+ total: 11.59,
985
+ },
986
+ ],
987
+ customer: {
988
+ _id: '651c76bff4a3602953356e87',
989
+ tags: ['default', 'all'],
990
+ },
991
+ modifiers: [
992
+ {
993
+ _id: '62cdbfd01ee1b4001932822e',
994
+ attributes: [],
995
+ modifierId: null,
996
+ _parentId: null,
997
+ locked: null,
998
+ name: 'Light',
999
+ sku: '',
1000
+ description: '',
1001
+ group: 'Starch',
1002
+ type: null,
1003
+ tags: [],
1004
+ order: 2,
1005
+ included: false,
1006
+ direct: true,
1007
+ hidden: false,
1008
+ print: true,
1009
+ required: false,
1010
+ recommended: false,
1011
+ default: false,
1012
+ code: 'L',
1013
+ properties: null,
1014
+ _computed: null,
1015
+ addModifiers: [],
1016
+ delModifiers: [],
1017
+ conditions: null,
1018
+ compute: null,
1019
+ _createdAt: '2024-10-22T21:28:35.551Z',
1020
+ _updatedAt: '2024-10-22T21:28:35.551Z',
1021
+ },
1022
+ {
1023
+ _id: '66cd14a4b74b7da4b9f195d3',
1024
+ attributes: [],
1025
+ modifierId: null,
1026
+ _parentId: null,
1027
+ locked: false,
1028
+ name: 'Box',
1029
+ sku: '',
1030
+ description: 'Packing in a box.',
1031
+ group: 'Packing',
1032
+ type: '',
1033
+ tags: ['default'],
1034
+ order: 0,
1035
+ included: false,
1036
+ direct: true,
1037
+ hidden: false,
1038
+ print: true,
1039
+ required: false,
1040
+ recommended: false,
1041
+ default: false,
1042
+ code: '',
1043
+ properties: {
1044
+ group: {
1045
+ modifiers: [],
1046
+ items: [],
1047
+ },
1048
+ sort: null,
1049
+ },
1050
+ _computed: null,
1051
+ addModifiers: [],
1052
+ delModifiers: [],
1053
+ conditions: null,
1054
+ compute: {
1055
+ type: null,
1056
+ action: null,
1057
+ amount: 0,
1058
+ },
1059
+ _createdAt: '2024-10-22T21:28:35.551Z',
1060
+ _updatedAt: '2024-10-22T21:28:35.551Z',
1061
+ },
1062
+ ],
1063
+ start: {
1064
+ requestDate: '2024-10-22T21:27:29.846Z',
1065
+ },
1066
+ end: {
1067
+ requestDate: '2024-10-25T07:00:00.000Z',
1068
+ },
1069
+ subTotal: 13.5,
1070
+ subTotals: {
1071
+ null: 0,
1072
+ '': 0,
1073
+ tax: 0.68,
1074
+ },
1075
+ totalPaid: 10.34,
1076
+ total: 11.59,
1077
+ };
1078
+
1079
+ const resultedOrder = pricingService.order.calculate(partiallyPaidOrder, {
1080
+ paymentType: 'cash',
1081
+ });
1082
+
1083
+ expect(resultedOrder.items[0].total).toEqual(11.34);
1084
+
1085
+ expect(resultedOrder).toHaveProperty('total', 11.34);
1086
+ expect(resultedOrder).toHaveProperty('subTotal', 13.5);
1087
+ expect(resultedOrder).toHaveProperty('subTotals', {
1088
+ '': 0,
1089
+ discount: -2.835,
1090
+ null: 0,
1091
+ tax: 0.675,
1092
+ });
1093
+
1094
+ expect(resultedOrder.items[0].modifiers).toHaveLength(6);
1095
+
1096
+ expect(resultedOrder.items[0].modifiers[0]._computed).toEqual(
1097
+ expect.objectContaining({
1098
+ amount: 0,
1099
+ description: 'Alice Blue ($0.00)',
1100
+ })
1101
+ );
1102
+
1103
+ expect(resultedOrder.items[0].modifiers[1]._computed).toEqual(
1104
+ expect.objectContaining({
1105
+ amount: 0,
1106
+ description: 'CASH 20% DISCOUNT ($0.00)',
1107
+ })
1108
+ );
1109
+
1110
+ expect(resultedOrder.items[0].modifiers[2]._computed).toEqual(
1111
+ expect.objectContaining({
1112
+ amount: 0.675,
1113
+ description: 'Sales Tax v2 ($0.68)',
1114
+ })
1115
+ );
1116
+ });
1117
+ });