@darkpos/pricing 1.0.102 → 1.0.104

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.
@@ -676,7 +676,7 @@ describe('Modifier actions', () => {
676
676
  properties: {
677
677
  isManual: true,
678
678
  },
679
- _id: 'ead6eb247a93bca8f802f9b2',
679
+ _id: '5d97805a91c31603f8fc6ab0',
680
680
  }),
681
681
  expect.objectContaining({
682
682
  name: 'Blue Label',
@@ -685,7 +685,7 @@ describe('Modifier actions', () => {
685
685
  properties: {
686
686
  isManual: true,
687
687
  },
688
- _id: '4e23edf8fa734884f4618003',
688
+ _id: '49327d26c324cb709456a279',
689
689
  }),
690
690
  ])
691
691
  );
@@ -739,21 +739,21 @@ describe('Modifier actions', () => {
739
739
  expect(result).toStrictEqual([
740
740
  {
741
741
  name: 'Red Tag',
742
- _id: 'ead6eb247a93bca8f802f9b2',
742
+ _id: '5d97805a91c31603f8fc6ab0',
743
743
  direct: true,
744
744
  group: 'colorGroup1',
745
745
  properties: { isManual: true, spreadFrom: 'abc123' },
746
746
  },
747
747
  {
748
748
  name: 'White Shirt',
749
- _id: '4e23edf8fa734884f4618003',
749
+ _id: '3b115e8ff1d00d9ae4ea3601',
750
750
  direct: true,
751
751
  group: 'colorGroup1',
752
752
  properties: { isManual: true, spreadFrom: 'abc123' },
753
753
  },
754
754
  {
755
755
  name: 'Blue Label',
756
- _id: '94b02ee7ba009b09a913a786',
756
+ _id: '49327d26c324cb709456a279',
757
757
  direct: true,
758
758
  group: 'colorGroup1',
759
759
  properties: { isManual: true, spreadFrom: 'abc123' },
@@ -815,21 +815,21 @@ describe('Modifier actions', () => {
815
815
  expect(result).toStrictEqual([
816
816
  {
817
817
  name: 'Red Tag',
818
- _id: 'ead6eb247a93bca8f802f9b2',
818
+ _id: '5d97805a91c31603f8fc6ab0',
819
819
  direct: true,
820
820
  group: 'colorGroup1',
821
821
  properties: { isManual: true, spreadFrom: 'abc123' },
822
822
  },
823
823
  {
824
824
  name: 'White Shirt',
825
- _id: '4e23edf8fa734884f4618003',
825
+ _id: '3b115e8ff1d00d9ae4ea3601',
826
826
  direct: true,
827
827
  group: 'colorGroup1',
828
828
  properties: { isManual: true, spreadFrom: 'abc123' },
829
829
  },
830
830
  {
831
831
  name: 'Blue Label',
832
- _id: '94b02ee7ba009b09a913a786',
832
+ _id: '49327d26c324cb709456a279',
833
833
  direct: true,
834
834
  group: 'colorGroup1',
835
835
  properties: { isManual: true, spreadFrom: 'abc123' },
@@ -1259,4 +1259,232 @@ 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
+ });
1319
+
1320
+ test('Should mark modifier as not valid if customerTotalSales !== 0', () => {
1321
+ const modifier = {
1322
+ _id: '6819114c06c23d37c1f19412',
1323
+ name: 'first order discount',
1324
+ type: 'discount',
1325
+ tags: ['default'],
1326
+ direct: true,
1327
+ conditions: {
1328
+ valid: null,
1329
+ rules: [
1330
+ {
1331
+ key: 'customerTotalSales',
1332
+ value: 0,
1333
+ operand: '$eq',
1334
+ },
1335
+ ],
1336
+ },
1337
+ compute: {
1338
+ type: 'percentage',
1339
+ action: 'subtract',
1340
+ amount: 25,
1341
+ },
1342
+ };
1343
+
1344
+ const item = {
1345
+ _id: 'abc',
1346
+ price: 10,
1347
+ quantity: 1,
1348
+ modifiers: [],
1349
+ };
1350
+
1351
+ let order = {
1352
+ items: [item],
1353
+ customer: {
1354
+ _id: '123456789',
1355
+ stats: {
1356
+ totalSales: 15,
1357
+ totalVisits: 0,
1358
+ },
1359
+ },
1360
+ };
1361
+
1362
+ order = pricingService.order.addItemModifier({
1363
+ order,
1364
+ modifier,
1365
+ itemIndex: 0,
1366
+ });
1367
+
1368
+ expect(order.items[0].modifiers.length).toBe(1);
1369
+
1370
+ const calculatedOrder = pricingService.order.calculate(order);
1371
+
1372
+ expect(calculatedOrder.total).toBe(10);
1373
+ expect(calculatedOrder.items[0].total).toBe(10);
1374
+ expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
1375
+ });
1376
+
1377
+ test('Should mark modifier as valid if customerTotalVisits === 0', () => {
1378
+ const modifier = {
1379
+ _id: '6819114c06c23d37c1f19412',
1380
+ name: 'first order discount',
1381
+ type: 'discount',
1382
+ tags: ['default'],
1383
+ direct: true,
1384
+ conditions: {
1385
+ valid: null,
1386
+ rules: [
1387
+ {
1388
+ key: 'customerTotalVisits',
1389
+ value: 0,
1390
+ operand: '$eq',
1391
+ },
1392
+ ],
1393
+ },
1394
+ compute: {
1395
+ type: 'percentage',
1396
+ action: 'subtract',
1397
+ amount: 25,
1398
+ },
1399
+ };
1400
+
1401
+ const item = {
1402
+ _id: 'abc',
1403
+ price: 10,
1404
+ quantity: 1,
1405
+ modifiers: [],
1406
+ };
1407
+
1408
+ let order = {
1409
+ items: [item],
1410
+ customer: {
1411
+ _id: '123456789',
1412
+ stats: {
1413
+ totalSales: 0,
1414
+ totalVisits: 0,
1415
+ },
1416
+ },
1417
+ };
1418
+
1419
+ order = pricingService.order.addItemModifier({
1420
+ order,
1421
+ modifier,
1422
+ itemIndex: 0,
1423
+ });
1424
+
1425
+ expect(order.items[0].modifiers.length).toBe(1);
1426
+
1427
+ const calculatedOrder = pricingService.order.calculate(order);
1428
+
1429
+ expect(calculatedOrder.total).toBe(7.5);
1430
+ expect(calculatedOrder.items[0].total).toBe(7.5);
1431
+ expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(true);
1432
+ });
1433
+
1434
+ test('Should mark modifier as not valid if customerTotalVisits !== 0', () => {
1435
+ const modifier = {
1436
+ _id: '6819114c06c23d37c1f19412',
1437
+ name: 'first order discount',
1438
+ type: 'discount',
1439
+ tags: ['default'],
1440
+ direct: true,
1441
+ conditions: {
1442
+ valid: null,
1443
+ rules: [
1444
+ {
1445
+ key: 'customerTotalVisits',
1446
+ value: 0,
1447
+ operand: '$eq',
1448
+ },
1449
+ ],
1450
+ },
1451
+ compute: {
1452
+ type: 'percentage',
1453
+ action: 'subtract',
1454
+ amount: 25,
1455
+ },
1456
+ };
1457
+
1458
+ const item = {
1459
+ _id: 'abc',
1460
+ price: 10,
1461
+ quantity: 1,
1462
+ modifiers: [],
1463
+ };
1464
+
1465
+ let order = {
1466
+ items: [item],
1467
+ customer: {
1468
+ _id: '123456789',
1469
+ stats: {
1470
+ totalSales: 0,
1471
+ totalVisits: 15,
1472
+ },
1473
+ },
1474
+ };
1475
+
1476
+ order = pricingService.order.addItemModifier({
1477
+ order,
1478
+ modifier,
1479
+ itemIndex: 0,
1480
+ });
1481
+
1482
+ expect(order.items[0].modifiers.length).toBe(1);
1483
+
1484
+ const calculatedOrder = pricingService.order.calculate(order);
1485
+
1486
+ expect(calculatedOrder.total).toBe(10);
1487
+ expect(calculatedOrder.items[0].total).toBe(10);
1488
+ expect(calculatedOrder.items[0].modifiers[0].conditions.valid).toBe(false);
1489
+ });
1262
1490
  });
@@ -12,6 +12,19 @@ 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
+ }
27
+
15
28
  const lockPaymentModifiers = !!opts.lockPaymentModifiers;
16
29
  const allItems = Array.isArray(opts.items) ? opts.items : [];
17
30
 
@@ -61,6 +74,8 @@ module.exports = ({ _, utils, actions, modifierActions }) => {
61
74
  paymentMethod,
62
75
  paymentType,
63
76
  isPrepay,
77
+ customerTotalVisits,
78
+ customerTotalSales,
64
79
  });
65
80
 
66
81
  const modifiersToCompute = validatedModifiers.filter(
@@ -8,6 +8,8 @@ module.exports = ({ modifierActions }) =>
8
8
  paymentMethod,
9
9
  paymentType,
10
10
  isPrepay,
11
+ customerTotalVisits,
12
+ customerTotalSales,
11
13
  }) {
12
14
  const validatedModifiers = [];
13
15
  const firstValidatedModifiers = itemModifiers.map(each =>
@@ -19,6 +21,8 @@ module.exports = ({ modifierActions }) =>
19
21
  paymentMethod,
20
22
  paymentType,
21
23
  isPrepay,
24
+ customerTotalVisits,
25
+ customerTotalSales,
22
26
  })
23
27
  );
24
28
 
@@ -9,6 +9,8 @@ module.exports = ({ actions, utils }) => {
9
9
  paymentMethod,
10
10
  paymentType,
11
11
  isPrepay,
12
+ customerTotalVisits,
13
+ customerTotalSales,
12
14
  }
13
15
  ) =>
14
16
  modifier.conditions && Array.isArray(modifier.conditions.rules)
@@ -83,6 +85,18 @@ module.exports = ({ actions, utils }) => {
83
85
  condition.value,
84
86
  condition.operand
85
87
  );
88
+ case 'customerTotalVisits':
89
+ return actions.validateNumberCondition(
90
+ customerTotalVisits,
91
+ condition.value,
92
+ condition.operand
93
+ );
94
+ case 'customerTotalSales':
95
+ return actions.validateNumberCondition(
96
+ customerTotalSales,
97
+ condition.value,
98
+ condition.operand
99
+ );
86
100
  case 'modifiers':
87
101
  return actions.validateRequiredModifiers(
88
102
  item.modifiers,
@@ -124,6 +138,8 @@ module.exports = ({ actions, utils }) => {
124
138
  paymentMethod,
125
139
  paymentType,
126
140
  isPrepay,
141
+ customerTotalVisits,
142
+ customerTotalSales,
127
143
  } = opts;
128
144
  return (
129
145
  modifier &&
@@ -135,6 +151,8 @@ module.exports = ({ actions, utils }) => {
135
151
  paymentMethod,
136
152
  paymentType,
137
153
  isPrepay,
154
+ customerTotalVisits,
155
+ customerTotalSales,
138
156
  })
139
157
  );
140
158
  }
