@darkpos/pricing 1.0.103 → 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.
@@ -1259,4 +1259,369 @@ describe('Conditions not met for the item', () => {
1259
1259
 
1260
1260
  expect(result.modifiers.length).toBe(0);
1261
1261
  });
1262
+
1263
+ test('Should mark modifier as valid if customerTotalSales === 0', () => {
1264
+ const modifier = {
1265
+ _id: '6819114c06c23d37c1f19412',
1266
+ name: 'first order discount',
1267
+ type: 'discount',
1268
+ tags: ['default'],
1269
+ direct: true,
1270
+ conditions: {
1271
+ valid: null,
1272
+ rules: [
1273
+ {
1274
+ key: 'customerTotalSales',
1275
+ value: 0,
1276
+ operand: '$eq',
1277
+ },
1278
+ ],
1279
+ },
1280
+ compute: {
1281
+ type: 'percentage',
1282
+ action: 'subtract',
1283
+ amount: 25,
1284
+ },
1285
+ };
1286
+
1287
+ const item = {
1288
+ _id: 'abc',
1289
+ price: 10,
1290
+ quantity: 1,
1291
+ modifiers: [],
1292
+ };
1293
+
1294
+ let order = {
1295
+ items: [item],
1296
+ customer: {
1297
+ _id: '123456789',
1298
+ stats: {
1299
+ totalSales: 0,
1300
+ totalVisits: 0,
1301
+ },
1302
+ },
1303
+ };
1304
+
1305
+ order = pricingService.order.addItemModifier({
1306
+ order,
1307
+ modifier,
1308
+ itemIndex: 0,
1309
+ });
1310
+
1311
+ expect(order.items[0].modifiers.length).toBe(1);
1312
+
1313
+ const calculatedOrder = pricingService.order.calculate(order);
1314
+
1315
+ expect(calculatedOrder.total).toBe(7.5);
1316
+ expect(calculatedOrder.items[0].total).toBe(7.5);
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
+ );
1322
+ });
1323
+
1324
+ test('Should mark modifier as not valid if customerTotalSales !== 0', () => {
1325
+ const modifier = {
1326
+ _id: '6819114c06c23d37c1f19412',
1327
+ name: 'first order discount',
1328
+ type: 'discount',
1329
+ tags: ['default'],
1330
+ direct: true,
1331
+ conditions: {
1332
+ valid: null,
1333
+ rules: [
1334
+ {
1335
+ key: 'customerTotalSales',
1336
+ value: 0,
1337
+ operand: '$eq',
1338
+ },
1339
+ ],
1340
+ },
1341
+ compute: {
1342
+ type: 'percentage',
1343
+ action: 'subtract',
1344
+ amount: 25,
1345
+ },
1346
+ };
1347
+
1348
+ const item = {
1349
+ _id: 'abc',
1350
+ price: 10,
1351
+ quantity: 1,
1352
+ modifiers: [],
1353
+ };
1354
+
1355
+ let order = {
1356
+ items: [item],
1357
+ customer: {
1358
+ _id: '123456789',
1359
+ stats: {
1360
+ totalSales: 15,
1361
+ totalVisits: 0,
1362
+ },
1363
+ },
1364
+ };
1365
+
1366
+ order = pricingService.order.addItemModifier({
1367
+ order,
1368
+ modifier,
1369
+ itemIndex: 0,
1370
+ });
1371
+
1372
+ expect(order.items[0].modifiers.length).toBe(1);
1373
+
1374
+ const calculatedOrder = pricingService.order.calculate(order);
1375
+
1376
+ expect(calculatedOrder.total).toBe(10);
1377
+ expect(calculatedOrder.items[0].total).toBe(10);
1378
+ expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
1379
+ expect(calculatedOrder.items[0].modifiers[0].locked).toBe(undefined);
1380
+ });
1381
+
1382
+ test('Should mark modifier as valid if customerTotalVisits === 0', () => {
1383
+ const modifier = {
1384
+ _id: '6819114c06c23d37c1f19412',
1385
+ name: 'first order discount',
1386
+ type: 'discount',
1387
+ tags: ['default'],
1388
+ direct: true,
1389
+ conditions: {
1390
+ valid: null,
1391
+ rules: [
1392
+ {
1393
+ key: 'customerTotalVisits',
1394
+ value: 0,
1395
+ operand: '$eq',
1396
+ },
1397
+ ],
1398
+ },
1399
+ compute: {
1400
+ type: 'percentage',
1401
+ action: 'subtract',
1402
+ amount: 25,
1403
+ },
1404
+ };
1405
+
1406
+ const item = {
1407
+ _id: 'abc',
1408
+ price: 10,
1409
+ quantity: 1,
1410
+ modifiers: [],
1411
+ };
1412
+
1413
+ let order = {
1414
+ items: [item],
1415
+ customer: {
1416
+ _id: '123456789',
1417
+ stats: {
1418
+ totalSales: 0,
1419
+ totalVisits: 0,
1420
+ },
1421
+ },
1422
+ };
1423
+
1424
+ order = pricingService.order.addItemModifier({
1425
+ order,
1426
+ modifier,
1427
+ itemIndex: 0,
1428
+ });
1429
+
1430
+ expect(order.items[0].modifiers.length).toBe(1);
1431
+
1432
+ const calculatedOrder = pricingService.order.calculate(order);
1433
+
1434
+ expect(calculatedOrder.total).toBe(7.5);
1435
+ expect(calculatedOrder.items[0].total).toBe(7.5);
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
+ );
1441
+ });
1442
+
1443
+ test('Should mark modifier as not valid if customerTotalVisits !== 0', () => {
1444
+ const modifier = {
1445
+ _id: '6819114c06c23d37c1f19412',
1446
+ name: 'first order discount',
1447
+ type: 'discount',
1448
+ tags: ['default'],
1449
+ direct: true,
1450
+ conditions: {
1451
+ valid: null,
1452
+ rules: [
1453
+ {
1454
+ key: 'customerTotalVisits',
1455
+ value: 0,
1456
+ operand: '$eq',
1457
+ },
1458
+ ],
1459
+ },
1460
+ compute: {
1461
+ type: 'percentage',
1462
+ action: 'subtract',
1463
+ amount: 25,
1464
+ },
1465
+ };
1466
+
1467
+ const item = {
1468
+ _id: 'abc',
1469
+ price: 10,
1470
+ quantity: 1,
1471
+ modifiers: [],
1472
+ };
1473
+
1474
+ let order = {
1475
+ items: [item],
1476
+ customer: {
1477
+ _id: '123456789',
1478
+ stats: {
1479
+ totalSales: 0,
1480
+ totalVisits: 15,
1481
+ },
1482
+ },
1483
+ };
1484
+
1485
+ order = pricingService.order.addItemModifier({
1486
+ order,
1487
+ modifier,
1488
+ itemIndex: 0,
1489
+ });
1490
+
1491
+ expect(order.items[0].modifiers.length).toBe(1);
1492
+
1493
+ const calculatedOrder = pricingService.order.calculate(order);
1494
+
1495
+ expect(calculatedOrder.total).toBe(10);
1496
+ expect(calculatedOrder.items[0].total).toBe(10);
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
+ );
1626
+ });
1262
1627
  });
