@darkpos/pricing 1.0.104 → 1.0.105
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 +137 -0
- package/lib/item/calculate.js +14 -16
- package/lib/item/validateModifiers.js +2 -4
- package/lib/modifier/areConditionsMet.js +18 -8
- package/lib/modifier/index.js +12 -0
- package/lib/modifier/isCustomerStatsModifier.js +7 -0
- package/lib/modifier/isTotalSalesModifier.js +11 -0
- package/lib/modifier/isTotalVisitsModifier.js +11 -0
- package/lib/modifier/isValidCustomer.js +4 -0
- package/lib/modifier/lockCustomerStatsModifiers.js +22 -0
- package/lib/modifier/unlockCustomerStatsModifiers.js +23 -0
- package/package.json +2 -2
|
@@ -1315,6 +1315,10 @@ describe('Conditions not met for the item', () => {
|
|
|
1315
1315
|
expect(calculatedOrder.total).toBe(7.5);
|
|
1316
1316
|
expect(calculatedOrder.items[0].total).toBe(7.5);
|
|
1317
1317
|
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(true);
|
|
1318
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(true);
|
|
1319
|
+
expect(calculatedOrder.items[0].modifiers[0].properties.customerId).toBe(
|
|
1320
|
+
'123456789'
|
|
1321
|
+
);
|
|
1318
1322
|
});
|
|
1319
1323
|
|
|
1320
1324
|
test('Should mark modifier as not valid if customerTotalSales !== 0', () => {
|
|
@@ -1372,6 +1376,7 @@ describe('Conditions not met for the item', () => {
|
|
|
1372
1376
|
expect(calculatedOrder.total).toBe(10);
|
|
1373
1377
|
expect(calculatedOrder.items[0].total).toBe(10);
|
|
1374
1378
|
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
|
|
1379
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(undefined);
|
|
1375
1380
|
});
|
|
1376
1381
|
|
|
1377
1382
|
test('Should mark modifier as valid if customerTotalVisits === 0', () => {
|
|
@@ -1429,6 +1434,10 @@ describe('Conditions not met for the item', () => {
|
|
|
1429
1434
|
expect(calculatedOrder.total).toBe(7.5);
|
|
1430
1435
|
expect(calculatedOrder.items[0].total).toBe(7.5);
|
|
1431
1436
|
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(true);
|
|
1437
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(true);
|
|
1438
|
+
expect(calculatedOrder.items[0].modifiers[0].properties.customerId).toBe(
|
|
1439
|
+
'123456789'
|
|
1440
|
+
);
|
|
1432
1441
|
});
|
|
1433
1442
|
|
|
1434
1443
|
test('Should mark modifier as not valid if customerTotalVisits !== 0', () => {
|
|
@@ -1486,5 +1495,133 @@ describe('Conditions not met for the item', () => {
|
|
|
1486
1495
|
expect(calculatedOrder.total).toBe(10);
|
|
1487
1496
|
expect(calculatedOrder.items[0].total).toBe(10);
|
|
1488
1497
|
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
|
|
1498
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(undefined);
|
|
1499
|
+
});
|
|
1500
|
+
|
|
1501
|
+
test('Should mark modifier as not valid if there is no customer', () => {
|
|
1502
|
+
const modifier = {
|
|
1503
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1504
|
+
name: 'first order discount',
|
|
1505
|
+
type: 'discount',
|
|
1506
|
+
tags: ['default'],
|
|
1507
|
+
direct: true,
|
|
1508
|
+
conditions: {
|
|
1509
|
+
valid: null,
|
|
1510
|
+
rules: [
|
|
1511
|
+
{
|
|
1512
|
+
key: 'customerTotalVisits',
|
|
1513
|
+
value: 0,
|
|
1514
|
+
operand: '$eq',
|
|
1515
|
+
},
|
|
1516
|
+
],
|
|
1517
|
+
},
|
|
1518
|
+
compute: {
|
|
1519
|
+
type: 'percentage',
|
|
1520
|
+
action: 'subtract',
|
|
1521
|
+
amount: 25,
|
|
1522
|
+
},
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
const item = {
|
|
1526
|
+
_id: 'abc',
|
|
1527
|
+
price: 10,
|
|
1528
|
+
quantity: 1,
|
|
1529
|
+
modifiers: [],
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1532
|
+
let order = {
|
|
1533
|
+
items: [item],
|
|
1534
|
+
};
|
|
1535
|
+
|
|
1536
|
+
order = pricingService.order.addItemModifier({
|
|
1537
|
+
order,
|
|
1538
|
+
modifier,
|
|
1539
|
+
itemIndex: 0,
|
|
1540
|
+
});
|
|
1541
|
+
|
|
1542
|
+
expect(order.items[0].modifiers.length).toBe(1);
|
|
1543
|
+
|
|
1544
|
+
const calculatedOrder = pricingService.order.calculate(order);
|
|
1545
|
+
|
|
1546
|
+
expect(calculatedOrder.total).toBe(10);
|
|
1547
|
+
expect(calculatedOrder.items[0].total).toBe(10);
|
|
1548
|
+
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
|
|
1549
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(undefined);
|
|
1550
|
+
expect(calculatedOrder.items[0].modifiers[0].properties).toBe(undefined);
|
|
1551
|
+
});
|
|
1552
|
+
|
|
1553
|
+
test('Should mark modifier as valid if there is a customer, no matter is stats is undefined', () => {
|
|
1554
|
+
const modifier = {
|
|
1555
|
+
_id: '6819114c06c23d37c1f19412',
|
|
1556
|
+
name: 'first order discount',
|
|
1557
|
+
type: 'discount',
|
|
1558
|
+
tags: ['default'],
|
|
1559
|
+
direct: true,
|
|
1560
|
+
conditions: {
|
|
1561
|
+
valid: null,
|
|
1562
|
+
rules: [
|
|
1563
|
+
{
|
|
1564
|
+
key: 'customerTotalVisits',
|
|
1565
|
+
value: 0,
|
|
1566
|
+
operand: '$eq',
|
|
1567
|
+
},
|
|
1568
|
+
],
|
|
1569
|
+
},
|
|
1570
|
+
compute: {
|
|
1571
|
+
type: 'percentage',
|
|
1572
|
+
action: 'subtract',
|
|
1573
|
+
amount: 25,
|
|
1574
|
+
},
|
|
1575
|
+
};
|
|
1576
|
+
|
|
1577
|
+
const item = {
|
|
1578
|
+
_id: 'abc',
|
|
1579
|
+
price: 10,
|
|
1580
|
+
quantity: 1,
|
|
1581
|
+
modifiers: [],
|
|
1582
|
+
};
|
|
1583
|
+
|
|
1584
|
+
let order = {
|
|
1585
|
+
items: [item],
|
|
1586
|
+
customer: {
|
|
1587
|
+
_id: 'abcd1234',
|
|
1588
|
+
},
|
|
1589
|
+
};
|
|
1590
|
+
|
|
1591
|
+
order = pricingService.order.addItemModifier({
|
|
1592
|
+
order,
|
|
1593
|
+
modifier,
|
|
1594
|
+
itemIndex: 0,
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
expect(order.items[0].modifiers.length).toBe(1);
|
|
1598
|
+
|
|
1599
|
+
let calculatedOrder = pricingService.order.calculate(order);
|
|
1600
|
+
|
|
1601
|
+
expect(calculatedOrder.total).toBe(7.5);
|
|
1602
|
+
expect(calculatedOrder.items[0].total).toBe(7.5);
|
|
1603
|
+
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(true);
|
|
1604
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(true);
|
|
1605
|
+
expect(calculatedOrder.items[0].modifiers[0].properties.customerId).toBe(
|
|
1606
|
+
'abcd1234'
|
|
1607
|
+
);
|
|
1608
|
+
|
|
1609
|
+
calculatedOrder = pricingService.order.calculate({
|
|
1610
|
+
...calculatedOrder,
|
|
1611
|
+
customer: {
|
|
1612
|
+
_id: '11122555',
|
|
1613
|
+
stats: {
|
|
1614
|
+
totalVisits: 15,
|
|
1615
|
+
},
|
|
1616
|
+
},
|
|
1617
|
+
});
|
|
1618
|
+
|
|
1619
|
+
expect(calculatedOrder.total).toBe(10);
|
|
1620
|
+
expect(calculatedOrder.items[0].total).toBe(10);
|
|
1621
|
+
expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
|
|
1622
|
+
expect(calculatedOrder.items[0].modifiers[0].locked).toBe(false);
|
|
1623
|
+
expect(calculatedOrder.items[0].modifiers[0].properties.customerId).toBe(
|
|
1624
|
+
undefined
|
|
1625
|
+
);
|
|
1489
1626
|
});
|
|
1490
1627
|
});
|
package/lib/item/calculate.js
CHANGED
|
@@ -12,18 +12,7 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
12
12
|
const isPrepay = opts.isPrepay || false;
|
|
13
13
|
const startRequestDate = opts.startRequestDate || null;
|
|
14
14
|
const endRequestDate = opts.endRequestDate || null;
|
|
15
|
-
|
|
16
|
-
let customerTotalVisits = 0;
|
|
17
|
-
let customerTotalSales = 0;
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
opts.customer &&
|
|
21
|
-
typeof opts.customer !== 'string' &&
|
|
22
|
-
opts.customer.stats
|
|
23
|
-
) {
|
|
24
|
-
customerTotalVisits = opts.customer.stats.totalVisits || 0;
|
|
25
|
-
customerTotalSales = opts.customer.stats.totalSales || 0;
|
|
26
|
-
}
|
|
15
|
+
const customer = opts.customer || null;
|
|
27
16
|
|
|
28
17
|
const lockPaymentModifiers = !!opts.lockPaymentModifiers;
|
|
29
18
|
const allItems = Array.isArray(opts.items) ? opts.items : [];
|
|
@@ -56,16 +45,21 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
56
45
|
subTotals._simple = math.mul(price, quantity);
|
|
57
46
|
|
|
58
47
|
const modifiers = [];
|
|
59
|
-
|
|
48
|
+
let { modifiers: itemModifiersPrev = [] } =
|
|
60
49
|
actions.removeModifiersByQuantity(item);
|
|
61
50
|
|
|
51
|
+
itemModifiersPrev = modifierActions.unlockCustomerStatsModifiers({
|
|
52
|
+
modifiers: itemModifiersPrev,
|
|
53
|
+
customer,
|
|
54
|
+
});
|
|
55
|
+
|
|
62
56
|
const itemModifiers = [...itemModifiersPrev].filter(
|
|
63
57
|
mod =>
|
|
64
58
|
!modifierActions.isCalculatedPaymentModifier(mod) ||
|
|
65
59
|
modifierActions.isLocked(mod)
|
|
66
60
|
);
|
|
67
61
|
|
|
68
|
-
|
|
62
|
+
let validatedModifiers = actions.validateModifiers({
|
|
69
63
|
item,
|
|
70
64
|
itemModifiers,
|
|
71
65
|
startRequestDate,
|
|
@@ -74,8 +68,12 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
|
|
|
74
68
|
paymentMethod,
|
|
75
69
|
paymentType,
|
|
76
70
|
isPrepay,
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
customer,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
validatedModifiers = modifierActions.lockCustomerStatsModifiers({
|
|
75
|
+
modifiers: validatedModifiers,
|
|
76
|
+
customer,
|
|
79
77
|
});
|
|
80
78
|
|
|
81
79
|
const modifiersToCompute = validatedModifiers.filter(
|
|
@@ -8,8 +8,7 @@ module.exports = ({ modifierActions }) =>
|
|
|
8
8
|
paymentMethod,
|
|
9
9
|
paymentType,
|
|
10
10
|
isPrepay,
|
|
11
|
-
|
|
12
|
-
customerTotalSales,
|
|
11
|
+
customer,
|
|
13
12
|
}) {
|
|
14
13
|
const validatedModifiers = [];
|
|
15
14
|
const firstValidatedModifiers = itemModifiers.map(each =>
|
|
@@ -21,8 +20,7 @@ module.exports = ({ modifierActions }) =>
|
|
|
21
20
|
paymentMethod,
|
|
22
21
|
paymentType,
|
|
23
22
|
isPrepay,
|
|
24
|
-
|
|
25
|
-
customerTotalSales,
|
|
23
|
+
customer,
|
|
26
24
|
})
|
|
27
25
|
);
|
|
28
26
|
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
module.exports = ({ actions, utils }) => {
|
|
2
|
+
const getCustomerStat = (customer, key) => {
|
|
3
|
+
if (
|
|
4
|
+
!customer ||
|
|
5
|
+
!customer.stats ||
|
|
6
|
+
typeof customer.stats[key] !== 'number'
|
|
7
|
+
) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
return customer.stats[key];
|
|
11
|
+
};
|
|
12
|
+
|
|
2
13
|
const modifierConditionPass = (
|
|
3
14
|
modifier,
|
|
4
15
|
{
|
|
@@ -9,8 +20,7 @@ module.exports = ({ actions, utils }) => {
|
|
|
9
20
|
paymentMethod,
|
|
10
21
|
paymentType,
|
|
11
22
|
isPrepay,
|
|
12
|
-
|
|
13
|
-
customerTotalSales,
|
|
23
|
+
customer,
|
|
14
24
|
}
|
|
15
25
|
) =>
|
|
16
26
|
modifier.conditions && Array.isArray(modifier.conditions.rules)
|
|
@@ -86,14 +96,16 @@ module.exports = ({ actions, utils }) => {
|
|
|
86
96
|
condition.operand
|
|
87
97
|
);
|
|
88
98
|
case 'customerTotalVisits':
|
|
99
|
+
if (!actions.isValidCustomer(customer)) return false;
|
|
89
100
|
return actions.validateNumberCondition(
|
|
90
|
-
|
|
101
|
+
getCustomerStat(customer, 'totalVisits'),
|
|
91
102
|
condition.value,
|
|
92
103
|
condition.operand
|
|
93
104
|
);
|
|
94
105
|
case 'customerTotalSales':
|
|
106
|
+
if (!actions.isValidCustomer(customer)) return false;
|
|
95
107
|
return actions.validateNumberCondition(
|
|
96
|
-
|
|
108
|
+
getCustomerStat(customer, 'totalSales'),
|
|
97
109
|
condition.value,
|
|
98
110
|
condition.operand
|
|
99
111
|
);
|
|
@@ -138,8 +150,7 @@ module.exports = ({ actions, utils }) => {
|
|
|
138
150
|
paymentMethod,
|
|
139
151
|
paymentType,
|
|
140
152
|
isPrepay,
|
|
141
|
-
|
|
142
|
-
customerTotalSales,
|
|
153
|
+
customer,
|
|
143
154
|
} = opts;
|
|
144
155
|
return (
|
|
145
156
|
modifier &&
|
|
@@ -151,8 +162,7 @@ module.exports = ({ actions, utils }) => {
|
|
|
151
162
|
paymentMethod,
|
|
152
163
|
paymentType,
|
|
153
164
|
isPrepay,
|
|
154
|
-
|
|
155
|
-
customerTotalSales,
|
|
165
|
+
customer,
|
|
156
166
|
})
|
|
157
167
|
);
|
|
158
168
|
}
|
package/lib/modifier/index.js
CHANGED
|
@@ -167,6 +167,12 @@ const isNotesOverride = require('./isNotesOverride');
|
|
|
167
167
|
const isOverrideSubtotal = require('./isOverrideSubtotal');
|
|
168
168
|
const validatePaymentCondition = require('./validatePaymentCondition');
|
|
169
169
|
const createManualModifier = require('./createManualModifier');
|
|
170
|
+
const isCustomerStatsModifier = require('./isCustomerStatsModifier');
|
|
171
|
+
const isTotalSalesModifier = require('./isTotalSalesModifier');
|
|
172
|
+
const isTotalVisitsModifier = require('./isTotalVisitsModifier');
|
|
173
|
+
const isValidCustomer = require('./isValidCustomer');
|
|
174
|
+
const lockCustomerStatsModifiers = require('./lockCustomerStatsModifiers');
|
|
175
|
+
const unlockCustomerStatsModifiers = require('./unlockCustomerStatsModifiers');
|
|
170
176
|
|
|
171
177
|
const modifierActions = (deps = {}) => {
|
|
172
178
|
const actions = {};
|
|
@@ -347,6 +353,12 @@ const modifierActions = (deps = {}) => {
|
|
|
347
353
|
isOverrideSubtotal: isOverrideSubtotal(innerDeps),
|
|
348
354
|
validatePaymentCondition: validatePaymentCondition(innerDeps),
|
|
349
355
|
createManualModifier: createManualModifier(innerDeps),
|
|
356
|
+
isCustomerStatsModifier: isCustomerStatsModifier(innerDeps),
|
|
357
|
+
isTotalSalesModifier: isTotalSalesModifier(innerDeps),
|
|
358
|
+
isTotalVisitsModifier: isTotalVisitsModifier(innerDeps),
|
|
359
|
+
isValidCustomer: isValidCustomer(innerDeps),
|
|
360
|
+
lockCustomerStatsModifiers: lockCustomerStatsModifiers(innerDeps),
|
|
361
|
+
unlockCustomerStatsModifiers: unlockCustomerStatsModifiers(innerDeps),
|
|
350
362
|
});
|
|
351
363
|
|
|
352
364
|
Object.keys(freezedActions).forEach(actionName => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = () =>
|
|
2
|
+
function isPaymentTypeModifier(modifier) {
|
|
3
|
+
return !!(
|
|
4
|
+
modifier &&
|
|
5
|
+
modifier.conditions &&
|
|
6
|
+
Array.isArray(modifier.conditions.rules) &&
|
|
7
|
+
modifier.conditions.rules.some(
|
|
8
|
+
condition => condition.key === 'customerTotalSales'
|
|
9
|
+
)
|
|
10
|
+
);
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = () =>
|
|
2
|
+
function isTotalVisitsModifier(modifier) {
|
|
3
|
+
return !!(
|
|
4
|
+
modifier &&
|
|
5
|
+
modifier.conditions &&
|
|
6
|
+
Array.isArray(modifier.conditions.rules) &&
|
|
7
|
+
modifier.conditions.rules.some(
|
|
8
|
+
condition => condition.key === 'customerTotalVisits'
|
|
9
|
+
)
|
|
10
|
+
);
|
|
11
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module.exports = ({ actions }) =>
|
|
2
|
+
function lockCustomerStatsModifiers({ modifiers, customer }) {
|
|
3
|
+
if (!Array.isArray(modifiers)) return [];
|
|
4
|
+
return modifiers.map(valMod => {
|
|
5
|
+
if (
|
|
6
|
+
actions.isValidCustomer(customer) &&
|
|
7
|
+
actions.isCustomerStatsModifier(valMod) &&
|
|
8
|
+
actions.isValid(valMod)
|
|
9
|
+
) {
|
|
10
|
+
return {
|
|
11
|
+
...valMod,
|
|
12
|
+
locked: true,
|
|
13
|
+
properties: {
|
|
14
|
+
...(valMod.properties || {}),
|
|
15
|
+
customerId: customer._id,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return valMod;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module.exports = ({ actions }) =>
|
|
2
|
+
function unlockCustomerStatsModifiers({ modifiers, customer }) {
|
|
3
|
+
if (!Array.isArray(modifiers)) return [];
|
|
4
|
+
return modifiers.map(valMod => {
|
|
5
|
+
if (
|
|
6
|
+
actions.isValidCustomer(customer) &&
|
|
7
|
+
actions.isCustomerStatsModifier(valMod) &&
|
|
8
|
+
actions.isLocked(valMod) &&
|
|
9
|
+
valMod.properties.customerId !== customer._id
|
|
10
|
+
) {
|
|
11
|
+
return {
|
|
12
|
+
...valMod,
|
|
13
|
+
locked: false,
|
|
14
|
+
properties: {
|
|
15
|
+
...(valMod.properties || {}),
|
|
16
|
+
customerId: undefined,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return valMod;
|
|
22
|
+
});
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darkpos/pricing",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.105",
|
|
4
4
|
"description": "Pricing calculator",
|
|
5
5
|
"author": "Dark POS",
|
|
6
6
|
"license": "ISC",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"supertest": "^6.2.3",
|
|
55
55
|
"supervisor": "^0.12.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "09c5c7462144195081cfc13eb82f55f4530a77aa"
|
|
58
58
|
}
|