@darkpos/pricing 1.0.55 → 1.0.57

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.
@@ -74,6 +74,64 @@ describe('Modifier actions', () => {
74
74
  },
75
75
  });
76
76
 
77
+ expect(conditionsBag).toEqual([]);
78
+ expect(error).toEqual('');
79
+
80
+ expect(updatedOrder2.items[0].modifiers.length).toEqual(2);
81
+ });
82
+
83
+ test('CU-86dve27tq Should not allow adding a modifier more than once to an item if isQuantityMultiplier={true} QTY={2}', () => {
84
+ const order = {
85
+ id: 'ord-123',
86
+ items: [],
87
+ modifiers: [],
88
+ };
89
+ const modifier = {
90
+ _id: 1,
91
+ compute: {
92
+ amount: 10,
93
+ action: 'subtract',
94
+ type: 'fixed',
95
+ },
96
+ properties: {
97
+ isQuantityMultiplier: true,
98
+ },
99
+ };
100
+ order.items.push({
101
+ quantity: 2,
102
+ itemId: '123',
103
+ price: 100,
104
+ modifiers: [],
105
+ });
106
+
107
+ const conditionsBag = [];
108
+
109
+ const updatedOrder = pricingService.order.addItemModifier({
110
+ order,
111
+ modifier,
112
+ itemIndex: 0,
113
+ onConditionsNotMet: bag => {
114
+ bag.forEach(condition => {
115
+ conditionsBag.push(condition);
116
+ });
117
+ },
118
+ });
119
+
120
+ let error = '';
121
+ const updatedOrder2 = pricingService.order.addItemModifier({
122
+ order: { ...updatedOrder },
123
+ modifier,
124
+ itemIndex: 0,
125
+ onConditionsNotMet: bag => {
126
+ bag.forEach(condition => {
127
+ conditionsBag.push(condition);
128
+ });
129
+ },
130
+ onError: errorMessage => {
131
+ error = errorMessage;
132
+ },
133
+ });
134
+
77
135
  expect(conditionsBag).toEqual([]);
78
136
  expect(error).toEqual('modifier.has.reached.the.maximum.amount.of.applies');
79
137
  expect(updatedOrder2).toEqual(updatedOrder);
@@ -1,11 +1,22 @@
1
1
  const moment = require('moment-timezone');
2
2
  const usePricing = require('../../lib/index');
3
3
 
4
- const pricingService = usePricing();
5
- const { pickEndDate } = pricingService.store;
4
+ const pricingService = usePricing({
5
+ store: {
6
+ _settings: {
7
+ schedule: {
8
+ close: [
9
+ {
10
+ date: '2024-09-03',
11
+ },
12
+ ],
13
+ },
14
+ },
15
+ },
16
+ });
6
17
 
7
18
  describe('pickEndDate function', () => {
8
- test('Get calculated Order, one item', () => {
19
+ test('Get EndDate, today is an Skip date', () => {
9
20
  const schedule = {
10
21
  addDays: 1,
11
22
  hour: 17,
@@ -16,24 +27,17 @@ describe('pickEndDate function', () => {
16
27
  };
17
28
 
18
29
  const now = moment('2024-08-25T15:00:00Z').tz('America/New_York');
19
-
20
30
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
21
- const result = pickEndDate(schedule);
22
31
 
23
- const expectedDate = now
24
- .clone()
25
- .add(2, 'days')
26
- .set({ hour: schedule.hour, minute: schedule.minute, second: 0 })
27
- .utc()
28
- .format();
32
+ const result = pricingService.store.pickEndDate(schedule);
29
33
 
30
- expect(result).toBe(expectedDate);
34
+ expect(result).toBe('2024-08-27T21:00:00Z'); // 2024-08-27 17:00:00 EDT
31
35
  });
32
36
 
33
37
  test('Order falls on a closed day', () => {
34
38
  const schedule = {
35
39
  addDays: 1,
36
- hour: 17,
40
+ hour: 14,
37
41
  minute: 0,
38
42
  skipDays: [7], // Skip Sunday
39
43
  cutHour: { hour: 16, minute: 0 },
@@ -43,19 +47,12 @@ describe('pickEndDate function', () => {
43
47
  const now = moment('2024-08-27T15:00:00Z').tz('America/New_York'); // Tuesday
44
48
 
45
49
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
46
- const result = pickEndDate(schedule);
47
-
48
- const expectedDate = now
49
- .clone()
50
- .add(2, 'days') // Skips the closed Wednesday, goes to Thursday
51
- .set({ hour: schedule.hour, minute: 0, second: 0 })
52
- .utc()
53
- .format();
50
+ const result = pricingService.store.pickEndDate(schedule);
54
51
 
55
- expect(result).toBe(expectedDate);
52
+ expect(result).toBe('2024-08-28T18:00:00Z'); // 2024-08-28 14:00:00 EDT
56
53
  });
57
54
 
58
- test('Order calculated on a weekend', () => {
55
+ test('Get endDate if today is friday and Saturday and Sunday are skip days', () => {
59
56
  const schedule = {
60
57
  addDays: 1,
61
58
  hour: 17,
@@ -68,16 +65,9 @@ describe('pickEndDate function', () => {
68
65
  const now = moment('2024-08-23T15:00:00Z').tz('America/New_York'); // Friday
69
66
 
70
67
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
71
- const result = pickEndDate(schedule);
68
+ const result = pricingService.store.pickEndDate(schedule);
72
69
 
73
- const expectedDate = now
74
- .clone()
75
- .add(3, 'days') // Skips weekend, goes to Monday
76
- .set({ hour: 17, minute: 0, second: 0 })
77
- .utc()
78
- .format();
79
-
80
- expect(result).toBe(expectedDate);
70
+ expect(result).toBe('2024-08-26T21:00:00Z'); // 2024-08-26 17:00:00 EDT
81
71
  });
82
72
 
83
73
  test('Order time before cut-off hour', () => {
@@ -93,16 +83,11 @@ describe('pickEndDate function', () => {
93
83
  const now = moment('2024-08-25T15:00:00Z').tz('America/New_York'); // Friday, before cut-off
94
84
 
95
85
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
96
- const result = pickEndDate(schedule);
97
-
98
- const expectedDate = now
99
- .clone()
100
- .set({ hour: 17, minute: 0, second: 0 })
101
- .utc()
102
- .format();
86
+ const result = pricingService.store.pickEndDate(schedule);
103
87
 
104
- expect(result).toBe(expectedDate);
88
+ expect(result).toBe('2024-08-25T21:00:00Z'); // 2024-08-25 17:00:00 EDT
105
89
  });
90
+
106
91
  test('Order time after cut-off hour', () => {
107
92
  const schedule = {
108
93
  hour: 17,
@@ -124,15 +109,44 @@ describe('pickEndDate function', () => {
124
109
  const now = moment().tz('America/New_York'); // Friday, after cut-off
125
110
 
126
111
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
127
- const result = pickEndDate(schedule);
112
+ const result = pricingService.store.pickEndDate(schedule);
113
+
114
+ expect(result).toBe('2024-08-31T21:00:00Z'); // 2024-08-31 17:00:00 EDT
115
+ });
116
+
117
+ test('Get EndDate, there are skip dates in between', () => {
118
+ const schedule = {
119
+ addDays: 1,
120
+ hour: 17,
121
+ minute: 0,
122
+ skipDays: [7, 0],
123
+ cutHour: { hour: 16, minute: 0 },
124
+ cutDay: 2,
125
+ };
126
+
127
+ const now = moment('2024-08-25T15:00:00Z').tz('America/New_York');
128
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
129
+
130
+ const result = pricingService.store.pickEndDate(schedule);
131
+
132
+ expect(result).toBe('2024-08-27T21:00:00Z'); // 2024-08-27 17:00:00 EDT
133
+ });
134
+
135
+ test('Get EndDate, there are skip dates in between and endDate falls in a closed date', () => {
136
+ const schedule = {
137
+ addDays: 1,
138
+ hour: 20,
139
+ minute: 0,
140
+ skipDays: [1, 7],
141
+ cutHour: { hour: 16, minute: 0 },
142
+ cutDay: 2,
143
+ };
144
+
145
+ const now = moment('2024-09-01T15:00:00Z').tz('America/New_York');
146
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
128
147
 
129
- const expectedDate = now
130
- .clone()
131
- .add(6, 'days') // Skips weekend, goes to Monday
132
- .set({ hour: 17, minute: 0, second: 0 })
133
- .utc()
134
- .format();
148
+ const result = pricingService.store.pickEndDate(schedule);
135
149
 
136
- expect(result).toBe(expectedDate);
150
+ expect(result).toBe('2024-09-06T00:00:00Z'); // 2024-09-05 20:00:00 EDT
137
151
  });
138
152
  });
@@ -0,0 +1,32 @@
1
+ const usePricing = require('../../index');
2
+ const mockStores = require('../mocks/stores');
3
+ const orderNotPaid = require('../mocks/unpaid/order-not-paid.json');
4
+ const constants = require('../../lib/constants/Status');
5
+
6
+ const session = {
7
+ store: mockStores[0],
8
+ };
9
+
10
+ const pricingService = usePricing(session);
11
+
12
+ describe('Unvoid order', () => {
13
+ test('Should update status.order to OPEN if order has existing status', () => {
14
+ const updatedOrder = pricingService.order.unvoidOrder(orderNotPaid);
15
+ expect(updatedOrder.status.order).toBe(constants.Order.OPEN);
16
+ });
17
+
18
+ test('Should return null if order is null', () => {
19
+ const updatedOrder = pricingService.order.unvoidOrder(null);
20
+ expect(updatedOrder).toBeNull();
21
+ });
22
+ test('Should return undefined if order is undefined', () => {
23
+ const updatedOrder = pricingService.order.unvoidOrder(undefined);
24
+ expect(updatedOrder).toBeUndefined();
25
+ });
26
+ test('Should not mutate the original order object', () => {
27
+ const order = { ...orderNotPaid };
28
+ const orderClone = JSON.parse(JSON.stringify(orderNotPaid));
29
+ pricingService.order.unvoidOrder(order);
30
+ expect(order).toEqual(orderClone);
31
+ });
32
+ });
@@ -227,7 +227,7 @@ module.exports = ({ actions, itemActions, modifierActions, utils, _ }) => {
227
227
  if (
228
228
  contains &&
229
229
  modifierActions.isCompute(modifier) &&
230
- !modifierActions.isQuantityMultiplier(modifier)
230
+ modifierActions.isQuantityMultiplier(modifier)
231
231
  ) {
232
232
  if (onError)
233
233
  onError('modifier.has.reached.the.maximum.amount.of.applies');
@@ -38,6 +38,7 @@ const addDiscountModifier = require('./addDiscountModifier');
38
38
  const calculateDue = require('./calculateDue');
39
39
  const toggleModifier = require('./toggleModifier');
40
40
  const voidOrder = require('./void');
41
+ const unvoidOrder = require('./unvoid');
41
42
  const holdOrder = require('./hold');
42
43
  const openOrder = require('./open');
43
44
  const isDetailed = require('./isDetailed');
@@ -137,6 +138,7 @@ const orderActions = (deps = {}) => {
137
138
  calculateDue: calculateDue(innerDeps),
138
139
  toggleModifier: toggleModifier(innerDeps),
139
140
  voidOrder: voidOrder(innerDeps),
141
+ unvoidOrder: unvoidOrder(innerDeps),
140
142
  holdOrder: holdOrder(innerDeps),
141
143
  openOrder: openOrder(innerDeps),
142
144
  isDetailed: isDetailed(innerDeps),
@@ -0,0 +1,11 @@
1
+ module.exports = ({ constants }) =>
2
+ function unvoid(order) {
3
+ if (!order) return order;
4
+ return {
5
+ ...order,
6
+ status: {
7
+ ...(order.status || {}),
8
+ order: constants.Status.Order.OPEN,
9
+ },
10
+ };
11
+ };
@@ -4,21 +4,20 @@ module.exports = ({ settings, _, moment }) => {
4
4
  const getClosedDays = () => {
5
5
  const schedule = _.get(settings, 'schedule', {});
6
6
  const { close = [] } = schedule;
7
-
8
7
  if (!Array.isArray(close)) return [];
9
- return close.map(closedDate => ({
10
- date: moment(closedDate.date), // the date is saved with the user timezone, no need to convert it back here (ex: date: '2024-08-27' would become date:'2024-08-26 23:00 -4:00')
11
- }));
8
+ return close;
12
9
  };
13
10
 
11
+ const MAX_ADD_DAYS = 365;
12
+
14
13
  return function pickEndDate(schedule = {}) {
15
14
  const {
16
- addDays = 1,
15
+ addDays: addDaysParam,
17
16
  hour,
18
17
  minute,
19
18
  skipDays = [],
20
19
  cutHour,
21
- cutDay = 1,
20
+ cutDay = 0,
22
21
  } = schedule;
23
22
 
24
23
  const todayTZ = moment().tz(timezone);
@@ -26,36 +25,45 @@ module.exports = ({ settings, _, moment }) => {
26
25
  const closedDays = getClosedDays();
27
26
  const todayHours = todayTZ.get('hours');
28
27
  const todayMinutes = todayTZ.get('minutes');
28
+
29
+ const addDays =
30
+ typeof addDaysParam !== 'number' || addDaysParam > MAX_ADD_DAYS
31
+ ? 0
32
+ : addDaysParam;
33
+
29
34
  if (
30
35
  (cutHour && todayHours > cutHour.hour) ||
31
36
  (todayHours >= cutHour.hour && todayMinutes > cutHour.minute)
32
37
  ) {
33
- endDateTZ = endDateTZ.add(cutDay, 'days'); // if the cut day is zero should we add a day based on hours? ask Nabil/Vicky
38
+ endDateTZ = endDateTZ.add(cutDay, 'days');
34
39
  }
35
40
 
36
- endDateTZ.add(addDays, 'days');
37
- // do the logic related to skipdays
38
- // if the date already pass the skip day, do nothing
39
- // if the date is the same as one of the skip day, check the next skip day if any, then add one more day
40
- skipDays.forEach(day => {
41
- if (todayTZ.isoWeekday() <= day) {
42
- endDateTZ.add(1, 'days');
43
- }
44
- });
45
-
46
- /**
47
- * setting the hour and minute so we can compare with closedDays
48
- */
49
- closedDays.forEach(closed => {
50
- const closedDay = moment(closed.date);
51
- closedDay.set('hour', hour);
52
- closedDay.set('minute', minute);
53
- if (endDateTZ.startOf('day').isSame(closedDay, 'day')) {
54
- endDateTZ.add(1, 'days');
55
- }
56
- });
57
41
  if (hour !== undefined) endDateTZ.set('hour', hour);
58
42
  if (minute !== undefined) endDateTZ.set('minute', minute);
43
+ endDateTZ.set('second', 0);
44
+
45
+ const isSkipDay = endDateIsoWeekDay => {
46
+ if (skipDays.length >= 7) return false;
47
+ return skipDays.includes(endDateIsoWeekDay);
48
+ };
49
+
50
+ const isClosedDay = endDate =>
51
+ closedDays.some(
52
+ closedDate => endDate.format('YYYY-MM-DD') === closedDate.date
53
+ );
54
+
55
+ let addedDays = 0;
56
+
57
+ while (
58
+ addedDays < addDays ||
59
+ isSkipDay(endDateTZ.isoWeekday()) ||
60
+ isClosedDay(endDateTZ)
61
+ ) {
62
+ if (!isSkipDay(endDateTZ.isoWeekday()) && !isClosedDay(endDateTZ)) {
63
+ addedDays += 1;
64
+ }
65
+ endDateTZ.add(1, 'days');
66
+ }
59
67
 
60
68
  return moment.utc(endDateTZ).format();
61
69
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darkpos/pricing",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
4
4
  "description": "Pricing calculator",
5
5
  "author": "Dark POS",
6
6
  "license": "ISC",
@@ -21,6 +21,7 @@
21
21
  "test:getModifierTags": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/item/getModifierTags.test.js",
22
22
  "test:createIndirectModifier": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/modifier/createIndirectModifier.test.js",
23
23
  "test:conditionsNotMet": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/conditionsNotMet.test.js",
24
+ "test:pickEndDate": "jest --runInBand --detectOpenHandles --logHeapUsage --forceExit ./__TEST__/order/pickEndDate.test.js",
24
25
  "lint": "eslint --quiet lib/"
25
26
  },
26
27
  "publishConfig": {
@@ -44,5 +45,5 @@
44
45
  "supertest": "^6.2.3",
45
46
  "supervisor": "^0.12.0"
46
47
  },
47
- "gitHead": "4341a5b5f555e6148a83ba4dba73bb7c908a02f5"
48
+ "gitHead": "d7719dca121087e9f10644bcef8ccd76e1271104"
48
49
  }