@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.
- package/__TEST__/modifier.test.js +58 -0
- package/__TEST__/order/pickEndDate.test.js +62 -48
- package/__TEST__/order/unvoid.test.js +32 -0
- package/lib/order/addItemModifier.js +1 -1
- package/lib/order/index.js +2 -0
- package/lib/order/unvoid.js +11 -0
- package/lib/store/pickEndDate.js +36 -28
- package/package.json +3 -2
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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:
|
|
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(
|
|
52
|
+
expect(result).toBe('2024-08-28T18:00:00Z'); // 2024-08-28 14:00:00 EDT
|
|
56
53
|
});
|
|
57
54
|
|
|
58
|
-
test('
|
|
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
|
-
|
|
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(
|
|
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
|
|
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(
|
|
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
|
-
|
|
230
|
+
modifierActions.isQuantityMultiplier(modifier)
|
|
231
231
|
) {
|
|
232
232
|
if (onError)
|
|
233
233
|
onError('modifier.has.reached.the.maximum.amount.of.applies');
|
package/lib/order/index.js
CHANGED
|
@@ -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),
|
package/lib/store/pickEndDate.js
CHANGED
|
@@ -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
|
|
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
|
|
15
|
+
addDays: addDaysParam,
|
|
17
16
|
hour,
|
|
18
17
|
minute,
|
|
19
18
|
skipDays = [],
|
|
20
19
|
cutHour,
|
|
21
|
-
cutDay =
|
|
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');
|
|
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.
|
|
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": "
|
|
48
|
+
"gitHead": "d7719dca121087e9f10644bcef8ccd76e1271104"
|
|
48
49
|
}
|