From 4c823f92ca0aca1119e08cc856408470ce79dc9a Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 21 Aug 2026 11:14:18 +0000 Subject: [PATCH] Fix lunch-break guard being skipped on same-day bookings getAvailableTimes() overloaded $dayStartTime: it starts as the worker's real shift start, but for same-day requests it is overwritten with the earliest bookable slot (next 15-min block + 1 hour). The lunch-break setup further down still read it as the shift start, so $shiftSeconds measured the *remaining* day instead of the whole shift. Once that fell under 6 hours, $lunchRequired went false and the guard was skipped entirely -- every free slot was offered, including ones that leave no room for a lunch break. Observed on prod on 2026-08-21: at 12:17 the cutoff pushed the start to 13:30, so Kateryna's 10:00-18:00 shift measured 4.5h and a 13:30-15:30 booking was accepted even though it consumed the last possible lunch slot. booking_process() re-validates through the same function, so the server-side check agreed. Capture the real shift start in $shiftStartTime before the cutoff runs, and use it for both $shiftSeconds and the computeLunchBreak() call. The latter also fixes a second symptom of the same overload: the lunch window was being clamped to the cutoff rather than to the actual shift. Verified end-to-end against pages/ajax on test: with the bug a slot that destroys the last lunch break is offered, with the fix it is withheld. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01VZv7QGLyRYwdD8NyimYbQQ --- application/models/Service_model.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/application/models/Service_model.php b/application/models/Service_model.php index 639fc1e..9672d99 100755 --- a/application/models/Service_model.php +++ b/application/models/Service_model.php @@ -622,6 +622,10 @@ class Service_model extends CI_Model { $finishTime = new DateTime($selectedDate . ' ' . $schedule->end_time, new DateTimeZone('Europe/Oslo')); } + // A műszak valódi kezdete - $dayStartTime-ot a mai napra alább felülírjuk a legkorábban + // foglalható időponttal, az ebédszünet számítása viszont a tényleges műszakkal dolgozik. + $shiftStartTime = clone $dayStartTime; + // --- ÚJ: ma foglalva csak (következő 15 perces blokk + 1 óra) UTÁN legyen időpont --- if ($selectedDate == date('Y-m-d')) { // használd a helyi (Oslo) időt, ne az esetleges UTC defaultot @@ -648,7 +652,7 @@ class Service_model extends CI_Model { // --- Lunch break setup --- // Pre-fetch all bookings for the day so we can do hypothetical checks per slot $workerRow = $this->db->query("SELECT lunch_window_start, lunch_window_end, lunch_preferred_time FROM workers WHERE worker_id = ? LIMIT 1", array($worker_id))->row(); - $shiftSeconds = $finishTime->getTimestamp() - $dayStartTime->getTimestamp(); + $shiftSeconds = $finishTime->getTimestamp() - $shiftStartTime->getTimestamp(); $lunchRequired = $workerRow && $workerRow->lunch_window_start && $workerRow->lunch_window_end && $shiftSeconds >= 6 * 3600; $allBookings = []; @@ -705,7 +709,7 @@ class Service_model extends CI_Model { ]]); $canStillBreak = $this->computeLunchBreak( $workerRow->lunch_window_start, $workerRow->lunch_window_end, - $selectedDate, $hypo, $finishTime, $dayStartTime, + $selectedDate, $hypo, $finishTime, $shiftStartTime, $workerRow->lunch_preferred_time ) !== null; if (!$canStillBreak) continue; // booking this slot would eliminate the only break opportunity