@@ -0,0 +1,48 @@
1
+ module.exports = ({ sha256 }) => {
2
+ function combineHashParts(partA, partB) {
3
+ let combined = '';
4
+ try {
5
+ combined = partA
6
+ .split('')
7
+ .map((char, index) => {
8
+ const digitA = parseInt(char, 16);
9
+ const digitB = parseInt(partB[index], 16);
10
+
11
+ // eslint-disable-next-line no-bitwise
12
+ return (digitA ^ digitB).toString(16);
13
+ })
14
+ .join('')
15
+ .padStart(partA.length, '0');
16
+ } catch (err) {
17
+ console.log(JSON.stringify(err));
18
+ }
19
+
20
+ return combined;
21
+ }
22
+
23
+ function generateManualModifierId(parentId, name) {
24
+ const input = `${parentId}-${name}`;
25
+ const hash = sha256(input).toString(); // 64 hex characters
26
+
27
+ const firstPart = hash.slice(0, 24);
28
+ const lastPart = hash.slice(-24);
29
+
30
+ return combineHashParts(firstPart, lastPart); // 24-char hex string
31
+ }
32
+
33
+ return function createManualModifier({ parentId, name, group }) {
34
+ const _id = generateManualModifierId(parentId, name);
35
+
36
+ const manualModifier = {
37
+ name,
38
+ _id,
39
+ direct: true,
40
+ group,
41
+ properties: {
42
+ isManual: true,
43
+ },
44
+ };
45
+
46
+ return manualModifier;
47
+ };
48
+ };
@@ -1,4 +1,4 @@
1
- module.exports = ({ sha256 }) => {
1
+ module.exports = ({ actions }) => {
2
2
  const csvToArray = input =>
3
3
  input
4
4
  .split(',')
@@ -39,23 +39,13 @@ module.exports = ({ sha256 }) => {
39
39
  ).filter(modName => otherModifiers.every(mod => mod.name !== modName));
40
40
 
41
41
  modifiers.push(
42
- ...manualModifiersNames.map((each, index) => {
43
- const hash = sha256(`${index}-${modifier._id}`).toString();
44
-
45
- const _id = hash.substring(0, 24);
46
-
47
- const manualModifier = {
42
+ ...manualModifiersNames.map(each =>
43
+ actions.createManualModifier({
44
+ parentId: modifier._id,
48
45
  name: each,
49
- _id,
50
- direct: true,
51
46
  group: modifier.group,
52
- properties: {
53
- isManual: true,
54
- },
55
- };
56
-
57
- return manualModifier;
58
- })
47
+ })
48
+ )
59
49
  );
60
50
  }
61
51
 
@@ -166,6 +166,7 @@ const getOverrideNote = require('./getOverrideNote');
166
166
  const isNotesOverride = require('./isNotesOverride');
167
167
  const isOverrideSubtotal = require('./isOverrideSubtotal');
168
168
  const validatePaymentCondition = require('./validatePaymentCondition');
169
+ const createManualModifier = require('./createManualModifier');
169
170
 
170
171
  const modifierActions = (deps = {}) => {
171
172
  const actions = {};
@@ -345,6 +346,7 @@ const modifierActions = (deps = {}) => {
345
346
  isNotesOverride: isNotesOverride(innerDeps),
346
347
  isOverrideSubtotal: isOverrideSubtotal(innerDeps),
347
348
  validatePaymentCondition: validatePaymentCondition(innerDeps),
349
+ createManualModifier: createManualModifier(innerDeps),
348
350
  });
349
351
 
350
352
  Object.keys(freezedActions).forEach(actionName => {
@@ -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.102",
3
+ "version": "1.0.104",
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": "a4c2dff797325d1c452db5eab1e9bda8f9de4e97"
57
+ "gitHead": "0a74400677d6852460e9a7773a3e6480912ad8b3"
58
58
  }