@@ -12,6 +12,8 @@ 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
+ const customer = opts.customer || null;
16
+
15
17
  const lockPaymentModifiers = !!opts.lockPaymentModifiers;
16
18
  const allItems = Array.isArray(opts.items) ? opts.items : [];
17
19
 
@@ -43,16 +45,21 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
43
45
  subTotals._simple = math.mul(price, quantity);
44
46
 
45
47
  const modifiers = [];
46
- const { modifiers: itemModifiersPrev = [] } =
48
+ let { modifiers: itemModifiersPrev = [] } =
47
49
  actions.removeModifiersByQuantity(item);
48
50
 
51
+ itemModifiersPrev = modifierActions.unlockCustomerStatsModifiers({
52
+ modifiers: itemModifiersPrev,
53
+ customer,
54
+ });
55
+
49
56
  const itemModifiers = [...itemModifiersPrev].filter(
50
57
  mod =>
51
58
  !modifierActions.isCalculatedPaymentModifier(mod) ||
52
59
  modifierActions.isLocked(mod)
53
60
  );
54
61
 
55
- const validatedModifiers = actions.validateModifiers({
62
+ let validatedModifiers = actions.validateModifiers({
56
63
  item,
57
64
  itemModifiers,
58
65
  startRequestDate,
@@ -61,6 +68,12 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
61
68
  paymentMethod,
62
69
  paymentType,
63
70
  isPrepay,
71
+ customer,
72
+ });
73
+
74
+ validatedModifiers = modifierActions.lockCustomerStatsModifiers({
75
+ modifiers: validatedModifiers,
76
+ customer,
64
77
  });
65
78
 
66
79
  const modifiersToCompute = validatedModifiers.filter(
@@ -8,6 +8,7 @@ module.exports = ({ modifierActions }) =>
8
8
  paymentMethod,
9
9
  paymentType,
10
10
  isPrepay,
11
+ customer,
11
12
  }) {
12
13
  const validatedModifiers = [];
13
14
  const firstValidatedModifiers = itemModifiers.map(each =>
@@ -19,6 +20,7 @@ module.exports = ({ modifierActions }) =>
19
20
  paymentMethod,
20
21
  paymentType,
21
22
  isPrepay,
23
+ customer,
22
24
  })
23
25
  );
