@darkpos/pricing 1.0.31 → 1.0.33

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 (31) hide show
  1. package/__TEST__/item/addIndirectModifier.test.js +192 -0
  2. package/__TEST__/modifier/calculate.test.js +35 -4
  3. package/__TEST__/modifier/createIndirectModifier.test.js +166 -0
  4. package/__TEST__/modifier/getFixedModifiersTotal.test.js +52 -0
  5. package/__TEST__/modifier/getSplittedModifiers.test.js +134 -0
  6. package/__TEST__/modifier/isComputedOverride.test.js +38 -0
  7. package/__TEST__/order/addItem.test.js +57 -53
  8. package/__TEST__/order/adjustFixedModifiersDifference.test.js +117 -0
  9. package/__TEST__/order/order.test.js +47 -0
  10. package/__TEST__/order/split.test.js +356 -0
  11. package/lib/item/addIndirectModifier.js +5 -2
  12. package/lib/item/calculate.js +5 -1
  13. package/lib/item/getItemsTotalQuantity.js +7 -0
  14. package/lib/item/getItemsTotalWeight.js +7 -0
  15. package/lib/item/getTotalPieces.js +1 -1
  16. package/lib/item/getTotalQuantity.js +5 -0
  17. package/lib/item/getTotalWeight.js +7 -0
  18. package/lib/item/index.js +8 -0
  19. package/lib/modifier/calculate.js +5 -2
  20. package/lib/modifier/createIndirectModifier.js +4 -3
  21. package/lib/modifier/getFixedModifiersTotal.js +5 -4
  22. package/lib/modifier/getSplittedModifiers.js +5 -7
  23. package/lib/modifier/index.js +0 -2
  24. package/lib/modifier/isComputedOverride.js +3 -2
  25. package/lib/modifier/utils.js +10 -0
  26. package/lib/order/addItemModifier.js +9 -4
  27. package/lib/order/addModifier.js +6 -4
  28. package/lib/order/adjustFixedModifiersDifference.js +10 -9
  29. package/lib/order/splitByDepartments.js +37 -7
  30. package/package.json +2 -2
  31. package/lib/modifier/includePiecesInQuantity.js +0 -10
