@darkpos/pricing 1.0.145 → 1.0.146

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.
@@ -201,6 +201,75 @@ describe('addItem function', () => {
201
201
  expect(updatedOrder.items[0].modifiers).toHaveLength(2); // Added item should have modifiers
202
202
  });
203
203
 
204
+ test('should return original order when item serial is duplicated', () => {
205
+ const { addItem } = pricingService.order;
206
+
207
+ const order = {
208
+ items: [
209
+ {
210
+ _id: 'existing-item',
211
+ itemId: '111',
212
+ quantity: 1,
213
+ price: 100,
214
+ serial: 'ABC-123',
215
+ modifiers: [],
216
+ },
217
+ ],
218
+ };
219
+
220
+ const item = {
221
+ _id: 'new-item',
222
+ itemId: '222',
223
+ quantity: 1,
224
+ price: 50,
225
+ serial: ' abc-123 ',
226
+ modifiers: [],
227
+ };
228
+
229
+ const result = addItem({
230
+ order,
231
+ item,
232
+ itemIndex: -1,
233
+ overridenQuantity: -1,
234
+ });
235
+
236
+ expect(result).toBe(order);
237
+ });
238
+
239
+ test('should return original order when autoBarcode serial is duplicated', () => {
240
+ const { addItem } = pricingService.order;
241
+
242
+ const order = {
243
+ items: [
244
+ {
245
+ _id: 'existing-item',
246
+ itemId: '111',
247
+ quantity: 1,
248
+ price: 100,
249
+ serial: 'ABC-123',
250
+ modifiers: [],
251
+ },
252
+ ],
253
+ };
254
+
255
+ const item = {
256
+ _id: 'new-item',
257
+ itemId: '222',
258
+ quantity: 1,
259
+ price: 50,
260
+ modifiers: [],
261
+ };
262
+
263
+ const result = addItem({
264
+ order,
265
+ item,
266
+ itemIndex: 1,
267
+ autoBarcode: 'ABC-123',
268
+ });
269
+
270
+ expect(result).toBe(order);
271
+ });
272
+
204
273
  test('Add Related Item', () => {
205
274
  const { addItem } = pricingService.order;
206
275
 
@@ -1,7 +1,7 @@
1
1
  const moment = require('moment-timezone');
2
2
  const usePricing = require('../../lib/index');
3
3
 
4
- const getDefaultSettings = schedules => ({
4
+ const getDefaultSettings = (schedules, readyDateCapacityDays = []) => ({
5
5
  store: {
6
6
  _settings: {
7
7
  schedule: {
@@ -24,6 +24,9 @@ const getDefaultSettings = schedules => ({
24
24
  cutHour: null,
25
25
  },
26
26
  ],
27
+ readyDateCapacity: {
28
+ days: readyDateCapacityDays,
29
+ },
27
30
  },
28
31
  },
29
32
  },
@@ -115,7 +118,7 @@ describe('pickEndDate function', () => {
115
118
  recommended: 'nothing_recommended',
116
119
  };
117
120
 
118
- const now = moment().tz('America/New_York');
121
+ const now = moment('2024-08-25T15:00:00Z').tz('America/New_York');
119
122
 
120
123
  jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
121
124
  const pricingServiceTest = usePricing(getDefaultSettings([schedule]));
@@ -299,4 +302,207 @@ describe('pickEndDate function', () => {
299
302
 
300
303
  expect(result).toBe('2025-05-15T22:00:00Z');
301
304
  });
305
+
306
+ test('pickEndDate - skips day when maxOrders capacity is reached', () => {
307
+ const schedule = {
308
+ addDays: 0,
309
+ readyHour: { hour: 17, minute: 0 },
310
+ skipDays: [],
311
+ cutHour: { hour: 16, minute: 0 },
312
+ cutDay: 1,
313
+ };
314
+
315
+ const pricingService = usePricing(
316
+ getDefaultSettings([schedule], [{ day: 2, maxOrders: 1 }])
317
+ );
318
+
319
+ const now = moment('2025-05-13T15:00:00Z').tz('America/New_York');
320
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
321
+
322
+ const result = pricingService.store.pickEndDate(
323
+ undefined,
324
+ undefined,
325
+ undefined,
326
+ [
327
+ {
328
+ date: '2025-05-13',
329
+ totalOrders: 1,
330
+ totalItems: 0,
331
+ },
332
+ ]
333
+ );
334
+
335
+ expect(result).toBe('2025-05-14T21:00:00Z');
336
+ });
337
+
338
+ test('pickEndDate - skips day when maxItems capacity is reached', () => {
339
+ const schedule = {
340
+ addDays: 0,
341
+ readyHour: { hour: 17, minute: 0 },
342
+ skipDays: [],
343
+ cutHour: { hour: 16, minute: 0 },
344
+ cutDay: 1,
345
+ };
346
+
347
+ const pricingService = usePricing(
348
+ getDefaultSettings([schedule], [{ day: 2, maxItems: 1 }])
349
+ );
350
+
351
+ const now = moment('2025-05-13T15:00:00Z').tz('America/New_York');
352
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
353
+
354
+ const result = pricingService.store.pickEndDate(
355
+ undefined,
356
+ undefined,
357
+ undefined,
358
+ [
359
+ {
360
+ date: '2025-05-13',
361
+ totalOrders: 0,
362
+ totalItems: 1,
363
+ },
364
+ ]
365
+ );
366
+
367
+ expect(result).toBe('2025-05-14T21:00:00Z');
368
+ });
369
+
370
+ test('pickEndDate - moves to next available day when capacity is full', () => {
371
+ const schedule = {
372
+ addDays: 2,
373
+ readyHour: { hour: 17, minute: 0 },
374
+ skipDays: [],
375
+ cutHour: { hour: 16, minute: 0 },
376
+ cutDay: 1,
377
+ dayOfWeek: [1, 2, 3, 4, 5],
378
+ };
379
+
380
+ const pricingService = usePricing(
381
+ getDefaultSettings([schedule], [{ day: 6, maxOrders: 1 }])
382
+ );
383
+
384
+ const now = moment('2026-02-26T15:00:00Z').tz('America/New_York');
385
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
386
+
387
+ const result = pricingService.store.pickEndDate(
388
+ undefined,
389
+ undefined,
390
+ undefined,
391
+ [
392
+ {
393
+ date: '2026-02-28',
394
+ totalOrders: 1,
395
+ totalItems: 0,
396
+ },
397
+ ]
398
+ );
399
+
400
+ expect(result).toBe('2026-03-01T22:00:00Z');
401
+ });
402
+
403
+ test('pickEndDate - skips closed day after capacity overflow', () => {
404
+ const schedule = {
405
+ addDays: 2,
406
+ readyHour: { hour: 17, minute: 0 },
407
+ skipDays: null,
408
+ cutHour: { hour: 10, minute: 0 },
409
+ cutDay: 1,
410
+ };
411
+
412
+ const pricingService = usePricing({
413
+ store: {
414
+ _settings: {
415
+ schedule: {
416
+ closed: [{ date: '2026-03-01' }],
417
+ },
418
+ order: {
419
+ schedules: [schedule],
420
+ readyDateCapacity: {
421
+ days: [
422
+ { day: 6, maxOrders: 2, maxItems: 10 },
423
+ { day: 1, maxOrders: 10, maxItems: 10 },
424
+ ],
425
+ },
426
+ },
427
+ },
428
+ },
429
+ });
430
+
431
+ const now = moment('2026-02-25T16:04:51Z').tz('America/New_York');
432
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
433
+
434
+ const result = pricingService.store.pickEndDate(
435
+ undefined,
436
+ undefined,
437
+ undefined,
438
+ [
439
+ { date: '2026-02-26', totalOrders: 4, totalItems: 5 },
440
+ { date: '2026-02-27', totalOrders: 1, totalItems: 1 },
441
+ { date: '2026-02-28', totalOrders: 2, totalItems: 2 },
442
+ ]
443
+ );
444
+
445
+ expect(result).toBe('2026-03-02T22:00:00Z');
446
+ });
447
+
448
+ test('pickEndDate - skips multiple consecutive capacity-full days', () => {
449
+ const schedule = {
450
+ addDays: 0,
451
+ readyHour: { hour: 17, minute: 0 },
452
+ skipDays: [],
453
+ cutHour: { hour: 16, minute: 0 },
454
+ cutDay: 1,
455
+ };
456
+
457
+ const pricingService = usePricing(
458
+ getDefaultSettings(
459
+ [schedule],
460
+ [
461
+ { day: 2, maxOrders: 1 },
462
+ { day: 3, maxOrders: 1 },
463
+ ]
464
+ )
465
+ );
466
+
467
+ const now = moment('2025-05-13T15:00:00Z').tz('America/New_York');
468
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
469
+
470
+ const result = pricingService.store.pickEndDate(
471
+ undefined,
472
+ undefined,
473
+ undefined,
474
+ [
475
+ { date: '2025-05-13', totalOrders: 1, totalItems: 0 },
476
+ { date: '2025-05-14', totalOrders: 1, totalItems: 0 },
477
+ ]
478
+ );
479
+
480
+ expect(result).toBe('2025-05-15T21:00:00Z');
481
+ });
482
+
483
+ test('pickEndDate - returns base date when no capacity counts are provided', () => {
484
+ const schedule = {
485
+ addDays: 0,
486
+ readyHour: { hour: 17, minute: 0 },
487
+ skipDays: [],
488
+ cutHour: { hour: 16, minute: 0 },
489
+ cutDay: 1,
490
+ };
491
+
492
+ const pricingService = usePricing(
493
+ getDefaultSettings([schedule], [{ day: 2, maxOrders: 1 }])
494
+ );
495
+
496
+ const now = moment('2025-05-13T15:00:00Z').tz('America/New_York');
497
+ jest.spyOn(moment, 'now').mockImplementation(() => now.valueOf());
498
+
499
+ const result = pricingService.store.pickEndDate(
500
+ undefined,
501
+ undefined,
502
+ undefined,
503
+ []
504
+ );
505
+
506
+ expect(result).toBe('2025-05-13T21:00:00Z');
507
+ });
302
508
  });
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ MAX_ADD_DAYS: 365,
3
+ };
@@ -1,7 +1,9 @@
1
1
  const Status = require('./Status');
2
2
  const Modifier = require('./Modifier');
3
+ const Store = require('./Store');
3
4
 
4
5
  module.exports = {
5
6
  Status,
6
7
  Modifier,
8
+ Store,
7
9
  };
@@ -227,6 +227,8 @@ module.exports = ({ actions, itemActions, modifierActions, settings, _ }) => {
227
227
  originalItem: item,
228
228
  });
229
229
 
230
+ if (actions.hasSerial({ order, item: orderItem })) return orderProp;
231
+
230
232
  const params = addOrderItem({
231
233
  order,
232
234
  item: orderItem,
@@ -0,0 +1,7 @@
1
+ module.exports = ({ _, settings }) =>
2
+ function getClosedDays() {
3
+ const schedule = _.get(settings, 'schedule', {});
4
+ const { closed = [] } = schedule;
5
+ if (!Array.isArray(closed)) return [];
6
+ return closed;
7
+ };
@@ -0,0 +1,4 @@
1
+ module.exports = ({ _, settings }) =>
2
+ function getReadyDateCapacityDays() {
3
+ return _.get(settings, 'order.readyDateCapacity.days', []);
4
+ };
@@ -0,0 +1,33 @@
1
+ module.exports = ({ _, moment }) =>
2
+ function getReadyDateCountsByDate(counts = []) {
3
+ const countsByDate = new Map();
4
+
5
+ if (!Array.isArray(counts) || !counts.length) return countsByDate;
6
+
7
+ counts.forEach(dayCount => {
8
+ const rawDate = _.get(dayCount, 'date');
9
+ if (!rawDate) return;
10
+
11
+ const utcDateKey = moment.utc(rawDate).format('YYYY-MM-DD');
12
+ if (!utcDateKey || utcDateKey === 'Invalid date') return;
13
+
14
+ const currentValue = countsByDate.get(utcDateKey) || {
15
+ totalOrders: 0,
16
+ totalItems: 0,
17
+ };
18
+
19
+ const nextOrders = Number(_.get(dayCount, 'totalOrders'));
20
+ const nextItems = Number(_.get(dayCount, 'totalItems'));
21
+
22
+ countsByDate.set(utcDateKey, {
23
+ totalOrders:
24
+ currentValue.totalOrders +
25
+ (Number.isFinite(nextOrders) && nextOrders > 0 ? nextOrders : 0),
26
+ totalItems:
27
+ currentValue.totalItems +
28
+ (Number.isFinite(nextItems) && nextItems > 0 ? nextItems : 0),
29
+ });
30
+ });
31
+
32
+ return countsByDate;
33
+ };
@@ -0,0 +1,61 @@
1
+ module.exports = ({ _, moment, settings, actions }) =>
2
+ function getSchedule(schedules, isoWeekday, fromDate) {
3
+ const timezone = actions.getStoreTimezone();
4
+ let todayTZ = moment().tz(timezone);
5
+
6
+ if (fromDate) {
7
+ todayTZ = moment(fromDate).tz(timezone);
8
+ }
9
+
10
+ const day = isoWeekday || todayTZ.isoWeekday(); // monday 1 - sunday 7
11
+
12
+ let activeSchedules = _.get(settings, 'order.schedules', []).filter(
13
+ item => !item.departments || !item.departments.length
14
+ );
15
+
16
+ if (schedules && schedules.length) {
17
+ activeSchedules = schedules;
18
+ }
19
+
20
+ if (!activeSchedules.length) {
21
+ return {
22
+ todayTZ,
23
+ skipDays: [],
24
+ cutDay: 0,
25
+ };
26
+ }
27
+
28
+ const schedule = activeSchedules.find(item => {
29
+ const { dayOfWeek } = item || {};
30
+ if (!dayOfWeek || !dayOfWeek.length) return true;
31
+ return dayOfWeek.includes(day);
32
+ });
33
+
34
+ if (schedule) {
35
+ return {
36
+ ...schedule,
37
+ todayTZ,
38
+ };
39
+ }
40
+
41
+ for (let offset = 1; offset <= 7; offset += 1) {
42
+ const nextIsoWeekday = ((day - 1 + offset) % 7) + 1;
43
+ const nextSchedule = activeSchedules.find(item => {
44
+ const { dayOfWeek } = item || {};
45
+ return Array.isArray(dayOfWeek) && dayOfWeek.includes(nextIsoWeekday);
46
+ });
47
+
48
+ if (nextSchedule) {
49
+ return {
50
+ ...nextSchedule,
51
+ todayTZ: todayTZ.clone().add(offset, 'days'),
52
+ };
53
+ }
54
+ }
55
+
56
+ return {
57
+ todayTZ,
58
+ skipDays: [],
59
+ cutDay: 0,
60
+ };
61
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = ({ _, settings }) =>
2
+ function getStoreTimezone() {
3
+ return (
4
+ _.get(settings, 'localization.timezone', 'America/New_York') ||
5
+ 'America/New_York'
6
+ );
7
+ };
@@ -0,0 +1,8 @@
1
+ module.exports = ({ _, actions }) =>
2
+ function hasReadyDateCapacitySettings(days = []) {
3
+ return days.some(
4
+ day =>
5
+ actions.normalizeLimit(_.get(day, 'maxOrders')) > 0 ||
6
+ actions.normalizeLimit(_.get(day, 'maxItems')) > 0
7
+ );
8
+ };
@@ -1,6 +1,14 @@
1
1
  //
2
2
  const getScheduleByCustomer = require('./getScheduleByCustomer');
3
3
  const isNeareastMultiple = require('./isNeareastMultiple');
4
+ const getClosedDays = require('./getClosedDays');
5
+ const getReadyDateCapacityDays = require('./getReadyDateCapacityDays');
6
+ const getReadyDateCountsByDate = require('./getReadyDateCountsByDate');
7
+ const getSchedule = require('./getSchedule');
8
+ const getStoreTimezone = require('./getStoreTimezone');
9
+ const hasReadyDateCapacitySettings = require('./hasReadyDateCapacitySettings');
10
+ const normalizeLimit = require('./normalizeLimit');
11
+ const pickBaseEndDate = require('./pickBaseEndDate');
4
12
  const pickEndDate = require('./pickEndDate');
5
13
  const pickEndDateByCustomer = require('./pickEndDateByCustomer');
6
14
 
@@ -13,8 +21,16 @@ const storeActions = (deps = {}) => {
13
21
  };
14
22
 
15
23
  const freezedActions = Object.freeze({
24
+ getClosedDays: getClosedDays(innerDeps),
25
+ getReadyDateCapacityDays: getReadyDateCapacityDays(innerDeps),
26
+ getReadyDateCountsByDate: getReadyDateCountsByDate(innerDeps),
16
27
  getScheduleByCustomer: getScheduleByCustomer(innerDeps),
28
+ getSchedule: getSchedule(innerDeps),
29
+ getStoreTimezone: getStoreTimezone(innerDeps),
30
+ hasReadyDateCapacitySettings: hasReadyDateCapacitySettings(innerDeps),
17
31
  isNeareastMultiple: isNeareastMultiple(innerDeps),
32
+ normalizeLimit: normalizeLimit(innerDeps),
33
+ pickBaseEndDate: pickBaseEndDate(innerDeps),
18
34
  pickEndDate: pickEndDate(innerDeps),
19
35
  pickEndDateByCustomer: pickEndDateByCustomer(innerDeps),
20
36
  });
@@ -0,0 +1,5 @@
1
+ module.exports = () =>
2
+ function normalizeLimit(value) {
3
+ const parsedValue = Math.trunc(Number(value) || 0);
4
+ return parsedValue > 0 ? parsedValue : 0;
5
+ };
@@ -0,0 +1,71 @@
1
+ const { MAX_ADD_DAYS } = require('../constants/Store');
2
+
3
+ module.exports = ({ moment, actions }) =>
4
+ function pickBaseEndDate(schedules, isoWeekday, fromDate) {
5
+ const {
6
+ addDays: addDaysParam,
7
+ readyHour,
8
+ cutHour,
9
+ cutDay,
10
+ skipDays,
11
+ todayTZ,
12
+ } = actions.getSchedule(schedules, isoWeekday, fromDate);
13
+
14
+ let endDateTZ = todayTZ.clone();
15
+ const closedDays = actions.getClosedDays();
16
+ const todayHours = todayTZ.get('hours');
17
+ const todayMinutes = todayTZ.get('minutes');
18
+
19
+ let addDays = 0;
20
+
21
+ if (
22
+ !fromDate &&
23
+ typeof addDaysParam === 'number' &&
24
+ addDaysParam <= MAX_ADD_DAYS
25
+ ) {
26
+ addDays = addDaysParam;
27
+ }
28
+
29
+ if (
30
+ (cutHour && todayHours > cutHour.hour) ||
31
+ (cutHour && todayHours >= cutHour.hour && todayMinutes > cutHour.minute)
32
+ ) {
33
+ endDateTZ = endDateTZ.add(cutDay, 'days');
34
+ }
35
+
36
+ if (readyHour && readyHour.hour !== undefined)
37
+ endDateTZ.set('hour', readyHour.hour);
38
+ if (readyHour && readyHour.minute !== undefined)
39
+ endDateTZ.set('minute', readyHour.minute);
40
+
41
+ endDateTZ.set('second', 0);
42
+
43
+ const isSkipDay = endDateIsoWeekDay => {
44
+ if (skipDays && skipDays.length >= 7) return false;
45
+
46
+ return skipDays && skipDays.includes(endDateIsoWeekDay);
47
+ };
48
+
49
+ const isClosedDay = endDate =>
50
+ closedDays.some(
51
+ closedDate => endDate.format('YYYY-MM-DD') === closedDate.date
52
+ );
53
+
54
+ let addedDays = 0;
55
+
56
+ while (
57
+ addedDays < addDays ||
58
+ isSkipDay(endDateTZ.isoWeekday()) ||
59
+ isClosedDay(endDateTZ)
60
+ ) {
61
+ if (
62
+ endDateTZ.isSame(todayTZ, 'day') ||
63
+ (!isSkipDay(endDateTZ.isoWeekday()) && !isClosedDay(endDateTZ))
64
+ ) {
65
+ addedDays += 1;
66
+ }
67
+ endDateTZ.add(1, 'days');
68
+ }
69
+
70
+ return moment.utc(endDateTZ).format();
71
+ };
@@ -1,108 +1,82 @@
1
- module.exports = ({ settings, _, moment }) => {
2
- const timezone =
3
- _.get(settings, 'localization.timezone', 'America/New_York') ||
4
- 'America/New_York';
5
-
6
- const getSchedule = (schedules, isoWeekday) => {
7
- const todayTZ = moment().tz(timezone);
8
- const day = isoWeekday || todayTZ.isoWeekday(); // monday 1 - sunday 7
9
- const _schedules =
10
- schedules && schedules.length
11
- ? schedules
12
- : _.get(settings, 'order.schedules', []).filter(
13
- item => !item.departments || !item.departments.length
14
- );
15
-
16
- if (!_schedules.length) {
17
- return {
18
- todayTZ,
19
- skipDays: [],
20
- cutDay: 0,
21
- };
22
- }
1
+ const { MAX_ADD_DAYS } = require('../constants/Store');
2
+
3
+ module.exports = ({ _, moment, actions }) =>
4
+ function pickEndDate(
5
+ schedules,
6
+ isoWeekday,
7
+ fromDate,
8
+ readyDateCapacityCounts = []
9
+ ) {
10
+ const timezone = actions.getStoreTimezone();
11
+
12
+ let candidateDate = actions.pickBaseEndDate(
13
+ schedules,
14
+ isoWeekday,
15
+ fromDate
16
+ );
17
+
18
+ const readyDateCapacityDays = actions.getReadyDateCapacityDays();
19
+ if (!actions.hasReadyDateCapacitySettings(readyDateCapacityDays))
20
+ return candidateDate;
21
+
22
+ const countsByDate = actions.getReadyDateCountsByDate(
23
+ readyDateCapacityCounts
24
+ );
25
+ if (!countsByDate.size) return candidateDate;
26
+
27
+ const inspectedDays = new Set();
28
+
29
+ for (let index = 0; index < MAX_ADD_DAYS; index += 1) {
30
+ const candidateMomentTZ = moment(candidateDate).tz(timezone);
31
+ const candidateLocalDateKey = candidateMomentTZ.format('YYYY-MM-DD');
32
+
33
+ if (inspectedDays.has(candidateLocalDateKey)) break;
34
+ inspectedDays.add(candidateLocalDateKey);
35
+
36
+ const capacitySettingsForDay = readyDateCapacityDays.find(
37
+ day => Number(_.get(day, 'day')) === candidateMomentTZ.isoWeekday()
38
+ );
23
39
 
24
- const schedule = _schedules.find(item => {
25
- const { dayOfWeek } = item || {};
26
- if (!dayOfWeek || !dayOfWeek.length) return true;
27
- return dayOfWeek.includes(day);
28
- });
40
+ if (!capacitySettingsForDay) return candidateDate;
29
41
 
30
- return {
31
- ...schedule,
32
- todayTZ,
33
- };
34
- };
42
+ const maxOrders = actions.normalizeLimit(
43
+ _.get(capacitySettingsForDay, 'maxOrders')
44
+ );
45
+ const maxItems = actions.normalizeLimit(
46
+ _.get(capacitySettingsForDay, 'maxItems')
47
+ );
35
48
 
36
- const getClosedDays = () => {
37
- const schedule = _.get(settings, 'schedule', {});
38
- const { closed = [] } = schedule;
39
- if (!Array.isArray(closed)) return [];
40
- return closed;
41
- };
49
+ if (maxOrders <= 0 && maxItems <= 0) return candidateDate;
42
50
 
43
- const MAX_ADD_DAYS = 365;
44
-
45
- return function pickEndDate(schedules, isoWeekday) {
46
- const {
47
- addDays: addDaysParam,
48
- readyHour,
49
- cutHour,
50
- cutDay,
51
- skipDays,
52
- todayTZ,
53
- } = getSchedule(schedules, isoWeekday);
54
-
55
- let endDateTZ = todayTZ.clone();
56
- const closedDays = getClosedDays();
57
- const todayHours = todayTZ.get('hours');
58
- const todayMinutes = todayTZ.get('minutes');
59
-
60
- const addDays =
61
- typeof addDaysParam !== 'number' || addDaysParam > MAX_ADD_DAYS
62
- ? 0
63
- : addDaysParam;
64
-
65
- if (
66
- (cutHour && todayHours > cutHour.hour) ||
67
- (cutHour && todayHours >= cutHour.hour && todayMinutes > cutHour.minute)
68
- ) {
69
- endDateTZ = endDateTZ.add(cutDay, 'days');
70
- }
51
+ const candidateUTCDateKey = moment
52
+ .utc(candidateDate)
53
+ .format('YYYY-MM-DD');
54
+ const dayCount = countsByDate.get(candidateUTCDateKey) || {
55
+ totalOrders: 0,
56
+ totalItems: 0,
57
+ };
71
58
 
72
- if (readyHour && readyHour.hour !== undefined)
73
- endDateTZ.set('hour', readyHour.hour);
74
- if (readyHour && readyHour.minute !== undefined)
75
- endDateTZ.set('minute', readyHour.minute);
59
+ const isUnavailable =
60
+ (maxOrders > 0 && dayCount.totalOrders >= maxOrders) ||
61
+ (maxItems > 0 && dayCount.totalItems >= maxItems);
76
62
 
77
- endDateTZ.set('second', 0);
63
+ if (!isUnavailable) return candidateDate;
78
64
 
79
- const isSkipDay = endDateIsoWeekDay => {
80
- if (skipDays && skipDays.length >= 7) return false;
65
+ const nextDateSeed = candidateMomentTZ
66
+ .clone()
67
+ .add(1, 'day')
68
+ .startOf('day')
69
+ .toISOString();
81
70
 
82
- return skipDays && skipDays.includes(endDateIsoWeekDay);
83
- };
71
+ const { readyHour, cutHour, cutDay, skipDays } =
72
+ actions.getSchedule(schedules, undefined, candidateDate) || {};
84
73
 
85
- const isClosedDay = endDate =>
86
- closedDays.some(
87
- closedDate => endDate.format('YYYY-MM-DD') === closedDate.date
74
+ candidateDate = actions.pickBaseEndDate(
75
+ [{ readyHour, cutHour, cutDay, skipDays }],
76
+ undefined,
77
+ nextDateSeed
88
78
  );
89
-
90
- let addedDays = 0;
91
-
92
- while (
93
- addedDays < addDays ||
94
- isSkipDay(endDateTZ.isoWeekday()) ||
95
- isClosedDay(endDateTZ)
96
- ) {
97
- if (
98
- endDateTZ.isSame(todayTZ, 'day') ||
99
- (!isSkipDay(endDateTZ.isoWeekday()) && !isClosedDay(endDateTZ))
100
- ) {
101
- addedDays += 1;
102
- }
103
- endDateTZ.add(1, 'days');
104
79
  }
105
80
 
106
- return moment.utc(endDateTZ).format();
81
+ return candidateDate;
107
82
  };
108
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darkpos/pricing",
3
- "version": "1.0.145",
3
+ "version": "1.0.146",
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": "eb6adf31020d7ca3b57f6e6b1bfa20c4e0289ca0"
57
+ "gitHead": "50cda463bcaad6e5aa03bded3329269a9ac99398"
58
58
  }