24
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,6 +20,7 @@ module.exports = ({ actions, utils }) => {
9
20
  paymentMethod,
10
21
  paymentType,
11
22
  isPrepay,
23
+ customer,
12
24
  }
13
25
  ) =>
14
26
  modifier.conditions && Array.isArray(modifier.conditions.rules)
@@ -83,6 +95,20 @@ module.exports = ({ actions, utils }) => {
83
95
  condition.value,
84
96
  condition.operand
85
97
  );
98
+ case 'customerTotalVisits':
99
+ if (!actions.isValidCustomer(customer)) return false;
100
+ return actions.validateNumberCondition(
101
+ getCustomerStat(customer, 'totalVisits'),
102
+ condition.value,
103
+ condition.operand
104
+ );
105
+ case 'customerTotalSales':
106
+ if (!actions.isValidCustomer(customer)) return false;
107
+ return actions.validateNumberCondition(
108
+ getCustomerStat(customer, 'totalSales'),
109
+ condition.value,
110
+ condition.operand
111
+ );
86
112
  case 'modifiers':
87
113
  return actions.validateRequiredModifiers(
88
114
  item.modifiers,
@@ -124,6 +150,7 @@ module.exports = ({ actions, utils }) => {
124
150
  paymentMethod,
125
151
  paymentType,
126
152
  isPrepay,
153
+ customer,
127
154
  } = opts;
128
155
  return (
129
156
  modifier &&
@@ -135,6 +162,7 @@ module.exports = ({ actions, utils }) => {
135
162
  paymentMethod,
136
163
  paymentType,
137
164
  isPrepay,
165
+ customer,
138
166
  })
139
167
  );
140
168
  }
@@ -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,7 @@
1
+ module.exports = ({ actions }) =>
2
+ function isCustomerStatModifier(modifier) {
3
+ return (
4
+ actions.isTotalSalesModifier(modifier) ||
5
+ actions.isTotalVisitsModifier(modifier)
6
+ );
7
+ };
@@ -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,4 @@
1
+ module.exports = () =>
2
+ function isValid(customer) {
3
+ return customer && typeof customer !== 'string' && customer._id;
4
+ };
@@ -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
+ };
@@ -13,7 +13,7 @@ module.exports = ({
13
13
  function calculateorder(inputOrder, opts = {}) {
14
14
  if (!inputOrder) return inputOrder;
15
15
  const order = _.cloneDeep(inputOrder);
16
- const { items = [], orders = [] } = order;
16
+ const { items = [], orders = [], customer } = order;
17
17
  if (!items.length) {
18
18
  if (!orders.length)
19
19
  return { ...order, subTotals: {}, subTotal: 0, total: 0 };
@@ -22,10 +22,12 @@ module.exports = ({
22
22
  }
23
23
  const startRequestDate = order.start ? order.start.requestDate : null;
24
24
  const endRequestDate = order.end ? order.end.requestDate : null;
25
+
25
26
  const options = {
26
27
  ...opts,
27
28
  startRequestDate,
28
29
  endRequestDate,
30
+ customer,
29
31
  };
30
32
  const sortedOrderModifiers = modifierActions.sort(order.modifiers || []);
31
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darkpos/pricing",
3
- "version": "1.0.103",
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": "032bea629a5c32d78886daca4d2382b847b5d075"
57
+ "gitHead": "09c5c7462144195081cfc13eb82f55f4530a77aa"
58
58
  }