@@ -0,0 +1,192 @@
1
+ const _ = require('lodash');
2
+ const utils = require('@darkpos/utils');
3
+ const addIndirectModifierFunction = require('../../lib/item/addIndirectModifier');
4
+
5
+ describe('addIndirectModifier Function', () => {
6
+ const modifierActions = {
7
+ calculate: jest.fn(),
8
+ createIndirectModifier: jest.fn(),
9
+ };
10
+
11
+ const getComputeModField = jest.fn();
12
+ // const modifierActions = makeModifierActions(deps);
13
+
14
+ const addIndirectModifier = addIndirectModifierFunction({
15
+ utils,
16
+ modifierActions,
17
+ _,
18
+ });
19
+
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+ });
23
+
24
+ test('should correctly distribute modifier across items when totals match', () => {
25
+ const modifier = {
26
+ modifier: { type: 'non-credit', action: 'add', amount: 50 },
27
+ };
28
+ const items = [
29
+ { _id: 'item1', total: 50, quantity: 2 },
30
+ { _id: 'item2', total: 50, quantity: 1 },
31
+ ];
32
+ const orderTotal = 100;
33
+ modifierActions.calculate.mockReturnValueOnce({
34
+ _computed: { amount: 100 },
35
+ });
36
+ modifierActions.createIndirectModifier
37
+ .mockReturnValueOnce({ compute: { amount: 25 }, properties: {} })
38
+ .mockReturnValueOnce({ compute: { amount: 50 }, properties: {} });
39
+
40
+ const result = addIndirectModifier({ orderTotal, items, modifier });
41
+
42
+ expect(result).toEqual({
43
+ item1: {
44
+ compute: { amount: 25 },
45
+ properties: {},
46
+ },
47
+ item2: {
48
+ compute: { amount: 50 },
49
+ properties: {},
50
+ },
51
+ });
52
+ });
53
+
54
+ test('should adjust the modifier on one item when totals do not match', () => {
55
+ const modifier = { modifier: { type: 'non-credit' } };
56
+ const items = [
57
+ { _id: 'item1', total: 50, quantity: 2 },
58
+ { _id: 'item2', total: 50, quantity: 1 },
59
+ ];
60
+ const orderTotal = 100;
61
+
62
+ modifierActions.calculate.mockReturnValueOnce({
63
+ _computed: { amount: 100 },
64
+ });
65
+ modifierActions.createIndirectModifier
66
+ .mockReturnValueOnce({ compute: { amount: 20 }, properties: {} })
67
+ .mockReturnValueOnce({ compute: { amount: 50 }, properties: {} });
68
+
69
+ const result = addIndirectModifier({ orderTotal, items, modifier });
70
+
71
+ expect(result).toEqual({
72
+ item1: {
73
+ compute: { amount: 50 }, // Adjusted amount to fix the total distribution difference
74
+ properties: { ignoreQuantity: true },
75
+ },
76
+ item2: { compute: { amount: 50 }, properties: {} },
77
+ });
78
+ });
79
+
80
+ test('should not adjust the modifier if compute type is percentage and modifier is not credit', () => {
81
+ const modifier = {
82
+ modifier: { type: 'non-credit' },
83
+ };
84
+ const items = [
85
+ {
86
+ _id: 'item1',
87
+ total: 50,
88
+ quantity: 2,
89
+ compute: { type: 'percentage', amount: 10, action: '' },
90
+ },
91
+ {
92
+ _id: 'item2',
93
+ total: 50,
94
+ quantity: 1,
95
+ compute: { type: 'percentage', amount: 10, action: '' },
96
+ },
97
+ ];
98
+ const orderTotal = 100;
99
+
100
+ getComputeModField.mockReturnValueOnce({ type: 'percentage' });
101
+ modifierActions.calculate
102
+ .mockReturnValueOnce({
103
+ compute: { amount: 20 },
104
+ properties: {},
105
+ _computed: { amount: 15 },
106
+ })
107
+ .mockReturnValueOnce({
108
+ compute: { amount: 50 },
109
+ properties: {},
110
+ _computed: { amount: 20 },
111
+ });
112
+ modifierActions.createIndirectModifier
113
+ .mockReturnValueOnce({
114
+ compute: { amount: 20 },
115
+ properties: {},
116
+ _computed: { amount: 15 },
117
+ })
118
+ .mockReturnValueOnce({
119
+ compute: { amount: 50 },
120
+ properties: {},
121
+ _computed: { amount: 20 },
122
+ });
123
+
124
+ const result = addIndirectModifier({ orderTotal, items, modifier });
125
+
126
+ expect(result).toEqual({
127
+ item1: {
128
+ compute: { amount: -35 },
129
+ properties: {
130
+ ignoreQuantity: true,
131
+ },
132
+ _computed: { amount: 15 },
133
+ },
134
+ item2: {
135
+ compute: { amount: 50 },
136
+ properties: {},
137
+ _computed: { amount: 20 },
138
+ },
139
+ });
140
+ });
141
+
142
+ test('should return itemsModifiers as is if totalDistributed equals orderModifierTotal', () => {
143
+ const modifier = { modifier: { type: 'non-credit' } };
144
+ const items = [
145
+ { _id: 'item1', total: 50, quantity: 2 },
146
+ { _id: 'item2', total: 50, quantity: 1 },
147
+ ];
148
+ const orderTotal = 100;
149
+ modifierActions.calculate.mockReturnValueOnce({
150
+ _computed: { amount: 100 },
151
+ });
152
+
153
+ modifierActions.createIndirectModifier
154
+ .mockReturnValueOnce({ compute: { amount: 25 }, properties: {} })
155
+ .mockReturnValueOnce({ compute: { amount: 50 }, properties: {} });
156
+
157
+ const result = addIndirectModifier({ orderTotal, items, modifier });
158
+
159
+ expect(result).toEqual({
160
+ item1: {
161
+ compute: { amount: -30 },
162
+ properties: {
163
+ ignoreQuantity: true,
164
+ },
165
+ },
166
+ item2: { compute: { amount: 50 }, properties: {} },
167
+ });
168
+ });
169
+
170
+ test('should not modify any items if totalDistributed exceeds orderModifierTotal and no item can cover the difference', () => {
171
+ const modifier = { modifier: { type: 'non-credit' } };
172
+ const items = [
173
+ { _id: 'item1', total: 10, quantity: 1 },
174
+ { _id: 'item2', total: 10, quantity: 1 },
175
+ ];
176
+ const orderTotal = 20;
177
+
178
+ modifierActions.calculate.mockReturnValueOnce({
179
+ _computed: { amount: 100 },
180
+ });
181
+ modifierActions.createIndirectModifier
182
+ .mockReturnValueOnce({ compute: { amount: 40 }, properties: {} })
183
+ .mockReturnValueOnce({ compute: { amount: 40 }, properties: {} });
184
+
185
+ const result = addIndirectModifier({ orderTotal, items, modifier });
186
+
187
+ expect(result).toEqual({
188
+ item1: { compute: { amount: 40 }, properties: {} },
189
+ item2: { compute: { amount: 40 }, properties: {} },
190
+ });
191
+ });
192
+ });
@@ -1,5 +1,6 @@
1
1
  const usePricing = require('../../index');
