@darkpos/pricing 1.0.142 → 1.0.145

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.
@@ -814,7 +814,7 @@ describe('Item actions', () => {
814
814
  expect(newItem).toHaveProperty('price', 10);
815
815
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
816
816
  amount: 0,
817
- description: 'Override item price fixed 10 ($10.00/Unit)',
817
+ description: 'Override item price fixed 10 ($10.00/unit)',
818
818
  });
819
819
 
820
820
  expect(newItem).toHaveProperty('subTotals', {
@@ -867,8 +867,7 @@ describe('Item actions', () => {
867
867
  expect(newItem).toHaveProperty('price', 135);
868
868
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
869
869
  amount: 0,
870
- description:
871
- 'Override Item Price 10 USD Multiplier (10 Unit @ $13.50/Unit)',
870
+ description: 'Override Item Price 10 USD Multiplier (10 @ $13.50/unit)',
872
871
  });
873
872
 
874
873
  expect(newItem).toHaveProperty('subTotals', {
@@ -1356,7 +1355,7 @@ describe('Item actions', () => {
1356
1355
  expect(calculatedOrder.items[0].price).toBe(0);
1357
1356
  expect(calculatedOrder.items[0].total).toBe(0);
1358
1357
  expect(calculatedOrder.items[0].modifiers[0]._computed.description).toBe(
1359
- 'No Clean (0 Unit @ $0.00/Unit)'
1358
+ 'No Clean (0 @ $0.00/unit)'
1360
1359
  );
1361
1360
  expect(calculatedOrder.items[0].modifiers[1]._computed.description).toBe(
1362
1361
  '30% Family Discount'
@@ -1480,7 +1479,7 @@ describe('Item actions', () => {
1480
1479
  '30% Family Discount'
1481
1480
  );
1482
1481
  expect(calculatedOrder.items[0].modifiers[1]._computed.description).toBe(
1483
- 'No Clean (0 Unit @ $0.00/Unit)'
1482
+ 'No Clean (0 @ $0.00/unit)'
1484
1483
  );
1485
1484
  });
1486
1485
 
@@ -1668,7 +1667,7 @@ describe('Item actions', () => {
1668
1667
  expect(newItem).toHaveProperty('price', 0);
1669
1668
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
1670
1669
  amount: 0,
1671
- description: 'Override item price fixed 0 ($0.00/Unit)',
1670
+ description: 'Override item price fixed 0 ($0.00/unit)',
1672
1671
  });
1673
1672
 
1674
1673
  expect(newItem.modifiers[1]).toHaveProperty('_computed', {
@@ -1804,7 +1803,7 @@ describe('Item actions', () => {
1804
1803
  expect(newItem.total).toBe(5.5);
1805
1804
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
1806
1805
  amount: 0,
1807
- description: 'Override item price fixed 0 ($5.00/Unit)',
1806
+ description: 'Override item price fixed 0 ($5.00/unit)',
1808
1807
  });
1809
1808
 
1810
1809
  expect(newItem.modifiers[1]).toHaveProperty('_computed', {
@@ -1875,7 +1874,7 @@ describe('Item actions', () => {
1875
1874
 
1876
1875
  expect(newItem.modifiers[1]).toHaveProperty('_computed', {
1877
1876
  amount: 0,
1878
- description: 'Override item price fixed 0 ($5.00/Unit)',
1877
+ description: 'Override item price fixed 0 ($5.00/unit)',
1879
1878
  });
1880
1879
 
1881
1880
  expect(newItem).toHaveProperty('subTotals', {
@@ -1922,7 +1921,7 @@ describe('Item actions', () => {
1922
1921
 
1923
1922
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
1924
1923
  amount: 0,
1925
- description: 'Override item price fixed 0 ($5.00/Unit)',
1924
+ description: 'Override item price fixed 0 ($5.00/unit)',
1926
1925
  });
1927
1926
  expect(newItem.modifiers[0].conditions.valid).toBe(false);
1928
1927
 
@@ -1941,7 +1940,7 @@ describe('Item actions', () => {
1941
1940
 
1942
1941
  expect(newItem.modifiers[0]).toHaveProperty('_computed', {
1943
1942
  amount: 0,
1944
- description: 'Override item price fixed 0 ($5.00/Unit)',
1943
+ description: 'Override item price fixed 0 ($5.00/unit)',
1945
1944
  });
1946
1945
  expect(newItem.modifiers[0].conditions.valid).toBe(true);
1947
1946
 
@@ -2695,4 +2694,204 @@ describe('Item actions', () => {
2695
2694
  expect(updatedItem.price).toBe(14.5);
2696
2695
  });
2697
2696
  });
2697
+ test('CU-86dzhxcmx: Show accurate description for options modifier', () => {
2698
+ const item = {
2699
+ name: 'Coat',
2700
+ description: '',
2701
+ pieces: 1,
2702
+ modifiersTotalAmount: 0,
2703
+ totalPaid: 0,
2704
+ price: 13,
2705
+ quantity: 1,
2706
+ path: ',68a0ea81aa30dd1524162285,68a102e959fd1012e3aaa97b,',
2707
+ notes: [],
2708
+ serial: null,
2709
+ sku: '',
2710
+ modifiers: [
2711
+ {
2712
+ _id: '69974da407b7cf050250222e',
2713
+ attributes: ['override'],
2714
+ modifierId: '699738ae40884707d55d5142',
2715
+ _parentId: null,
2716
+ locked: false,
2717
+ name: 'Pleats',
2718
+ sku: '',
2719
+ description: '',
2720
+ group: '',
2721
+ type: '',
2722
+ tags: ['default'],
2723
+ order: 0,
2724
+ included: false,
2725
+ direct: true,
2726
+ hidden: false,
2727
+ print: true,
2728
+ required: false,
2729
+ recommended: false,
2730
+ default: false,
2731
+ code: '',
2732
+ properties: {
2733
+ override: {
2734
+ field: 'price',
2735
+ type: null,
2736
+ fixedValue: null,
2737
+ service: null,
2738
+ multiplier: true,
2739
+ unitAsAmountMultiplier: false,
2740
+ amountMultiplier: null,
2741
+ options: [
2742
+ {
2743
+ label: 'Pleats',
2744
+ input: 'multiply',
2745
+ units: ['pleat'],
2746
+ },
2747
+ ],
2748
+ selected: {
2749
+ label: 'Pleats',
2750
+ input: 'multiply',
2751
+ units: ['pleat'],
2752
+ _id: '69974da007b7cf050250222d',
2753
+ selectedUnit: 'pleat',
2754
+ },
2755
+ },
2756
+ sort: null,
2757
+ },
2758
+ conditions: {
2759
+ valid: true,
2760
+ },
2761
+ compute: {
2762
+ amount: 4,
2763
+ },
2764
+ _createdAt: '2026-02-19T16:22:06.530Z',
2765
+ _updatedAt: '2026-02-19T16:42:25.064Z',
2766
+ __typename: 'Modifier',
2767
+ addModifiers: [],
2768
+ delModifiers: [],
2769
+ },
2770
+ ],
2771
+ _id: '69974d9e07b7cf0502502227',
2772
+ _updatedAt: '2026-02-12T21:24:47.256Z',
2773
+ _createdAt: '2025-08-16T21:19:58.509Z',
2774
+ weight: 0,
2775
+ properties: {
2776
+ overwrittenPrice: 13,
2777
+ },
2778
+ hasInventory: true,
2779
+ inventoryType: 'push',
2780
+ serialRequired: null,
2781
+ tags: [],
2782
+ category: null,
2783
+ __typename: 'OrderItem',
2784
+ priceLevels: [
2785
+ {
2786
+ value: 13,
2787
+ tags: ['default'],
2788
+ },
2789
+ {
2790
+ value: 6,
2791
+ tags: ['police'],
2792
+ },
2793
+ {
2794
+ value: 11,
2795
+ tags: ['default', 'press only'],
2796
+ },
2797
+ {
2798
+ value: 4,
2799
+ tags: ['police', 'press only'],
2800
+ },
2801
+ ],
2802
+ costLevels: [],
2803
+ itemId: '68a0f5feaa30dd15241630e1',
2804
+ menuRuleId: '68a1039559fd1012e3aaa98e',
2805
+ };
2806
+ const newItem = pricingService.item.calculate(item);
2807
+
2808
+ expect(newItem).toHaveProperty('total', 52);
2809
+ expect(newItem).toHaveProperty('price', 52);
2810
+ expect(newItem.modifiers[0]).toHaveProperty('_computed', {
2811
+ amount: 0,
2812
+ description: 'Pleats (4 @ $13.00/pleat)',
2813
+ });
2814
+ });
2815
+
2816
+ test('CU-86dzhxcmx: Show accurate description for override.amount modifier', () => {
2817
+ const item = {
2818
+ name: 'Coat',
2819
+ description: '',
2820
+ pieces: 1,
2821
+ modifiersTotalAmount: 0,
2822
+ total: 25.2,
2823
+ totalPaid: 0,
2824
+ price: 13,
2825
+ quantity: 1,
2826
+ path: ',68a0ea81aa30dd1524162285,68a102e959fd1012e3aaa97b,',
2827
+ notes: [],
2828
+ serial: null,
2829
+ sku: '',
2830
+ modifiers: [
2831
+ {
2832
+ _id: '69976be93caefd42eef93bed',
2833
+ attributes: ['override'],
2834
+ modifierId: '699738ae40884707d55d5142',
2835
+ _parentId: null,
2836
+ locked: false,
2837
+ name: 'Pleats',
2838
+ tags: ['default'],
2839
+ properties: {
2840
+ override: {
2841
+ field: 'amount',
2842
+ type: 'manual',
2843
+ fixedValue: 2,
2844
+ service: null,
2845
+ multiplier: true,
2846
+ unitAsAmountMultiplier: true,
2847
+ amountMultiplier: 5.5,
2848
+ options: null,
2849
+ },
2850
+ sort: null,
2851
+ },
2852
+ conditions: {
2853
+ valid: true,
2854
+ },
2855
+ compute: {
2856
+ type: 'fixed',
2857
+ amount: 2,
2858
+ action: 'add',
2859
+ },
2860
+ _createdAt: '2026-02-19T16:22:06.530Z',
2861
+ _updatedAt: '2026-02-19T19:56:51.708Z',
2862
+ __typename: 'Modifier',
2863
+ addModifiers: [],
2864
+ delModifiers: [],
2865
+ },
2866
+ ],
2867
+ _id: '69976be33caefd42eef93be8',
2868
+ priceLevels: [
2869
+ {
2870
+ value: 13,
2871
+ tags: ['default'],
2872
+ },
2873
+ {
2874
+ value: 6,
2875
+ tags: ['police'],
2876
+ },
2877
+ {
2878
+ value: 11,
2879
+ tags: ['default', 'press only'],
2880
+ },
2881
+ {
2882
+ value: 4,
2883
+ tags: ['police', 'press only'],
2884
+ },
2885
+ ],
2886
+ costLevels: [],
2887
+ };
2888
+ const newItem = pricingService.item.calculate(item);
2889
+
2890
+ expect(newItem).toHaveProperty('total', 24);
2891
+ expect(newItem).toHaveProperty('price', 13);
2892
+ expect(newItem.modifiers[0]).toHaveProperty('_computed', {
2893
+ amount: 11,
2894
+ description: 'Pleats (2 @ $5.50/unit)',
2895
+ });
2896
+ });
2698
2897
  });
@@ -0,0 +1,86 @@
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
+
10
+ describe('hasSerial function', () => {
11
+ test('returns true when another item has the same serial', () => {
12
+ const { hasSerial } = pricingService.order;
13
+
14
+ const order = {
15
+ items: [
16
+ {
17
+ _id: '1',
18
+ serial: 'ABC-123',
19
+ },
20
+ ],
21
+ };
22
+
23
+ const item = {
24
+ _id: '2',
25
+ serial: ' abc-123 ',
26
+ };
27
+
28
+ const result = hasSerial({ order, item });
29
+
30
+ expect(result).toBe(true);
31
+ });
32
+
33
+ test('returns false when the matching serial belongs to the same item', () => {
34
+ const { hasSerial } = pricingService.order;
35
+
36
+ const order = {
37
+ items: [
38
+ {
39
+ _id: '1',
40
+ serial: 'ABC-123',
41
+ },
42
+ ],
43
+ };
44
+
45
+ const item = {
46
+ _id: '1',
47
+ serial: 'ABC-123',
48
+ };
49
+
50
+ const result = hasSerial({ order, item });
51
+
52
+ expect(result).toBe(false);
53
+ });
54
+
55
+ test('returns false for related items', () => {
56
+ const { hasSerial } = pricingService.order;
57
+
58
+ const order = {
59
+ items: [
60
+ {
61
+ _id: '1',
62
+ serial: 'ABC-123',
63
+ },
64
+ ],
65
+ };
66
+
67
+ const item = {
68
+ _id: '2',
69
+ serial: 'ABC-123',
70
+ properties: {
71
+ relatedItem: true,
72
+ },
73
+ };
74
+
75
+ const result = hasSerial({ order, item });
76
+
77
+ expect(result).toBe(false);
78
+ });
79
+
80
+ test('returns false when order or item is missing', () => {
81
+ const { hasSerial } = pricingService.order;
82
+
83
+ expect(hasSerial({ order: null, item: { serial: 'ABC-123' } })).toBe(false);
84
+ expect(hasSerial({ order: { items: [] }, item: null })).toBe(false);
85
+ });
86
+ });
@@ -1,43 +1,49 @@
1
1
  module.exports = ({ actions, localization, _, utils }) =>
2
2
  function createDescription({ modifier, price }) {
3
- const { _computed, compute, name } = modifier;
4
-
5
- let description = '';
6
- const localAmount =
7
- !!_computed.amount && Number(_computed.amount) !== 0
8
- ? `${localization.formatAmount(_computed.amount)}`
9
- : '';
10
-
11
- const localBasePrice = localization.formatAmount(price || 0);
12
-
3
+ const name = _.get(modifier, 'name', '');
4
+ const computedAmount = _.get(modifier, '_computed.amount', 0);
5
+ const computeAmount = _.get(modifier, 'compute.amount', 0);
13
6
  const isMultiplier = actions.isMultiplierOverride(modifier);
14
7
 
15
- description = `${name}${localAmount ? ` (${localAmount})` : ''}`;
8
+ const UNIT_SUFFIX = '/unit';
9
+
10
+ if (actions.isAmountOverride(modifier) && isMultiplier) {
11
+ const isAmountMultiplier = actions.isAmountMultiplier(modifier);
16
12
 
17
- if (actions.isPriceOverride(modifier)) {
18
- const dividedPrice = localization.formatAmount(
19
- price && compute.amount ? utils.math.div(price, compute.amount) : 0
13
+ const amountMultiplier = localization.formatAmount(
14
+ actions.getAmountMultiplier(modifier)
20
15
  );
21
- description = isMultiplier
22
- ? `${name} (${compute.amount} Unit @ ${dividedPrice}/Unit)`
23
- : `${name} (${localization.formatAmount(compute.amount)}/Unit)`;
24
- }
16
+ if (isAmountMultiplier) {
17
+ return `${name} (${computeAmount} @ ${amountMultiplier}${UNIT_SUFFIX})`;
18
+ }
25
19
 
26
- if (actions.isAmountOverride(modifier) && isMultiplier) {
27
- description = `${name} (${localization.formatAmount(_computed.amount)})`;
20
+ return `${name} (${localization.formatAmount(computedAmount)})`;
28
21
  }
29
22
 
30
- if (actions.isOptionsSelectedOverride(modifier)) {
31
- const selectedOverrideOptions = _.get(
23
+ if (
24
+ actions.isPriceOverride(modifier) ||
25
+ actions.isOptionsSelectedOverride(modifier)
26
+ ) {
27
+ const selectedUnit = _.get(
32
28
  modifier,
33
- 'properties.override.selected'
29
+ 'properties.override.selected.selectedUnit'
34
30
  );
35
- description = isMultiplier
36
- ? `${name} (${compute.amount} Unit @ ${localBasePrice}/${selectedOverrideOptions.selectedUnit})`
37
- : `${name} (${localization.formatAmount(compute.amount)}/${
38
- selectedOverrideOptions.selectedUnit
39
- })`;
31
+ const unitSuffix = selectedUnit ? `/${selectedUnit}` : UNIT_SUFFIX;
32
+
33
+ if (isMultiplier) {
34
+ const dividedPrice = localization.formatAmount(
35
+ price && computeAmount ? utils.math.div(price, computeAmount) : 0
36
+ );
37
+ return `${name} (${computeAmount} @ ${dividedPrice}${unitSuffix})`;
38
+ }
39
+
40
+ return `${name} (${localization.formatAmount(computeAmount)}${unitSuffix})`;
40
41
  }
41
42
 
42
- return description;
43
+ const localAmount =
44
+ computedAmount && Number(computedAmount) !== 0
45
+ ? localization.formatAmount(computedAmount)
46
+ : '';
47
+
48
+ return `${name}${localAmount ? ` (${localAmount})` : ''}`;
43
49
  };
@@ -0,0 +1,29 @@
1
+ const normalizeSerial = serial => {
2
+ if (typeof serial !== 'string') return '';
3
+ return serial.trim().toUpperCase();
4
+ };
5
+
6
+ module.exports = ({ itemActions }) =>
7
+ function hasSerial({ order, item }) {
8
+ if (
9
+ !item ||
10
+ !item.serial ||
11
+ !order ||
12
+ !order.items ||
13
+ itemActions.isRelatedItem(item)
14
+ )
15
+ return false;
16
+
17
+ const normalizedSerial = normalizeSerial(item.serial);
18
+
19
+ if (!normalizedSerial) return false;
20
+
21
+ return order.items
22
+ .filter(
23
+ orderItem =>
24
+ orderItem._id !== item._id && !itemActions.isRelatedItem(orderItem)
25
+ )
26
+ .some(
27
+ orderItem => normalizeSerial(orderItem.serial) === normalizedSerial
28
+ );
29
+ };
@@ -101,6 +101,7 @@ const getTaxes = require('./getTaxes');
101
101
  const getPickedStatus = require('./getPickedStatus');
102
102
  const calculateWithPayment = require('./calculateWithPayment');
103
103
  const getOverpaidAmount = require('./getOverpaidAmount');
104
+ const hasSerial = require('./hasSerial');
104
105
 
105
106
  const orderActions = (deps = {}) => {
106
107
  const actions = {};
@@ -213,6 +214,7 @@ const orderActions = (deps = {}) => {
213
214
  getPickedStatus: getPickedStatus(innerDeps),
214
215
  calculateWithPayment: calculateWithPayment(innerDeps),
215
216
  getOverpaidAmount: getOverpaidAmount(innerDeps),
217
+ hasSerial: hasSerial(innerDeps),
216
218
  });
217
219
 
218
220
  Object.keys(freezedActions).forEach(actionName => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darkpos/pricing",
3
- "version": "1.0.142",
3
+ "version": "1.0.145",
4
4
  "description": "Pricing calculator",
5
5
  "author": "Dark POS",
6
6
  "license": "ISC",
@@ -32,6 +32,7 @@
32
32
  "test:addItemModifier": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/modifier/addItemModifier.test.js",
33
33
  "test:payment": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/payment.test.js",
34
34
  "test:orderPaymentModifier": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/order-payment-modifier.test.js",
35
+ "test:hasSerial": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/hasSerial.test.js",
35
36
  "lint": "eslint --quiet lib/"
36
37
  },
37
38
  "publishConfig": {
@@ -53,5 +54,5 @@
53
54
  "supertest": "^6.2.3",
54
55
  "supervisor": "^0.12.0"
55
56
  },
56
- "gitHead": "e7382ab79964b44db2814e58b06a8dfe5c036b34"
57
+ "gitHead": "eb6adf31020d7ca3b57f6e6b1bfa20c4e0289ca0"
57
58
  }