@darkpos/pricing 1.0.92 → 1.0.93
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/conditionsNotMet.test.js +124 -0
- package/__TEST__/order/getParentTotals.test.js +79 -0
- package/__TEST__/order/order-payment-modifier.test.js +332 -17
- package/lib/item/calculate.js +10 -1
- package/lib/item/hasPaymentMethodType.js +7 -1
- package/lib/modifier/areConditionsMet.js +3 -0
- package/lib/modifier/calculatePaymentModifier.js +2 -0
- package/lib/modifier/hasPaymentMethodType.js +21 -6
- package/lib/modifier/index.js +2 -0
- package/lib/modifier/isPaymentModifier.js +2 -1
- package/lib/modifier/isPercentage.js +1 -1
- package/lib/modifier/isPrepayModifier.js +11 -0
- package/lib/modifier/sort.js +16 -27
- package/lib/order/getTotals.js +21 -22
- package/lib/order/splitItems.js +2 -1
- package/package.json +3 -2
|
@@ -884,4 +884,128 @@ describe('Conditions not met for the item', () => {
|
|
|
884
884
|
expect(order.items[1].total).toBe(20);
|
|
885
885
|
expect(order.items[1].modifiers.length).toBe(1);
|
|
886
886
|
});
|
|
887
|
+
|
|
888
|
+
test('Payment type condition is met (payment modifier and using prepay at the same time)', () => {
|
|
889
|
+
const prePayDiscount1Usd = {
|
|
890
|
+
_id: '6819114c06c23d37c1f19412',
|
|
891
|
+
name: '1 usd pre pay disc',
|
|
892
|
+
type: 'discount',
|
|
893
|
+
tags: ['default'],
|
|
894
|
+
direct: true,
|
|
895
|
+
conditions: {
|
|
896
|
+
valid: null,
|
|
897
|
+
rules: [
|
|
898
|
+
{
|
|
899
|
+
key: 'paymentMethods',
|
|
900
|
+
value: ['cash'],
|
|
901
|
+
operand: '$in',
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
key: 'paymentTypes',
|
|
905
|
+
value: ['cash'],
|
|
906
|
+
operand: '$in',
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
key: 'payment',
|
|
910
|
+
value: 'prepay',
|
|
911
|
+
operand: '$in',
|
|
912
|
+
},
|
|
913
|
+
],
|
|
914
|
+
},
|
|
915
|
+
compute: {
|
|
916
|
+
type: 'fixed',
|
|
917
|
+
action: 'subtract',
|
|
918
|
+
amount: 1,
|
|
919
|
+
},
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
const item = {
|
|
923
|
+
_id: 'abc',
|
|
924
|
+
price: 10,
|
|
925
|
+
quantity: 1,
|
|
926
|
+
modifiers: [prePayDiscount1Usd],
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const resultedOrder = pricingService.order.calculate(
|
|
930
|
+
{
|
|
931
|
+
id: 'ord-123',
|
|
932
|
+
items: [item],
|
|
933
|
+
modifiers: [],
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
paymentMethod: 'cash',
|
|
937
|
+
paymentType: 'cash',
|
|
938
|
+
}
|
|
939
|
+
);
|
|
940
|
+
|
|
941
|
+
expect(resultedOrder.total).toBe(10);
|
|
942
|
+
expect(resultedOrder.items[0].total).toBe(10);
|
|
943
|
+
expect(resultedOrder.items[0].modifiers[0]._computed.amount).toBe(0);
|
|
944
|
+
|
|
945
|
+
const resultedOrderPrepay = pricingService.order.calculate(resultedOrder, {
|
|
946
|
+
paymentMethod: 'cash',
|
|
947
|
+
paymentType: 'cash',
|
|
948
|
+
isPrepay: true,
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
expect(resultedOrderPrepay.total).toBe(9);
|
|
952
|
+
expect(resultedOrderPrepay.items[0].total).toBe(9);
|
|
953
|
+
expect(resultedOrderPrepay.items[0].modifiers[0]._computed.amount).toBe(0);
|
|
954
|
+
expect(resultedOrderPrepay.items[0].modifiers[1]._computed.amount).toBe(-1);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
test('Payment type condition is met (using only prepay rule)', () => {
|
|
958
|
+
const prePayDiscount1Usd = {
|
|
959
|
+
_id: '6819114c06c23d37c1f19412',
|
|
960
|
+
name: '1 usd pre pay disc',
|
|
961
|
+
type: 'discount',
|
|
962
|
+
tags: ['default'],
|
|
963
|
+
direct: true,
|
|
964
|
+
conditions: {
|
|
965
|
+
valid: null,
|
|
966
|
+
rules: [
|
|
967
|
+
{
|
|
968
|
+
key: 'payment',
|
|
969
|
+
value: 'prepay',
|
|
970
|
+
operand: '$in',
|
|
971
|
+
},
|
|
972
|
+
],
|
|
973
|
+
},
|
|
974
|
+
compute: {
|
|
975
|
+
type: 'fixed',
|
|
976
|
+
action: 'subtract',
|
|
977
|
+
amount: 1,
|
|
978
|
+
},
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
const item = {
|
|
982
|
+
_id: 'abc',
|
|
983
|
+
price: 10,
|
|
984
|
+
quantity: 1,
|
|
985
|
+
modifiers: [prePayDiscount1Usd],
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
const resultedOrder = pricingService.order.calculate({
|
|
989
|
+
id: 'ord-123',
|
|
990
|
+
items: [item],
|
|
991
|
+
modifiers: [],
|
|
992
|
+
});
|
|
993
|
+
|
|
994
|
+
expect(resultedOrder.total).toBe(10);
|
|
995
|
+
expect(resultedOrder.items[0].total).toBe(10);
|
|
996
|
+
expect(resultedOrder.items[0].modifiers[0]._computed.amount).toBe(0);
|
|
997
|
+
|
|
998
|
+
const resultedOrderPrepay = pricingService.order.calculate(resultedOrder, {
|
|
999
|
+
isPrepay: true,
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
expect(resultedOrderPrepay.total).toBe(9);
|
|
1003
|
+
expect(resultedOrderPrepay.items[0].total).toBe(9);
|
|
1004
|
+
expect(resultedOrderPrepay.items[0].modifiers[0]._computed.amount).toBe(0);
|
|
1005
|
+
expect(resultedOrderPrepay.items[0].modifiers[1]._computed.amount).toBe(-1);
|
|
1006
|
+
expect(resultedOrderPrepay.items[0].modifiers[1].properties).toMatchObject({
|
|
1007
|
+
isCalculatedPaymentModifier: true,
|
|
1008
|
+
paymentId: undefined,
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
887
1011
|
});
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
describe('Get parent totals', () => {
|
|
10
|
+
it('should return zero totals if input is not an array', () => {
|
|
11
|
+
expect(pricingService.order.getTotals(null)).toEqual({
|
|
12
|
+
total: 0,
|
|
13
|
+
subTotal: 0,
|
|
14
|
+
subTotals: {},
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should calculate totals for simple sub-orders', () => {
|
|
19
|
+
const orders = [
|
|
20
|
+
{
|
|
21
|
+
parentId: '123',
|
|
22
|
+
total: 10,
|
|
23
|
+
subTotal: 8,
|
|
24
|
+
subTotals: {
|
|
25
|
+
base: 8,
|
|
26
|
+
tax: 2,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
parentId: '123',
|
|
31
|
+
total: 20,
|
|
32
|
+
subTotal: 18,
|
|
33
|
+
subTotals: {
|
|
34
|
+
base: 18,
|
|
35
|
+
tax: 2,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
expect(pricingService.order.getTotals(orders)).toEqual({
|
|
41
|
+
total: 30,
|
|
42
|
+
subTotal: 26,
|
|
43
|
+
subTotals: {
|
|
44
|
+
base: 26,
|
|
45
|
+
tax: 4,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should merge subtotals with missing keys', () => {
|
|
51
|
+
const orders = [
|
|
52
|
+
{
|
|
53
|
+
parentId: '1',
|
|
54
|
+
total: 5,
|
|
55
|
+
subTotal: 5,
|
|
56
|
+
subTotals: {
|
|
57
|
+
fee: 1,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
parentId: '1',
|
|
62
|
+
total: 10,
|
|
63
|
+
subTotal: 10,
|
|
64
|
+
subTotals: {
|
|
65
|
+
tax: 2,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
expect(pricingService.order.getTotals(orders)).toEqual({
|
|
71
|
+
total: 15,
|
|
72
|
+
subTotal: 15,
|
|
73
|
+
subTotals: {
|
|
74
|
+
fee: 1,
|
|
75
|
+
tax: 2,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -44,40 +44,28 @@ describe('Order actions', () => {
|
|
|
44
44
|
total: 10,
|
|
45
45
|
totalPaid: 0,
|
|
46
46
|
};
|
|
47
|
-
|
|
48
47
|
let cashPercentageDiscountOrder = pricingService.order.calculate(
|
|
49
48
|
{ items: [orderItem] },
|
|
50
49
|
{ paymentType: 'cash' }
|
|
51
50
|
);
|
|
52
|
-
|
|
53
51
|
expect(cashPercentageDiscountOrder).toHaveProperty('total', 9);
|
|
54
52
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
|
|
55
53
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
|
|
56
54
|
discount: -1,
|
|
57
55
|
});
|
|
58
56
|
expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(2);
|
|
59
|
-
|
|
60
57
|
expect(cashPercentageDiscountOrder.items[0].modifiers[0]._computed).toEqual(
|
|
61
58
|
expect.objectContaining({
|
|
62
59
|
amount: 0,
|
|
63
60
|
description: 'CASH 10% DISCOUNT',
|
|
64
61
|
})
|
|
65
62
|
);
|
|
66
|
-
|
|
67
63
|
expect(cashPercentageDiscountOrder.items[0].modifiers[1]._computed).toEqual(
|
|
68
64
|
expect.objectContaining({
|
|
69
65
|
amount: -1,
|
|
70
66
|
description: '$1.00 discount (-$1.00)',
|
|
71
67
|
})
|
|
72
68
|
);
|
|
73
|
-
|
|
74
|
-
expect(cashPercentageDiscountOrder.items[0].modifiers[0]._computed).toEqual(
|
|
75
|
-
expect.objectContaining({
|
|
76
|
-
amount: 0,
|
|
77
|
-
description: 'CASH 10% DISCOUNT',
|
|
78
|
-
})
|
|
79
|
-
);
|
|
80
|
-
|
|
81
69
|
cashPercentageDiscountOrder = pricingService.order.calculate(
|
|
82
70
|
{ items: [orderItem] },
|
|
83
71
|
{
|
|
@@ -88,14 +76,12 @@ describe('Order actions', () => {
|
|
|
88
76
|
}
|
|
89
77
|
);
|
|
90
78
|
cashPercentageDiscountOrder.items[0].totalPaid = 1;
|
|
91
|
-
|
|
92
79
|
expect(cashPercentageDiscountOrder).toHaveProperty('total', 9.89);
|
|
93
80
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
|
|
94
81
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
|
|
95
82
|
discount: -0.1111111111111112,
|
|
96
83
|
});
|
|
97
84
|
expect(cashPercentageDiscountOrder.items[0].modifiers).toHaveLength(2);
|
|
98
|
-
|
|
99
85
|
cashPercentageDiscountOrder = pricingService.order.calculate(
|
|
100
86
|
cashPercentageDiscountOrder,
|
|
101
87
|
{
|
|
@@ -106,7 +92,6 @@ describe('Order actions', () => {
|
|
|
106
92
|
}
|
|
107
93
|
);
|
|
108
94
|
cashPercentageDiscountOrder.items[0].totalPaid = 3;
|
|
109
|
-
|
|
110
95
|
expect(cashPercentageDiscountOrder).toHaveProperty('total', 9.67);
|
|
111
96
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
|
|
112
97
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
|
|
@@ -141,7 +126,6 @@ describe('Order actions', () => {
|
|
|
141
126
|
paymentId: '111',
|
|
142
127
|
})
|
|
143
128
|
);
|
|
144
|
-
|
|
145
129
|
cashPercentageDiscountOrder = pricingService.order.calculate(
|
|
146
130
|
cashPercentageDiscountOrder,
|
|
147
131
|
{
|
|
@@ -151,7 +135,6 @@ describe('Order actions', () => {
|
|
|
151
135
|
paymentId: '333',
|
|
152
136
|
}
|
|
153
137
|
);
|
|
154
|
-
|
|
155
138
|
expect(cashPercentageDiscountOrder).toHaveProperty('total', 9);
|
|
156
139
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotal', 10);
|
|
157
140
|
expect(cashPercentageDiscountOrder).toHaveProperty('subTotals', {
|
|
@@ -1128,4 +1111,336 @@ describe('Order actions', () => {
|
|
|
1128
1111
|
})
|
|
1129
1112
|
);
|
|
1130
1113
|
});
|
|
1114
|
+
|
|
1115
|
+
test('Applies fixed and percentage discounts with fixed modifier added first (both payment modifiers)', () => {
|
|
1116
|
+
const prePayDiscount1Usd = {
|
|
1117
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1118
|
+
name: '1 usd pre pay disc',
|
|
1119
|
+
type: 'discount',
|
|
1120
|
+
tags: ['default'],
|
|
1121
|
+
direct: true,
|
|
1122
|
+
conditions: {
|
|
1123
|
+
valid: null,
|
|
1124
|
+
rules: [
|
|
1125
|
+
{
|
|
1126
|
+
key: 'paymentTypes',
|
|
1127
|
+
value: ['cash'],
|
|
1128
|
+
operand: '$in',
|
|
1129
|
+
},
|
|
1130
|
+
],
|
|
1131
|
+
},
|
|
1132
|
+
compute: {
|
|
1133
|
+
type: 'fixed',
|
|
1134
|
+
action: 'subtract',
|
|
1135
|
+
amount: 1,
|
|
1136
|
+
},
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
const cashDiscount10Percent = {
|
|
1140
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1141
|
+
name: '10 % cash discount',
|
|
1142
|
+
type: 'discount',
|
|
1143
|
+
tags: ['default'],
|
|
1144
|
+
direct: true,
|
|
1145
|
+
conditions: {
|
|
1146
|
+
valid: null,
|
|
1147
|
+
rules: [
|
|
1148
|
+
{
|
|
1149
|
+
key: 'paymentTypes',
|
|
1150
|
+
value: ['cash'],
|
|
1151
|
+
operand: '$in',
|
|
1152
|
+
},
|
|
1153
|
+
],
|
|
1154
|
+
},
|
|
1155
|
+
compute: {
|
|
1156
|
+
type: 'percentage',
|
|
1157
|
+
action: 'subtract',
|
|
1158
|
+
amount: 10,
|
|
1159
|
+
},
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
const item = {
|
|
1163
|
+
_id: 'abc',
|
|
1164
|
+
price: 10,
|
|
1165
|
+
quantity: 1,
|
|
1166
|
+
modifiers: [prePayDiscount1Usd, cashDiscount10Percent],
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
const resultedOrderPrepay = pricingService.item.calculate(item, {
|
|
1170
|
+
paymentType: 'cash',
|
|
1171
|
+
paymentMethod: 'cash',
|
|
1172
|
+
isPrepay: true,
|
|
1173
|
+
lockPaymentModifiers: true,
|
|
1174
|
+
paymentId: 'abcd123',
|
|
1175
|
+
amountToPay: 8,
|
|
1176
|
+
});
|
|
1177
|
+
|
|
1178
|
+
expect(resultedOrderPrepay.total).toBe(8);
|
|
1179
|
+
|
|
1180
|
+
expect(resultedOrderPrepay.modifiers[0]._computed.amount).toBe(0);
|
|
1181
|
+
expect(resultedOrderPrepay.modifiers[1]._computed.amount).toBe(0);
|
|
1182
|
+
expect(resultedOrderPrepay.modifiers[2]._computed.amount).toBe(-1);
|
|
1183
|
+
expect(resultedOrderPrepay.modifiers[3]._computed.amount).toBe(-1);
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
test('Applies percentage and fixed discounts with percentage modifier added first (both paymentModifiers)', () => {
|
|
1187
|
+
const prePayDiscount1Usd = {
|
|
1188
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1189
|
+
name: '1 usd pre pay disc',
|
|
1190
|
+
type: 'discount',
|
|
1191
|
+
tags: ['default'],
|
|
1192
|
+
direct: true,
|
|
1193
|
+
conditions: {
|
|
1194
|
+
valid: null,
|
|
1195
|
+
rules: [
|
|
1196
|
+
{
|
|
1197
|
+
key: 'paymentTypes',
|
|
1198
|
+
value: ['cash'],
|
|
1199
|
+
operand: '$in',
|
|
1200
|
+
},
|
|
1201
|
+
],
|
|
1202
|
+
},
|
|
1203
|
+
compute: {
|
|
1204
|
+
type: 'fixed',
|
|
1205
|
+
action: 'subtract',
|
|
1206
|
+
amount: 1,
|
|
1207
|
+
},
|
|
1208
|
+
};
|
|
1209
|
+
|
|
1210
|
+
const cashDiscount10Percent = {
|
|
1211
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1212
|
+
name: '10 % cash discount',
|
|
1213
|
+
type: 'discount',
|
|
1214
|
+
tags: ['default'],
|
|
1215
|
+
direct: true,
|
|
1216
|
+
conditions: {
|
|
1217
|
+
valid: null,
|
|
1218
|
+
rules: [
|
|
1219
|
+
{
|
|
1220
|
+
key: 'paymentTypes',
|
|
1221
|
+
value: ['cash'],
|
|
1222
|
+
operand: '$in',
|
|
1223
|
+
},
|
|
1224
|
+
],
|
|
1225
|
+
},
|
|
1226
|
+
compute: {
|
|
1227
|
+
type: 'percentage',
|
|
1228
|
+
action: 'subtract',
|
|
1229
|
+
amount: 10,
|
|
1230
|
+
},
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
const item = {
|
|
1234
|
+
_id: 'abc',
|
|
1235
|
+
price: 10,
|
|
1236
|
+
quantity: 1,
|
|
1237
|
+
modifiers: [cashDiscount10Percent, prePayDiscount1Usd],
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
const resultedOrderPrepay = pricingService.item.calculate(item, {
|
|
1241
|
+
paymentType: 'cash',
|
|
1242
|
+
paymentMethod: 'cash',
|
|
1243
|
+
isPrepay: true,
|
|
1244
|
+
lockPaymentModifiers: true,
|
|
1245
|
+
paymentId: 'abcd123',
|
|
1246
|
+
amountToPay: 8,
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
expect(resultedOrderPrepay.total).toBe(8);
|
|
1250
|
+
|
|
1251
|
+
expect(resultedOrderPrepay.modifiers[0]._computed.amount).toBe(0);
|
|
1252
|
+
expect(resultedOrderPrepay.modifiers[1]._computed.amount).toBe(0);
|
|
1253
|
+
expect(resultedOrderPrepay.modifiers[2]._computed.amount).toBe(-1);
|
|
1254
|
+
expect(resultedOrderPrepay.modifiers[3]._computed.amount).toBe(-1);
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
test('Applies one payment discount and one regular fixed discount (percentage first)', () => {
|
|
1258
|
+
const prePayDiscount1Usd = {
|
|
1259
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1260
|
+
name: '1 usd pre pay disc',
|
|
1261
|
+
type: 'discount',
|
|
1262
|
+
tags: ['default'],
|
|
1263
|
+
direct: true,
|
|
1264
|
+
conditions: {
|
|
1265
|
+
valid: null,
|
|
1266
|
+
rules: [],
|
|
1267
|
+
},
|
|
1268
|
+
compute: {
|
|
1269
|
+
type: 'fixed',
|
|
1270
|
+
action: 'subtract',
|
|
1271
|
+
amount: 1,
|
|
1272
|
+
},
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
const cashDiscount10Percent = {
|
|
1276
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1277
|
+
name: '10 % cash discount',
|
|
1278
|
+
type: 'discount',
|
|
1279
|
+
tags: ['default'],
|
|
1280
|
+
direct: true,
|
|
1281
|
+
conditions: {
|
|
1282
|
+
valid: null,
|
|
1283
|
+
rules: [
|
|
1284
|
+
{
|
|
1285
|
+
key: 'paymentTypes',
|
|
1286
|
+
value: ['cash'],
|
|
1287
|
+
operand: '$in',
|
|
1288
|
+
},
|
|
1289
|
+
],
|
|
1290
|
+
},
|
|
1291
|
+
compute: {
|
|
1292
|
+
type: 'percentage',
|
|
1293
|
+
action: 'subtract',
|
|
1294
|
+
amount: 10,
|
|
1295
|
+
},
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1298
|
+
const item = {
|
|
1299
|
+
_id: 'abc',
|
|
1300
|
+
price: 10,
|
|
1301
|
+
quantity: 1,
|
|
1302
|
+
modifiers: [cashDiscount10Percent, prePayDiscount1Usd],
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
const resultedOrderPrepay = pricingService.item.calculate(item, {
|
|
1306
|
+
paymentType: 'cash',
|
|
1307
|
+
paymentMethod: 'cash',
|
|
1308
|
+
isPrepay: true,
|
|
1309
|
+
lockPaymentModifiers: true,
|
|
1310
|
+
paymentId: 'abcd123',
|
|
1311
|
+
amountToPay: 8,
|
|
1312
|
+
});
|
|
1313
|
+
|
|
1314
|
+
expect(resultedOrderPrepay.total).toBe(8);
|
|
1315
|
+
|
|
1316
|
+
expect(resultedOrderPrepay.modifiers[0]._computed.amount).toBe(0);
|
|
1317
|
+
expect(resultedOrderPrepay.modifiers[1]._computed.amount).toBe(-1);
|
|
1318
|
+
expect(resultedOrderPrepay.modifiers[2]._computed.amount).toBe(-1);
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
test('Applies one payment discount and one regular percentage discount (fixed first)', () => {
|
|
1322
|
+
const prePayDiscount1Usd = {
|
|
1323
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1324
|
+
name: '1 usd pre pay disc',
|
|
1325
|
+
type: 'discount',
|
|
1326
|
+
tags: ['default'],
|
|
1327
|
+
direct: true,
|
|
1328
|
+
conditions: {
|
|
1329
|
+
valid: null,
|
|
1330
|
+
rules: [],
|
|
1331
|
+
},
|
|
1332
|
+
compute: {
|
|
1333
|
+
type: 'fixed',
|
|
1334
|
+
action: 'subtract',
|
|
1335
|
+
amount: 1,
|
|
1336
|
+
},
|
|
1337
|
+
};
|
|
1338
|
+
|
|
1339
|
+
const cashDiscount10Percent = {
|
|
1340
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1341
|
+
name: '10 % cash discount',
|
|
1342
|
+
type: 'discount',
|
|
1343
|
+
tags: ['default'],
|
|
1344
|
+
direct: true,
|
|
1345
|
+
conditions: {
|
|
1346
|
+
valid: null,
|
|
1347
|
+
rules: [
|
|
1348
|
+
{
|
|
1349
|
+
key: 'paymentTypes',
|
|
1350
|
+
value: ['cash'],
|
|
1351
|
+
operand: '$in',
|
|
1352
|
+
},
|
|
1353
|
+
],
|
|
1354
|
+
},
|
|
1355
|
+
compute: {
|
|
1356
|
+
type: 'percentage',
|
|
1357
|
+
action: 'subtract',
|
|
1358
|
+
amount: 10,
|
|
1359
|
+
},
|
|
1360
|
+
};
|
|
1361
|
+
|
|
1362
|
+
const item = {
|
|
1363
|
+
_id: 'abc',
|
|
1364
|
+
price: 10,
|
|
1365
|
+
quantity: 1,
|
|
1366
|
+
modifiers: [prePayDiscount1Usd, cashDiscount10Percent],
|
|
1367
|
+
};
|
|
1368
|
+
|
|
1369
|
+
const resultedOrderPrepay = pricingService.item.calculate(item, {
|
|
1370
|
+
paymentType: 'cash',
|
|
1371
|
+
paymentMethod: 'cash',
|
|
1372
|
+
isPrepay: true,
|
|
1373
|
+
lockPaymentModifiers: true,
|
|
1374
|
+
paymentId: 'abcd123',
|
|
1375
|
+
amountToPay: 8,
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
expect(resultedOrderPrepay.total).toBe(8);
|
|
1379
|
+
|
|
1380
|
+
expect(resultedOrderPrepay.modifiers[0]._computed.amount).toBe(0);
|
|
1381
|
+
expect(resultedOrderPrepay.modifiers[1]._computed.amount).toBe(-1);
|
|
1382
|
+
expect(resultedOrderPrepay.modifiers[2]._computed.amount).toBe(-1);
|
|
1383
|
+
});
|
|
1384
|
+
|
|
1385
|
+
test('Applies one payment discount and one regular percentage discount (fixed first) withouth sending amountToPay', () => {
|
|
1386
|
+
const prePayDiscount1Usd = {
|
|
1387
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1388
|
+
name: '1 usd pre pay disc',
|
|
1389
|
+
type: 'discount',
|
|
1390
|
+
tags: ['default'],
|
|
1391
|
+
direct: true,
|
|
1392
|
+
conditions: {
|
|
1393
|
+
valid: null,
|
|
1394
|
+
rules: [],
|
|
1395
|
+
},
|
|
1396
|
+
compute: {
|
|
1397
|
+
type: 'fixed',
|
|
1398
|
+
action: 'subtract',
|
|
1399
|
+
amount: 1,
|
|
1400
|
+
},
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
const cashDiscount10Percent = {
|
|
1404
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1405
|
+
name: '10 % cash discount',
|
|
1406
|
+
type: 'discount',
|
|
1407
|
+
tags: ['default'],
|
|
1408
|
+
direct: true,
|
|
1409
|
+
conditions: {
|
|
1410
|
+
valid: null,
|
|
1411
|
+
rules: [
|
|
1412
|
+
{
|
|
1413
|
+
key: 'paymentTypes',
|
|
1414
|
+
value: ['cash'],
|
|
1415
|
+
operand: '$in',
|
|
1416
|
+
},
|
|
1417
|
+
],
|
|
1418
|
+
},
|
|
1419
|
+
compute: {
|
|
1420
|
+
type: 'percentage',
|
|
1421
|
+
action: 'subtract',
|
|
1422
|
+
amount: 10,
|
|
1423
|
+
},
|
|
1424
|
+
};
|
|
1425
|
+
|
|
1426
|
+
const item = {
|
|
1427
|
+
_id: 'abc',
|
|
1428
|
+
price: 10,
|
|
1429
|
+
quantity: 1,
|
|
1430
|
+
modifiers: [prePayDiscount1Usd, cashDiscount10Percent],
|
|
1431
|
+
};
|
|
1432
|
+
|
|
1433
|
+
const resultedOrderPrepay = pricingService.item.calculate(item, {
|
|
1434
|
+
paymentType: 'cash',
|
|
1435
|
+
paymentMethod: 'cash',
|
|
1436
|
+
isPrepay: true,
|
|
1437
|
+
paymentId: 'abcd123',
|
|
1438
|
+
});
|
|
1439
|
+
|
|
1440
|
+
expect(resultedOrderPrepay.total).toBe(8);
|
|
1441
|
+
|
|
1442
|
+
expect(resultedOrderPrepay.modifiers[0]._computed.amount).toBe(0);
|
|
1443
|
+
expect(resultedOrderPrepay.modifiers[1]._computed.amount).toBe(-1);
|
|
1444
|
+
expect(resultedOrderPrepay.modifiers[2]._computed.amount).toBe(-1);
|
|
1445
|
+
});
|
|
1131
1446
|
});
|
package/lib/item/calculate.js
CHANGED
|
@@ -9,6 +9,7 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
9
9
|
typeof opts.amountToPay === 'number' ? opts.amountToPay : 0;
|
|
10
10
|
const paymentMethod = opts.paymentMethod || null;
|
|
11
11
|
const paymentType = opts.paymentType || null;
|
|
12
|
+
const isPrepay = opts.isPrepay || false;
|
|
12
13
|
const startRequestDate = opts.startRequestDate || null;
|
|
13
14
|
const endRequestDate = opts.endRequestDate || null;
|
|
14
15
|
const lockPaymentModifiers = !!opts.lockPaymentModifiers;
|
|
@@ -70,6 +71,7 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
70
71
|
paymentModifier: modifier,
|
|
71
72
|
paymentMethod,
|
|
72
73
|
paymentType,
|
|
74
|
+
isPrepay,
|
|
73
75
|
})
|
|
74
76
|
)
|
|
75
77
|
.filter(paymentModifier => {
|
|
@@ -116,6 +118,8 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
116
118
|
let prvPrice = 0;
|
|
117
119
|
let prvSort;
|
|
118
120
|
|
|
121
|
+
let accumulatedAmount = 0;
|
|
122
|
+
|
|
119
123
|
for (const modifier of sortedModifiers) {
|
|
120
124
|
const included = modifierActions.isIncluded(modifier);
|
|
121
125
|
const direct = modifierActions.isDirect(modifier);
|
|
@@ -132,7 +136,10 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
132
136
|
if (modifierActions.isPaymentModifier(modifier)) {
|
|
133
137
|
_modifier = modifierActions.calculatePaymentModifier({
|
|
134
138
|
paymentModifier: modifier,
|
|
135
|
-
amountToPay
|
|
139
|
+
amountToPay:
|
|
140
|
+
accumulatedAmount < 0 && amountToPay > 0
|
|
141
|
+
? math.add(amountToPay, math.abs(accumulatedAmount))
|
|
142
|
+
: amountToPay,
|
|
136
143
|
itemBalance:
|
|
137
144
|
typeof item.totalPaid === 'number' && item.totalPaid > 0
|
|
138
145
|
? actions.getItemsBalance({ items: [item] })
|
|
@@ -140,6 +147,7 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
140
147
|
paymentMethod,
|
|
141
148
|
paymentType,
|
|
142
149
|
paymentId,
|
|
150
|
+
isPrepay,
|
|
143
151
|
});
|
|
144
152
|
}
|
|
145
153
|
|
|
@@ -168,6 +176,7 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
168
176
|
computedAmount = _computed.amount;
|
|
169
177
|
|
|
170
178
|
prvPrice = math.add(prvPrice, math.div(_computed.amount, quantity));
|
|
179
|
+
accumulatedAmount = math.add(accumulatedAmount, _computed.amount);
|
|
171
180
|
prvSort = sort;
|
|
172
181
|
|
|
173
182
|
({ subTotals, total } = actions.getTotals({
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module.exports = ({ modifierActions }) =>
|
|
2
|
-
function hasPaymentMethodType({
|
|
2
|
+
function hasPaymentMethodType({
|
|
3
|
+
item,
|
|
4
|
+
paymentMethod,
|
|
5
|
+
paymentType,
|
|
6
|
+
isPrepay,
|
|
7
|
+
}) {
|
|
3
8
|
if (
|
|
4
9
|
!item ||
|
|
5
10
|
!Array.isArray(item.modifiers) ||
|
|
@@ -12,6 +17,7 @@ module.exports = ({ modifierActions }) =>
|
|
|
12
17
|
paymentModifier: modifier,
|
|
13
18
|
paymentMethod,
|
|
14
19
|
paymentType,
|
|
20
|
+
isPrepay,
|
|
15
21
|
})
|
|
16
22
|
);
|
|
17
23
|
};
|
|
@@ -8,12 +8,14 @@ module.exports = ({ actions, utils }) => {
|
|
|
8
8
|
paymentMethod,
|
|
9
9
|
paymentType,
|
|
10
10
|
paymentId,
|
|
11
|
+
isPrepay,
|
|
11
12
|
}) {
|
|
12
13
|
if (
|
|
13
14
|
!actions.hasPaymentMethodType({
|
|
14
15
|
paymentModifier: paymentModifierParam,
|
|
15
16
|
paymentMethod,
|
|
16
17
|
paymentType,
|
|
18
|
+
isPrepay,
|
|
17
19
|
})
|
|
18
20
|
)
|
|
19
21
|
return undefined;
|
|
@@ -3,12 +3,27 @@ module.exports = ({ actions }) =>
|
|
|
3
3
|
paymentModifier,
|
|
4
4
|
paymentMethod,
|
|
5
5
|
paymentType,
|
|
6
|
+
isPrepay,
|
|
6
7
|
}) {
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
if (!actions.isPaymentModifier(paymentModifier)) return false;
|
|
9
|
+
|
|
10
|
+
if (actions.isPrepayModifier(paymentModifier) && !isPrepay) return false;
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
actions.isPaymentTypeModifier(paymentModifier) &&
|
|
14
|
+
!paymentModifier.conditions.rules.some(rule =>
|
|
15
|
+
rule.value.includes(paymentType)
|
|
12
16
|
)
|
|
13
|
-
)
|
|
17
|
+
)
|
|
18
|
+
return false;
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
actions.isPaymentMethodModifier(paymentModifier) &&
|
|
22
|
+
!paymentModifier.conditions.rules.some(rule =>
|
|
23
|
+
rule.value.includes(paymentMethod)
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
return false;
|
|
27
|
+
|
|
28
|
+
return true;
|
|
14
29
|
};
|
package/lib/modifier/index.js
CHANGED
|
@@ -163,6 +163,7 @@ const isOrderUseValid = require('./isOrderUseValid');
|
|
|
163
163
|
const getMaxItemQuantity = require('./getMaxItemQuantity');
|
|
164
164
|
const createDescription = require('./createDescription');
|
|
165
165
|
const patchModifier = require('./patchModifier');
|
|
166
|
+
const isPrepayModifier = require('./isPrepayModifier');
|
|
166
167
|
|
|
167
168
|
const modifierActions = (deps = {}) => {
|
|
168
169
|
const actions = {};
|
|
@@ -339,6 +340,7 @@ const modifierActions = (deps = {}) => {
|
|
|
339
340
|
getCreditModifiersTotalEntities: getCreditModifiersTotalEntities(innerDeps),
|
|
340
341
|
createDescription: createDescription(innerDeps),
|
|
341
342
|
patchModifier: patchModifier(innerDeps),
|
|
343
|
+
isPrepayModifier: isPrepayModifier(innerDeps),
|
|
342
344
|
});
|
|
343
345
|
|
|
344
346
|
Object.keys(freezedActions).forEach(actionName => {
|
|
@@ -2,6 +2,7 @@ module.exports = ({ actions }) =>
|
|
|
2
2
|
function isPaymentModifier(modifier) {
|
|
3
3
|
return (
|
|
4
4
|
actions.isPaymentTypeModifier(modifier) ||
|
|
5
|
-
actions.isPaymentMethodModifier(modifier)
|
|
5
|
+
actions.isPaymentMethodModifier(modifier) ||
|
|
6
|
+
actions.isPrepayModifier(modifier)
|
|
6
7
|
);
|
|
7
8
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = () =>
|
|
2
|
+
function isPrepayModifier(modifier) {
|
|
3
|
+
return !!(
|
|
4
|
+
modifier &&
|
|
5
|
+
modifier.conditions &&
|
|
6
|
+
Array.isArray(modifier.conditions.rules) &&
|
|
7
|
+
modifier.conditions.rules.some(
|
|
8
|
+
condition => condition.key === 'payment' && condition.value === 'prepay'
|
|
9
|
+
)
|
|
10
|
+
);
|
|
11
|
+
};
|
package/lib/modifier/sort.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
module.exports = ({ actions }) => {
|
|
3
3
|
function compareValues(key, order = 'asc') {
|
|
4
4
|
return function innerSort(a, b) {
|
|
5
|
-
// property doesn't exist on either object
|
|
6
5
|
const aVal = actions.getProperty(a, key);
|
|
7
6
|
const bVal = actions.getProperty(b, key);
|
|
8
7
|
|
|
@@ -13,38 +12,27 @@ module.exports = ({ actions }) => {
|
|
|
13
12
|
const bIsCalculatedPaymentModifier =
|
|
14
13
|
actions.isCalculatedPaymentModifier(b);
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
if (bIsCalculatedPaymentModifier && aIsPaymentModifier && bVal === null) {
|
|
20
|
-
return -1;
|
|
21
|
-
}
|
|
15
|
+
const aIsPercentageNoSort = actions.isPercentage(a) && aVal == null;
|
|
16
|
+
const bIsPercentageNoSort = actions.isPercentage(b) && bVal == null;
|
|
22
17
|
|
|
23
|
-
if (
|
|
24
|
-
(aIsPaymentModifier || aIsCalculatedPaymentModifier) &&
|
|
25
|
-
aVal === null
|
|
26
|
-
) {
|
|
18
|
+
if (bIsPaymentModifier && aIsPercentageNoSort && !bIsPercentageNoSort)
|
|
27
19
|
return 1;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
(bIsPaymentModifier || bIsCalculatedPaymentModifier) &&
|
|
32
|
-
bVal === null
|
|
33
|
-
) {
|
|
34
|
-
return 1;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (aVal == null && bVal === null) {
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
20
|
+
if (aIsPaymentModifier && !aIsPercentageNoSort && bIsPercentageNoSort)
|
|
21
|
+
return -1;
|
|
40
22
|
|
|
41
|
-
if (aVal
|
|
23
|
+
if (aIsCalculatedPaymentModifier && bIsPaymentModifier && aVal === null)
|
|
24
|
+
return -1;
|
|
25
|
+
if (bIsCalculatedPaymentModifier && aIsPaymentModifier && bVal === null)
|
|
42
26
|
return -1;
|
|
43
|
-
}
|
|
44
27
|
|
|
45
|
-
if (
|
|
28
|
+
if ((aIsPaymentModifier || aIsCalculatedPaymentModifier) && aVal === null)
|
|
29
|
+
return 1;
|
|
30
|
+
if ((bIsPaymentModifier || bIsCalculatedPaymentModifier) && bVal === null)
|
|
46
31
|
return 1;
|
|
47
|
-
|
|
32
|
+
|
|
33
|
+
if (aVal == null && bVal === null) return 0;
|
|
34
|
+
if (aVal == null) return -1;
|
|
35
|
+
if (bVal === null) return 1;
|
|
48
36
|
|
|
49
37
|
const varA = typeof aVal === 'string' ? aVal.toUpperCase() : aVal;
|
|
50
38
|
const varB = typeof bVal === 'string' ? bVal.toUpperCase() : bVal;
|
|
@@ -52,6 +40,7 @@ module.exports = ({ actions }) => {
|
|
|
52
40
|
let comparison = 0;
|
|
53
41
|
if (varA > varB) comparison = 1;
|
|
54
42
|
else if (varA < varB) comparison = -1;
|
|
43
|
+
|
|
55
44
|
return order === 'desc' ? comparison * -1 : comparison;
|
|
56
45
|
};
|
|
57
46
|
}
|
package/lib/order/getTotals.js
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
module.exports = ({ utils }) => {
|
|
2
2
|
const { math } = utils;
|
|
3
|
+
|
|
3
4
|
return function getTotals(orders) {
|
|
4
|
-
if (!Array.isArray(orders))
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
acc.subTotals[key] || 0,
|
|
17
|
-
orderSubTotals[key]
|
|
18
|
-
);
|
|
5
|
+
if (!Array.isArray(orders)) {
|
|
6
|
+
return { total: 0, subTotal: 0, subTotals: {} };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return orders.reduce(
|
|
10
|
+
(acc, order) => {
|
|
11
|
+
const { subTotals: orderSubTotals, subTotal = 0, total = 0 } = order;
|
|
12
|
+
|
|
13
|
+
if (orderSubTotals) {
|
|
14
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
15
|
+
for (const [key, value] of Object.entries(orderSubTotals)) {
|
|
16
|
+
acc.subTotals[key] = math.add(acc.subTotals[key] || 0, value);
|
|
19
17
|
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
acc.total = math.add(acc.total, total);
|
|
21
|
+
acc.subTotal = math.add(acc.subTotal, subTotal);
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
{ total: 0, subTotals: {} }
|
|
27
|
-
);
|
|
23
|
+
return acc;
|
|
24
|
+
},
|
|
25
|
+
{ total: 0, subTotal: 0, subTotals: {} }
|
|
26
|
+
);
|
|
28
27
|
};
|
|
29
28
|
};
|
package/lib/order/splitItems.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module.exports = ({ actions, modifierActions, itemActions }) =>
|
|
1
|
+
module.exports = ({ actions, modifierActions, itemActions, utils }) =>
|
|
2
2
|
function splitItems({ order }) {
|
|
3
3
|
if (!order || !order.items) return order;
|
|
4
4
|
|
|
@@ -32,6 +32,7 @@ module.exports = ({ actions, modifierActions, itemActions }) =>
|
|
|
32
32
|
...item,
|
|
33
33
|
quantity: splitQty,
|
|
34
34
|
modifiers: [],
|
|
35
|
+
_id: utils.helpers.getObjectID(),
|
|
35
36
|
});
|
|
36
37
|
remaining -= splitQty;
|
|
37
38
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darkpos/pricing",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.93",
|
|
4
4
|
"description": "Pricing calculator",
|
|
5
5
|
"author": "Dark POS",
|
|
6
6
|
"license": "ISC",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"test:modifier": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/modifier.test.js",
|
|
28
28
|
"test:paymentModifiers": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/order-payment-modifier.test.js",
|
|
29
29
|
"test:addItem": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/addItem.test.js",
|
|
30
|
+
"test:getParentTotals": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/getParentTotals.test.js",
|
|
30
31
|
"lint": "eslint --quiet lib/"
|
|
31
32
|
},
|
|
32
33
|
"publishConfig": {
|
|
@@ -51,5 +52,5 @@
|
|
|
51
52
|
"supertest": "^6.2.3",
|
|
52
53
|
"supervisor": "^0.12.0"
|
|
53
54
|
},
|
|
54
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "fb466ad4fdad14d593a1ee3dc2814f683b10ec24"
|
|
55
56
|
}
|