2
2
 
3
+ const { getComputeModField } = require('../../lib/modifier/utils');
3
4
  const pricingService = usePricing();
4
5
 
5
6
  describe('Calculate Function', () => {
@@ -13,7 +14,10 @@ describe('Calculate Function', () => {
13
14
  name: 'someModifier',
14
15
  };
15
16
  const orderItem = { price: 30, quantity: 1 };
16
- const computedModifier = pricingService.modifier.calculate(modifier, orderItem);
17
+ const computedModifier = pricingService.modifier.calculate(
18
+ modifier,
19
+ orderItem
20
+ );
17
21
  expect(computedModifier._computed).toMatchObject({
18
22
  amount: 10,
19
23
  description: 'someModifier ($10.00)',
@@ -30,7 +34,10 @@ describe('Calculate Function', () => {
30
34
  name: 'someModifier',
31
35
  };
32
36
  const orderItem = { price: 30, quantity: 1 };
33
- const computedModifier = pricingService.modifier.calculate(modifier, orderItem);
37
+ const computedModifier = pricingService.modifier.calculate(
38
+ modifier,
39
+ orderItem
40
+ );
34
41
  expect(computedModifier._computed).toMatchObject({
35
42
  amount: -10,
36
43
  description: 'someModifier (-$10.00)',
@@ -47,7 +54,10 @@ describe('Calculate Function', () => {
47
54
  name: 'someModifier',
48
55
  };
49
56
  const orderItem = { price: 30, quantity: 1 };
50
- const computedModifier = pricingService.modifier.calculate(modifier, orderItem);
57
+ const computedModifier = pricingService.modifier.calculate(
58
+ modifier,
59
+ orderItem
60
+ );
51
61
  expect(computedModifier._computed).toMatchObject({
52
62
  amount: -6,
53
63
  description: 'someModifier (-$6.00)',
@@ -64,10 +74,31 @@ describe('Calculate Function', () => {
64
74
  name: 'someModifier',
65
75
  };
66
76
  const orderItem = { price: 30, quantity: 1 };
67
- const computedModifier = pricingService.modifier.calculate(modifier, orderItem);
77
+ const computedModifier = pricingService.modifier.calculate(
78
+ modifier,
79
+ orderItem
80
+ );
68
81
  expect(computedModifier._computed).toMatchObject({
69
82
  amount: 6,
70
83
  description: 'someModifier ($6.00)',
71
84
  });
72
85
  });
86
+
87
+ test('calculate with a null modifier', () => {
88
+ const modifier = {
89
+ compute: null,
90
+ name: 'someModifier',
91
+ };
92
+ const orderItem = { price: 30, quantity: 1 };
93
+ const computedModifier = pricingService.modifier.calculate(
94
+ modifier,
95
+ orderItem
96
+ );
97
+ const testCompute = getComputeModField(computedModifier);
98
+ expect(testCompute).toMatchObject({
99
+ type: '',
100
+ amount: 0,
101
+ action: '',
102
+ });
103
+ });
73
104
  });
@@ -0,0 +1,166 @@
1
+ const _ = require('lodash');
2
+ const utils = require('@darkpos/utils');
3
+ const createIndirectModifierFunction = require('../../lib/modifier/createIndirectModifier');
4
+
5
+ describe('createIndirectModifier Function', () => {
6
+ test('create indirect modifier with an undefined modifier compute', () => {
7
+ const constants = {
8
+ Modifier: {
9
+ Compute: {
10
+ Types: {
11
+ PERCENTAGE: 'percentage',
12
+ FIXED: 'fixed',
13
+ },
14
+ Actions: {
15
+ SUBTRACT: 'subtract',
16
+ },
17
+ },
18
+ },
19
+ };
20
+ const actions = {
21
+ getProperty: (modifier, prop) => modifier[prop],
22
+ create: modifier => modifier,
23
+ };
24
+ // const getComputeModField = jest.fn().mockReturnValue(null);
25
+
26
+ const createIndirectModifier = createIndirectModifierFunction({
27
+ _,
28
+ utils,
29
+ constants,
30
+ actions,
31
+ });
32
+
33
+ const modifier = {
34
+ type: 'credit',
35
+ properties: {},
36
+ };
37
+ const options = {
38
+ orderTotal: 100,
39
+ itemQuantity: 2,
40
+ itemTotal: 50,
41
+ };
42
+
43
+ const result = createIndirectModifier(modifier, options);
44
+
45
+ expect(result).toEqual({
46
+ ...modifier,
47
+ direct: false,
48
+ compute: {
49
+ type: 'fixed',
50
+ amount: 0,
51
+ action: 'subtract',
52
+ },
53
+ properties: {
54
+ ignoreQuantity: false,
55
+ },
56
+ });
57
+ });
58
+ test('create indirect modifier with a null modifier compute', () => {
59
+ const constants = {
60
+ Modifier: {
61
+ Compute: {
62
+ Types: {
63
+ PERCENTAGE: 'percentage',
64
+ FIXED: 'fixed',
65
+ },
66
+ Actions: {
67
+ SUBTRACT: 'subtract',
68
+ },
69
+ },
70
+ },
71
+ };
72
+ const actions = {
73
+ getProperty: (modifier, prop) => modifier[prop],
74
+ create: modifier => modifier,
75
+ };
76
+
77
+ const createIndirectModifier = createIndirectModifierFunction({
78
+ _,
79
+ utils,
80
+ constants,
81
+ actions,
82
+ });
83
+
84
+ const modifier = {
85
+ type: 'credit',
86
+ properties: {},
87
+ compute: null,
88
+ };
89
+ const options = {
90
+ orderTotal: 100,
91
+ itemQuantity: 2,
92
+ itemTotal: 50,
93
+ };
94
+
95
+ const result = createIndirectModifier(modifier, options);
96
+
97
+ expect(result).toEqual({
98
+ ...modifier,
99
+ direct: false,
100
+ compute: {
101
+ type: 'fixed',
102
+ amount: 0,
103
+ action: 'subtract',
104
+ },
105
+ properties: {
106
+ ignoreQuantity: false,
107
+ },
108
+ });
109
+ });
110
+ test('create indirect modifier regular modifier', () => {
111
+ const constants = {
112
+ Modifier: {
113
+ Compute: {
114
+ Types: {
115
+ PERCENTAGE: 'percentage',
116
+ FIXED: 'fixed',
117
+ },
118
+ Actions: {
119
+ SUBTRACT: 'subtract',
120
+ },
121
+ },
122
+ },
123
+ };
124
+ const actions = {
125
+ getProperty: (modifier, prop) => modifier[prop],
126
+ create: modifier => modifier,
127
+ };
128
+
129
+ const createIndirectModifier = createIndirectModifierFunction({
130
+ _,
131
+ utils,
132
+ constants,
133
+ actions,
134
+ });
135
+
136
+ const modifier = {
137
+ type: 'credit',
138
+ properties: {},
139
+ compute: {
140
+ type: 'fixed',
141
+ action: 'add',
142
+ amount: 10,
143
+ },
144
+ };
145
+ const options = {
146
+ orderTotal: 100,
147
+ itemQuantity: 2,
148
+ itemTotal: 50,
149
+ };
150
+
151
+ const result = createIndirectModifier(modifier, options);
152
+
153
+ expect(result).toEqual({
154
+ ...modifier,
155
+ direct: false,
156
+ compute: {
157
+ type: 'fixed',
158
+ action: 'add',
159
+ amount: 2.5,
160
+ },
161
+ properties: {
162
+ ignoreQuantity: false,
163
+ },
164
+ });
165
+ });
166
+ });
@@ -0,0 +1,52 @@
1
+ const utils = require('@darkpos/utils');
2
+ const getFixedModifiersTotalFunction = require('../../lib/modifier/getFixedModifiersTotal');
3
+
4
+ describe('getFixedModifiersTotal Function', () => {
5
+ const getComputeModField = jest.fn();
6
+
7
+ const getFixedModifiersTotal = getFixedModifiersTotalFunction({
8
+ utils,
9
+ });
10
+
11
+ test('should return 0 if modifiers is not an array', () => {
12
+ const result = getFixedModifiersTotal(null);
13
+ expect(result).toBe(0);
14
+ });
15
+
16
+ test('should return 0 if there are no fixed modifiers', () => {
17
+ getComputeModField.mockReturnValueOnce({ type: 'percentage' });
18
+ const modifiers = [{}, {}];
19
+
20
+ const result = getFixedModifiersTotal(modifiers);
21
+ expect(result).toBe(0);
22
+ });
23
+
24
+ test('should correctly sum fixed modifiers even with a compute null', () => {
25
+ const modifiers = [
26
+ {
27
+ compute: { type: 'fixed', amount: 10 },
28
+ },
29
+ { compute: { type: 'fixed', amount: 20 } },
30
+ { compute: { type: 'fixed', amount: 30 } },
31
+ { compute: null },
32
+ ];
33
+
34
+ const result = getFixedModifiersTotal(modifiers);
35
+ expect(result).toBe(60);
36
+ });
37
+
38
+ test('should correctly handle a fixed modifier with no amount', () => {
39
+ const modifiers = [
40
+ { compute: { type: 'fixed', amount: undefined } },
41
+ { compute: { type: 'fixed', amount: 15 } },
42
+ ];
43
+
44
+ const result = getFixedModifiersTotal(modifiers);
45
+ expect(result).toBe(15);
46
+ });
47
+
48
+ test('should correctly handle an empty array of modifiers', () => {
49
+ const result = getFixedModifiersTotal([]);
50
+ expect(result).toBe(0);
51
+ });
52
+ });
@@ -0,0 +1,134 @@
1
+ const utils = require('@darkpos/utils');
2
+ const getSplittedModifiersFunction = require('../../lib/modifier/getSplittedModifiers');
3
+
4
+ describe('getSplittedModifiers Function', () => {
5
+ const getSplittedModifiers = getSplittedModifiersFunction({
6
+ utils,
7
+ });
8
+
9
+ test('should return split credit modifier with divided maxAmount', () => {
10
+ const modifiers = [
11
+ {
12
+ type: 'credit',
13
+ properties: { maxAmount: 100 },
14
+ },
15
+ ];
16
+ const totalOriginOrder = 200;
17
+ const totalSplitedOrder = 50;
18
+
19
+ const result = getSplittedModifiers(
20
+ modifiers,
21
+ totalOriginOrder,
22
+ totalSplitedOrder
23
+ );
24
+
25
+ expect(result).toEqual([
26
+ {
27
+ type: 'credit',
28
+ properties: { maxAmount: 25 }, // 100 * (50 / 200)
29
+ compute: {
30
+ type: '',
31
+ amount: 0,
32
+ action: '',
33
+ },
34
+ },
35
+ ]);
36
+ });
37
+
38
+ test('should return split fixed modifier with divided amount', () => {
39
+ const modifiers = [
40
+ {
41
+ compute: { amount: 80, type: 'fixed' },
42
+ },
43
+ ];
44
+ const totalOriginOrder = 160;
45
+ const totalSplitedOrder = 40;
46
+
47
+ const result = getSplittedModifiers(
48
+ modifiers,
49
+ totalOriginOrder,
50
+ totalSplitedOrder
51
+ );
52
+
53
+ expect(result).toEqual([
54
+ {
55
+ compute: { amount: 20, type: 'fixed' }, // 80 * (40 / 160)
56
+ },
57
+ ]);
58
+ });
59
+
60
+ test('should return unmodified modifier if type is not credit or fixed', () => {
61
+ const modifiers = [
62
+ {
63
+ type: 'non-fixed',
64
+ compute: { amount: 10 },
65
+ },
66
+ ];
67
+ const totalOriginOrder = 200;
68
+ const totalSplitedOrder = 50;
69
+
70
+ const result = getSplittedModifiers(
71
+ modifiers,
72
+ totalOriginOrder,
73
+ totalSplitedOrder
74
+ );
75
+
76
+ expect(result).toEqual(modifiers); // should be unchanged
77
+ });
78
+
79
+ test('should return 0 maxAmount if totalOriginOrder is 0 for credit modifier', () => {
80
+ const modifiers = [
81
+ {
82
+ type: 'credit',
83
+ properties: { maxAmount: 100 },
84
+ },
85
+ ];
86
+ const totalOriginOrder = 0;
87
+ const totalSplitedOrder = 50;
88
+
89
+ const result = getSplittedModifiers(
90
+ modifiers,
91
+ totalOriginOrder,
92
+ totalSplitedOrder
93
+ );
94
+
95
+ expect(result).toEqual([
96
+ {
97
+ type: 'credit',
98
+ properties: { maxAmount: 0 },
99
+ compute: {
100
+ action: '',
101
+ type: '',
102
+ amount: 0,
103
+ },
104
+ },
105
+ ]);
106
+ });
107
+
108
+ test('should return 0 amount if totalOriginOrder is 0 for fixed modifier', () => {
109
+ const modifiers = [
110
+ {
111
+ compute: { amount: 80, type: 'fixed' },
112
+ },
113
+ ];
114
+ const totalOriginOrder = 0;
115
+ const totalSplitedOrder = 40;
116
+
117
+ const result = getSplittedModifiers(
118
+ modifiers,
119
+ totalOriginOrder,
120
+ totalSplitedOrder
121
+ );
122
+
123
+ expect(result).toEqual([
124
+ {
125
+ compute: { amount: 0, type: 'fixed' }, // totalOriginOrder is 0, so amount should be 0
126
+ },
127
+ ]);
128
+ });
129
+
130
+ test('should handle empty modifiers array', () => {
131
+ const result = getSplittedModifiers([], 200, 50);
132
+ expect(result).toEqual([]); // empty input should return empty output
133
+ });
134
+ });
@@ -0,0 +1,38 @@
1
+ const isComputedOverrideFunction = require('../../lib/modifier/isComputedOverride');
2
+
3
+ describe('isComputedOverride Function', () => {
4
+ const Modifier = {
5
+ Attributes: {
6
+ OVERRIDE: 'override',
7
+ },
8
+ };
9
+
10
+ const isComputedOverride = isComputedOverrideFunction({
11
+ constants: { Modifier },
12
+ });
13
+
14
+ test('should return false if modifier is null or undefined', () => {
15
+ expect(isComputedOverride(null)).toBe(false);
16
+ expect(isComputedOverride(undefined)).toBe(false);
17
+ });
18
+
19
+ test('should return false if modifier does not have compute property', () => {
20
+ const modifier = {};
21
+ expect(isComputedOverride(modifier)).toBe(false);
22
+ });
23
+
24
+ test('should return false if compute does not have action property', () => {
25
+ const modifier = { compute: {} };
26
+ expect(isComputedOverride(modifier)).toBe(false);
27
+ });
28
+
29
+ test('should return false if compute action is not OVERRIDE', () => {
30
+ const modifier = { compute: { action: 'other_action' } };
31
+ expect(isComputedOverride(modifier)).toBe(false);
32
+ });
33
+
34
+ test('should return true if compute action is OVERRIDE', () => {
35
+ const modifier = { compute: { action: 'override' } };
36
+ expect(isComputedOverride(modifier)).toBe(true);
37
+ });
38
+ });