@happychef/algorithm 1.2.13 → 1.2.15
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/.github/workflows/ci-cd.yml +0 -154
- package/BRANCH_PROTECTION_SETUP.md +167 -167
- package/README.md +144 -144
- package/__tests__/filters.test.js +276 -276
- package/__tests__/isDateAvailable.test.js +175 -175
- package/__tests__/isTimeAvailable.test.js +168 -168
- package/__tests__/restaurantData.test.js +422 -422
- package/__tests__/tableHelpers.test.js +247 -247
- package/assignTables.js +33 -13
- package/changes/2026/January/PR11_add__change.md +20 -0
- package/getAvailableTimeblocks.js +2 -2
- package/isDateAvailable.js +2 -2
- package/isDateAvailableWithTableCheck.js +5 -4
- package/jest.config.js +23 -23
- package/package.json +1 -1
- package/processing/timeblocksAvailable.js +2 -2
- package/reservation_data/counter.js +11 -1
- package/simulateTableAssignment.js +35 -18
- package/test-detailed-filter.js +100 -100
- package/test-lunch-debug.js +110 -110
- package/test-max-arrivals-filter.js +79 -79
- package/test-timezone-debug.js +47 -47
package/jest.config.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
testEnvironment: 'node',
|
|
3
|
-
coverageDirectory: 'coverage',
|
|
4
|
-
collectCoverageFrom: [
|
|
5
|
-
'**/*.js',
|
|
6
|
-
'!**/node_modules/**',
|
|
7
|
-
'!**/coverage/**',
|
|
8
|
-
'!jest.config.js',
|
|
9
|
-
'!test.js',
|
|
10
|
-
'!test-*.js',
|
|
11
|
-
'!**/__tests__/**'
|
|
12
|
-
],
|
|
13
|
-
testMatch: [
|
|
14
|
-
'**/__tests__/**/*.test.js'
|
|
15
|
-
],
|
|
16
|
-
testPathIgnorePatterns: [
|
|
17
|
-
'/node_modules/',
|
|
18
|
-
'/test\\.js$',
|
|
19
|
-
'/test-.*\\.js$'
|
|
20
|
-
],
|
|
21
|
-
verbose: true,
|
|
22
|
-
testTimeout: 10000
|
|
23
|
-
};
|
|
1
|
+
module.exports = {
|
|
2
|
+
testEnvironment: 'node',
|
|
3
|
+
coverageDirectory: 'coverage',
|
|
4
|
+
collectCoverageFrom: [
|
|
5
|
+
'**/*.js',
|
|
6
|
+
'!**/node_modules/**',
|
|
7
|
+
'!**/coverage/**',
|
|
8
|
+
'!jest.config.js',
|
|
9
|
+
'!test.js',
|
|
10
|
+
'!test-*.js',
|
|
11
|
+
'!**/__tests__/**'
|
|
12
|
+
],
|
|
13
|
+
testMatch: [
|
|
14
|
+
'**/__tests__/**/*.test.js'
|
|
15
|
+
],
|
|
16
|
+
testPathIgnorePatterns: [
|
|
17
|
+
'/node_modules/',
|
|
18
|
+
'/test\\.js$',
|
|
19
|
+
'/test-.*\\.js$'
|
|
20
|
+
],
|
|
21
|
+
verbose: true,
|
|
22
|
+
testTimeout: 10000
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -89,8 +89,8 @@ function fitsWithinMeal(data, dateStr, startTimeStr, duurReservatie) {
|
|
|
89
89
|
return startTime >= mealStartTime && startTime + duurReservatie <= mealEndTime;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
function timeblocksAvailable(data, dateStr, reservations, guests, blockedSlots = [], giftcard = null, isAdmin = false) {
|
|
93
|
-
const duurReservatie = getDuurReservatie(data);
|
|
92
|
+
function timeblocksAvailable(data, dateStr, reservations, guests, blockedSlots = [], giftcard = null, isAdmin = false, duration = null) {
|
|
93
|
+
const duurReservatie = duration && duration > 0 ? duration : getDuurReservatie(data);
|
|
94
94
|
const intervalReservatie = getInterval(data);
|
|
95
95
|
|
|
96
96
|
// Slots needed
|
|
@@ -48,7 +48,17 @@ function parseTime(timeStr) {
|
|
|
48
48
|
|
|
49
49
|
const startTime = parseTime(reservation.time);
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// Use reservation specific duration if available, else default
|
|
52
|
+
let rDuration = duurReservatie;
|
|
53
|
+
if (reservation.duration) {
|
|
54
|
+
const rawDur = reservation.duration.$numberInt ?? reservation.duration;
|
|
55
|
+
const parsed = parseInt(rawDur, 10);
|
|
56
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
57
|
+
rDuration = parsed;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const endTime = startTime + rDuration;
|
|
52
62
|
// Check if the target time is within the reservation time range
|
|
53
63
|
// Start time is inclusive, end time is exclusive
|
|
54
64
|
if (targetTime >= startTime && targetTime < endTime) {
|
|
@@ -322,7 +322,7 @@ function findMultiTableCombination(tables, guestsTotal, startIndex, currentSet,
|
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
function assignTablesForGivenTime(restaurantData, date, time, guests, tableOccupiedSlots, selectedZitplaats = null) {
|
|
325
|
+
function assignTablesForGivenTime(restaurantData, date, time, guests, tableOccupiedSlots, selectedZitplaats = null, duration = null) {
|
|
326
326
|
console.log(`[assignTablesForGivenTime] Processing ${date} ${time} for ${guests} guests`);
|
|
327
327
|
|
|
328
328
|
// Clear cache if it gets too large (prevent memory leaks)
|
|
@@ -341,6 +341,11 @@ function assignTablesForGivenTime(restaurantData, date, time, guests, tableOccup
|
|
|
341
341
|
duurReservatie = safeParseInt(generalSettings.duurReservatie, 120);
|
|
342
342
|
intervalReservatie = safeParseInt(generalSettings.intervalReservatie, 15);
|
|
343
343
|
|
|
344
|
+
// Use passed duration if available, otherwise default
|
|
345
|
+
if (duration && duration > 0) {
|
|
346
|
+
duurReservatie = duration;
|
|
347
|
+
}
|
|
348
|
+
|
|
344
349
|
console.log(`[assignTablesForGivenTime] Using duration: ${duurReservatie}min, interval: ${intervalReservatie}min`);
|
|
345
350
|
|
|
346
351
|
if (intervalReservatie <= 0) {
|
|
@@ -411,8 +416,8 @@ function assignTablesForGivenTime(restaurantData, date, time, guests, tableOccup
|
|
|
411
416
|
return best.tables.map(t => t.tableNumber);
|
|
412
417
|
}
|
|
413
418
|
|
|
414
|
-
function isTimeAvailableSync(restaurantData, date, time, guests, reservations, selectedZitplaats = null) {
|
|
415
|
-
console.log(`\n[isTimeAvailableSync] Checking ${date} ${time} for ${guests} guests`);
|
|
419
|
+
function isTimeAvailableSync(restaurantData, date, time, guests, reservations, selectedZitplaats = null, duration = null) {
|
|
420
|
+
console.log(`\n[isTimeAvailableSync] Checking ${date} ${time} for ${guests} guests (duration: ${duration || 'default'})`);
|
|
416
421
|
|
|
417
422
|
if (guests < 0) {
|
|
418
423
|
console.log(`[isTimeAvailableSync] Detected negative guest count (${guests}), adjusting to default of 2`);
|
|
@@ -445,19 +450,22 @@ function isTimeAvailableSync(restaurantData, date, time, guests, reservations, s
|
|
|
445
450
|
}
|
|
446
451
|
|
|
447
452
|
const generalSettings = restaurantData["general-settings"] || {};
|
|
448
|
-
let
|
|
453
|
+
let defaultDuurReservatie = 120; // Default: 2 hours in minutes
|
|
449
454
|
let intervalReservatie = 15; // Default: 15 minute intervals
|
|
450
|
-
|
|
455
|
+
defaultDuurReservatie = safeParseInt(generalSettings.duurReservatie, 120);
|
|
451
456
|
intervalReservatie = safeParseInt(generalSettings.intervalReservatie, 15);
|
|
452
457
|
|
|
453
|
-
|
|
458
|
+
// Use passed duration or default
|
|
459
|
+
const currentDuurReservatie = duration && duration > 0 ? duration : defaultDuurReservatie;
|
|
460
|
+
|
|
461
|
+
console.log(`[isTimeAvailableSync] Using duration: ${currentDuurReservatie}min (default: ${defaultDuurReservatie}), interval: ${intervalReservatie}min`);
|
|
454
462
|
|
|
455
463
|
if (intervalReservatie <= 0) {
|
|
456
464
|
console.error(`[isTimeAvailableSync] Invalid interval settings for ${date} ${time}`);
|
|
457
465
|
return false;
|
|
458
466
|
}
|
|
459
467
|
|
|
460
|
-
const requiredSlots = computeRequiredSlots(time,
|
|
468
|
+
const requiredSlots = computeRequiredSlots(time, currentDuurReservatie, intervalReservatie);
|
|
461
469
|
if (!requiredSlots || requiredSlots.length === 0) {
|
|
462
470
|
console.error(`[isTimeAvailableSync] Could not compute required slots for ${date} ${time}`);
|
|
463
471
|
return false; // Cannot proceed if slots are invalid
|
|
@@ -477,8 +485,15 @@ function isTimeAvailableSync(restaurantData, date, time, guests, reservations, s
|
|
|
477
485
|
console.log(`[isTimeAvailableSync] Processing ${reservationsForDate.length} existing reservations on ${date}`);
|
|
478
486
|
|
|
479
487
|
for (const r of reservationsForDate) {
|
|
488
|
+
// Calculate duration once per reservation
|
|
489
|
+
const rDuration = safeParseInt(r.duration, defaultDuurReservatie);
|
|
490
|
+
|
|
491
|
+
console.log(`[DEBUG] Reservation ${r.time} (${r.firstName}): Duration=${rDuration}, Tables raw=${JSON.stringify(r.tables)}`);
|
|
492
|
+
|
|
480
493
|
// NEW: Try to get actual table assignment first
|
|
481
494
|
const actualTables = getActualTableAssignment(r);
|
|
495
|
+
console.log(`[DEBUG] Reservation ${r.time}: actualTables detected = ${JSON.stringify(actualTables)}`);
|
|
496
|
+
|
|
482
497
|
let assignedTables = [];
|
|
483
498
|
|
|
484
499
|
if (actualTables.length > 0) {
|
|
@@ -486,14 +501,17 @@ function isTimeAvailableSync(restaurantData, date, time, guests, reservations, s
|
|
|
486
501
|
assignedTables = actualTables;
|
|
487
502
|
console.log(`[isTimeAvailableSync] Using actual table assignment for reservation: ${assignedTables.join(', ')}`);
|
|
488
503
|
} else {
|
|
489
|
-
//
|
|
504
|
+
// ... simulation log ...
|
|
490
505
|
console.log(`[isTimeAvailableSync] No actual table data, simulating assignment for reservation`);
|
|
491
|
-
assignedTables = assignTablesForGivenTime(restaurantData, r.date, r.time, r.guests, tableOccupiedSlots);
|
|
506
|
+
assignedTables = assignTablesForGivenTime(restaurantData, r.date, r.time, r.guests, tableOccupiedSlots, null, rDuration); // Simulation
|
|
492
507
|
}
|
|
493
508
|
|
|
494
509
|
// Update the occupancy map based on the actual or simulated assignment
|
|
495
510
|
if (assignedTables.length > 0) {
|
|
496
|
-
|
|
511
|
+
// Use reservation specific duration if available
|
|
512
|
+
const rSlots = computeRequiredSlots(r.time, rDuration, intervalReservatie);
|
|
513
|
+
console.log(`[DEBUG] Reservation ${r.time}: Occupying slots=${rSlots.join(',')} on tables=${assignedTables.join(',')}`);
|
|
514
|
+
|
|
497
515
|
if (!rSlots || rSlots.length === 0) continue; // Skip if slots invalid
|
|
498
516
|
|
|
499
517
|
assignedTables.forEach(tableNumber => {
|
|
@@ -502,8 +520,6 @@ function isTimeAvailableSync(restaurantData, date, time, guests, reservations, s
|
|
|
502
520
|
}
|
|
503
521
|
rSlots.forEach(slot => tableOccupiedSlots[tableNumber].add(slot));
|
|
504
522
|
});
|
|
505
|
-
|
|
506
|
-
console.log(`[isTimeAvailableSync] Marked tables ${assignedTables.join(', ')} as occupied for time ${r.time}`);
|
|
507
523
|
}
|
|
508
524
|
}
|
|
509
525
|
|
|
@@ -566,7 +582,7 @@ function isTimeAvailableSync(restaurantData, date, time, guests, reservations, s
|
|
|
566
582
|
}
|
|
567
583
|
}
|
|
568
584
|
|
|
569
|
-
function filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats = null) {
|
|
585
|
+
function filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats = null, duration = null) {
|
|
570
586
|
console.log(`[filterTimeblocksByTableAvailability] Filtering timeblocks for ${date} with ${guests} guests`);
|
|
571
587
|
|
|
572
588
|
if (guests < 0) {
|
|
@@ -590,7 +606,7 @@ function filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, g
|
|
|
590
606
|
let unavailableCount = 0;
|
|
591
607
|
|
|
592
608
|
for (const time in timeblocks) {
|
|
593
|
-
if (isTimeAvailableSync(restaurantData, date, time, guests, reservations, selectedZitplaats)) {
|
|
609
|
+
if (isTimeAvailableSync(restaurantData, date, time, guests, reservations, selectedZitplaats, duration)) {
|
|
594
610
|
filteredTimeblocks[time] = timeblocks[time];
|
|
595
611
|
availableCount++;
|
|
596
612
|
} else {
|
|
@@ -606,8 +622,8 @@ function filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, g
|
|
|
606
622
|
return filteredTimeblocks;
|
|
607
623
|
}
|
|
608
624
|
|
|
609
|
-
function getAvailableTimeblocksWithTableCheck(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats = null) {
|
|
610
|
-
return filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats);
|
|
625
|
+
function getAvailableTimeblocksWithTableCheck(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats = null, duration = null) {
|
|
626
|
+
return filterTimeblocksByTableAvailability(restaurantData, date, timeblocks, guests, reservations, selectedZitplaats, duration);
|
|
611
627
|
}
|
|
612
628
|
|
|
613
629
|
function getAvailableTablesForTime(restaurantData, date, time, guests, reservations, selectedZitplaats = null) {
|
|
@@ -656,17 +672,18 @@ function getAvailableTablesForTime(restaurantData, date, time, guests, reservati
|
|
|
656
672
|
|
|
657
673
|
console.log(`[getAvailableTablesForTime] Building occupancy map (Processing ${reservationsForDate.length} existing reservations)`);
|
|
658
674
|
for (const r of reservationsForDate) {
|
|
675
|
+
const rDuration = safeParseInt(r.duration, duurReservatie);
|
|
659
676
|
const actualTables = getActualTableAssignment(r);
|
|
660
677
|
let assignedTables = [];
|
|
661
678
|
|
|
662
679
|
if (actualTables.length > 0) {
|
|
663
680
|
assignedTables = actualTables;
|
|
664
681
|
} else {
|
|
665
|
-
assignedTables = assignTablesForGivenTime(restaurantData, r.date, r.time, r.guests, tableOccupiedSlots, null);
|
|
682
|
+
assignedTables = assignTablesForGivenTime(restaurantData, r.date, r.time, r.guests, tableOccupiedSlots, null, rDuration);
|
|
666
683
|
}
|
|
667
684
|
|
|
668
685
|
if (assignedTables.length > 0) {
|
|
669
|
-
const rSlots = computeRequiredSlots(r.time,
|
|
686
|
+
const rSlots = computeRequiredSlots(r.time, rDuration, intervalReservatie);
|
|
670
687
|
if (!rSlots || rSlots.length === 0) continue;
|
|
671
688
|
assignedTables.forEach(tableNumber => {
|
|
672
689
|
if (!tableOccupiedSlots[tableNumber]) {
|
package/test-detailed-filter.js
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
// Detailed filter test - simulating getAvailableTimeblocks logic
|
|
2
|
-
const { timeblocksAvailable } = require('./processing/timeblocksAvailable');
|
|
3
|
-
const { getMealTypeByTime, parseTime } = require('./tableHelpers');
|
|
4
|
-
|
|
5
|
-
const restaurantData = {
|
|
6
|
-
"_id": "demo",
|
|
7
|
-
"openinghours-lunch": {
|
|
8
|
-
"schemeSettings": {
|
|
9
|
-
"Monday": {
|
|
10
|
-
"enabled": true,
|
|
11
|
-
"startTime": "14:15",
|
|
12
|
-
"endTime": "15:00",
|
|
13
|
-
"maxCapacityEnabled": true,
|
|
14
|
-
"maxCapacity": "10"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"general-settings": {
|
|
19
|
-
"zitplaatsen": 13,
|
|
20
|
-
"uurOpVoorhand": 0,
|
|
21
|
-
"dagenInToekomst": 365,
|
|
22
|
-
"intervalReservatie": 30,
|
|
23
|
-
"duurReservatie": 60,
|
|
24
|
-
"ontbijtStop": "",
|
|
25
|
-
"lunchStop": "",
|
|
26
|
-
"dinerStop": ""
|
|
27
|
-
},
|
|
28
|
-
"max-arrivals-lunch": {
|
|
29
|
-
"14:15": 10,
|
|
30
|
-
"14:30": 10,
|
|
31
|
-
"14:45": 10
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const testDate = "2025-12-08";
|
|
36
|
-
const guests = 2;
|
|
37
|
-
const reservations = [];
|
|
38
|
-
const uurOpVoorhand = 0;
|
|
39
|
-
const isAdmin = false;
|
|
40
|
-
|
|
41
|
-
console.log('=== DETAILED FILTER TEST ===\n');
|
|
42
|
-
|
|
43
|
-
// Get timeblocks
|
|
44
|
-
const availableTimeblocks = timeblocksAvailable(restaurantData, testDate, reservations, guests, [], null, isAdmin);
|
|
45
|
-
console.log('Initial timeblocks:', Object.keys(availableTimeblocks));
|
|
46
|
-
|
|
47
|
-
// Simulate the time filtering logic
|
|
48
|
-
const now = new Date();
|
|
49
|
-
const [year, month, day] = testDate.split('-').map(Number);
|
|
50
|
-
const targetDateInTimeZone = new Date(year, month - 1, day);
|
|
51
|
-
const isToday = now.toDateString() === targetDateInTimeZone.toDateString();
|
|
52
|
-
|
|
53
|
-
console.log('\nTime filter check:');
|
|
54
|
-
console.log('Is today:', isToday);
|
|
55
|
-
console.log('uurOpVoorhand:', uurOpVoorhand);
|
|
56
|
-
console.log('Current time:', now.toString());
|
|
57
|
-
|
|
58
|
-
if (isToday && uurOpVoorhand >= 0) {
|
|
59
|
-
const cutoffTime = new Date(now.getTime());
|
|
60
|
-
cutoffTime.setHours(cutoffTime.getHours() + uurOpVoorhand);
|
|
61
|
-
console.log('Cutoff time:', cutoffTime.toString());
|
|
62
|
-
|
|
63
|
-
for (const key of Object.keys(availableTimeblocks)) {
|
|
64
|
-
const timeStr = key;
|
|
65
|
-
const [hours, minutes] = timeStr.split(':').map(Number);
|
|
66
|
-
const timeBlockDateTime = new Date(year, month - 1, day, hours, minutes);
|
|
67
|
-
|
|
68
|
-
console.log(`\n Checking ${timeStr}:`);
|
|
69
|
-
console.log(` timeBlockDateTime: ${timeBlockDateTime.toString()}`);
|
|
70
|
-
console.log(` cutoffTime: ${cutoffTime.toString()}`);
|
|
71
|
-
console.log(` timeBlockDateTime < cutoffTime: ${timeBlockDateTime < cutoffTime}`);
|
|
72
|
-
console.log(` Would be deleted: ${timeBlockDateTime < cutoffTime ? 'YES' : 'NO'}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Check lunchStop filter
|
|
77
|
-
console.log('\n\nLunch Stop filter check:');
|
|
78
|
-
const settings = restaurantData['general-settings'];
|
|
79
|
-
const lunchStop = settings.lunchStop || null;
|
|
80
|
-
console.log('lunchStop value:', JSON.stringify(lunchStop));
|
|
81
|
-
console.log('lunchStop truthy:', !!lunchStop);
|
|
82
|
-
|
|
83
|
-
if (lunchStop) {
|
|
84
|
-
console.log('LunchStop is set, would apply filter');
|
|
85
|
-
for (const time in availableTimeblocks) {
|
|
86
|
-
const mealType = getMealTypeByTime(time);
|
|
87
|
-
console.log(` ${time}: mealType=${mealType}`);
|
|
88
|
-
|
|
89
|
-
if (mealType === 'lunch') {
|
|
90
|
-
const timeMinutes = parseTime(time);
|
|
91
|
-
const stopMinutes = parseTime(lunchStop);
|
|
92
|
-
console.log(` timeMinutes=${timeMinutes}, stopMinutes=${stopMinutes}`);
|
|
93
|
-
console.log(` Would remove: ${timeMinutes >= stopMinutes ? 'YES' : 'NO'}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
console.log('LunchStop is NOT set, no filter applied');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
console.log('\n=== END TEST ===');
|
|
1
|
+
// Detailed filter test - simulating getAvailableTimeblocks logic
|
|
2
|
+
const { timeblocksAvailable } = require('./processing/timeblocksAvailable');
|
|
3
|
+
const { getMealTypeByTime, parseTime } = require('./tableHelpers');
|
|
4
|
+
|
|
5
|
+
const restaurantData = {
|
|
6
|
+
"_id": "demo",
|
|
7
|
+
"openinghours-lunch": {
|
|
8
|
+
"schemeSettings": {
|
|
9
|
+
"Monday": {
|
|
10
|
+
"enabled": true,
|
|
11
|
+
"startTime": "14:15",
|
|
12
|
+
"endTime": "15:00",
|
|
13
|
+
"maxCapacityEnabled": true,
|
|
14
|
+
"maxCapacity": "10"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"general-settings": {
|
|
19
|
+
"zitplaatsen": 13,
|
|
20
|
+
"uurOpVoorhand": 0,
|
|
21
|
+
"dagenInToekomst": 365,
|
|
22
|
+
"intervalReservatie": 30,
|
|
23
|
+
"duurReservatie": 60,
|
|
24
|
+
"ontbijtStop": "",
|
|
25
|
+
"lunchStop": "",
|
|
26
|
+
"dinerStop": ""
|
|
27
|
+
},
|
|
28
|
+
"max-arrivals-lunch": {
|
|
29
|
+
"14:15": 10,
|
|
30
|
+
"14:30": 10,
|
|
31
|
+
"14:45": 10
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const testDate = "2025-12-08";
|
|
36
|
+
const guests = 2;
|
|
37
|
+
const reservations = [];
|
|
38
|
+
const uurOpVoorhand = 0;
|
|
39
|
+
const isAdmin = false;
|
|
40
|
+
|
|
41
|
+
console.log('=== DETAILED FILTER TEST ===\n');
|
|
42
|
+
|
|
43
|
+
// Get timeblocks
|
|
44
|
+
const availableTimeblocks = timeblocksAvailable(restaurantData, testDate, reservations, guests, [], null, isAdmin);
|
|
45
|
+
console.log('Initial timeblocks:', Object.keys(availableTimeblocks));
|
|
46
|
+
|
|
47
|
+
// Simulate the time filtering logic
|
|
48
|
+
const now = new Date();
|
|
49
|
+
const [year, month, day] = testDate.split('-').map(Number);
|
|
50
|
+
const targetDateInTimeZone = new Date(year, month - 1, day);
|
|
51
|
+
const isToday = now.toDateString() === targetDateInTimeZone.toDateString();
|
|
52
|
+
|
|
53
|
+
console.log('\nTime filter check:');
|
|
54
|
+
console.log('Is today:', isToday);
|
|
55
|
+
console.log('uurOpVoorhand:', uurOpVoorhand);
|
|
56
|
+
console.log('Current time:', now.toString());
|
|
57
|
+
|
|
58
|
+
if (isToday && uurOpVoorhand >= 0) {
|
|
59
|
+
const cutoffTime = new Date(now.getTime());
|
|
60
|
+
cutoffTime.setHours(cutoffTime.getHours() + uurOpVoorhand);
|
|
61
|
+
console.log('Cutoff time:', cutoffTime.toString());
|
|
62
|
+
|
|
63
|
+
for (const key of Object.keys(availableTimeblocks)) {
|
|
64
|
+
const timeStr = key;
|
|
65
|
+
const [hours, minutes] = timeStr.split(':').map(Number);
|
|
66
|
+
const timeBlockDateTime = new Date(year, month - 1, day, hours, minutes);
|
|
67
|
+
|
|
68
|
+
console.log(`\n Checking ${timeStr}:`);
|
|
69
|
+
console.log(` timeBlockDateTime: ${timeBlockDateTime.toString()}`);
|
|
70
|
+
console.log(` cutoffTime: ${cutoffTime.toString()}`);
|
|
71
|
+
console.log(` timeBlockDateTime < cutoffTime: ${timeBlockDateTime < cutoffTime}`);
|
|
72
|
+
console.log(` Would be deleted: ${timeBlockDateTime < cutoffTime ? 'YES' : 'NO'}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check lunchStop filter
|
|
77
|
+
console.log('\n\nLunch Stop filter check:');
|
|
78
|
+
const settings = restaurantData['general-settings'];
|
|
79
|
+
const lunchStop = settings.lunchStop || null;
|
|
80
|
+
console.log('lunchStop value:', JSON.stringify(lunchStop));
|
|
81
|
+
console.log('lunchStop truthy:', !!lunchStop);
|
|
82
|
+
|
|
83
|
+
if (lunchStop) {
|
|
84
|
+
console.log('LunchStop is set, would apply filter');
|
|
85
|
+
for (const time in availableTimeblocks) {
|
|
86
|
+
const mealType = getMealTypeByTime(time);
|
|
87
|
+
console.log(` ${time}: mealType=${mealType}`);
|
|
88
|
+
|
|
89
|
+
if (mealType === 'lunch') {
|
|
90
|
+
const timeMinutes = parseTime(time);
|
|
91
|
+
const stopMinutes = parseTime(lunchStop);
|
|
92
|
+
console.log(` timeMinutes=${timeMinutes}, stopMinutes=${stopMinutes}`);
|
|
93
|
+
console.log(` Would remove: ${timeMinutes >= stopMinutes ? 'YES' : 'NO'}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
console.log('LunchStop is NOT set, no filter applied');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log('\n=== END TEST ===');
|