load->database(); $query = $this->db->query('INSERT INTO services ( service_type, service_category_no, service_category_en, service_category_hu, service_name_no, service_name_en, service_name_hu, service_description_no, service_description_en, service_description_hu, service_price, service_time, service_category_id, is_enabled ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', array( $serviceArray['service_type'], $serviceArray['service_category_no'], $serviceArray['service_category_en'], $serviceArray['service_category_hu'], $serviceArray['service_name_no'], $serviceArray['service_name_en'], $serviceArray['service_name_hu'], $serviceArray['service_description_no'], $serviceArray['service_description_en'], $serviceArray['service_description_hu'], $serviceArray['service_price'], $serviceArray['service_time'], $serviceArray['service_category_id'], $serviceArray['is_enabled'] )); } public function createServiceCategory($serviceCategoryArray){ $this->load->database(); $query = $this->db->query('INSERT INTO service_categories ( serv_cat_slug, serv_cat_name ) VALUES(?, ?)', array( $serviceCategoryArray['serv_cat_slug'], $serviceCategoryArray['serv_cat_name'] )); } public function updateService($service_id, $serviceArray){ $this->load->database(); $this->db->where('service_id', $service_id); $this->db->update('services', $serviceArray); } public function updateServiceCategory($service_category_id, $serviceCategoryArray){ $this->load->database(); $this->db->where('service_category_id', $service_category_id); $this->db->update('service_categories', $serviceCategoryArray); } public function createWorker($workerArray){ $this->load->database(); $query = $this->db->query('INSERT INTO workers ( worker_name, worker_profile_img, worker_info, is_beauty, is_barber, service_category_id ) VALUES(?, ?, ?, ?, ?, ?)', array( $workerArray['worker_name'], $workerArray['worker_profile_img'], $workerArray['worker_info'], $workerArray['is_beauty'], $workerArray['is_barber'], $workerArray['service_category_id'] )); } public function updateWorker($worker_id, $workerArray){ $this->load->database(); $this->db->where('worker_id', $worker_id); $this->db->update('workers', $workerArray); } public function updateBooking($booking_id, $bookingArray){ $this->load->database(); $this->db->where('booking_id', $booking_id); $this->db->update('bookings', $bookingArray); } public function getAllServiceByServiceType($service_type, $lang){ $this->load->database(); $query = $this->db->query('SELECT * FROM services JOIN service_categories ON services.service_category_id = service_categories.service_category_id WHERE service_type = ? AND services.is_enabled = "1" AND services.is_deleted != "1" ORDER BY service_id ASC', array($service_type)); $serviceArray = array(); if($query->num_rows() > 0){ foreach($query->result() as $resultItem){ $service_category = ''; $service_name = ''; $service_description = ''; switch($lang){ case 'no': $service_category = $resultItem->service_category_no; $service_name = $resultItem->service_name_no; $service_description = $resultItem->service_description_no; break; case 'en': $service_category = $resultItem->service_category_en; $service_name = $resultItem->service_name_en; $service_description = $resultItem->service_description_en; break; case 'hu': $service_category = $resultItem->service_category_hu; $service_name = $resultItem->service_name_hu; $service_description = $resultItem->service_description_hu; break; } $resultItemTmp = array( 'service_id' => $resultItem->service_id, 'service_type' => $resultItem->service_type, 'service_category' => $service_category, 'service_name' => $service_name, 'service_description' => $service_description, 'service_price' => $resultItem->service_price, 'service_time' => $resultItem->service_time, 'serv_cat_slug' => $resultItem->serv_cat_slug, 'service_category_id' => $resultItem->service_category_id ); $serviceArray[] = (object)$resultItemTmp; } } return $serviceArray; } public function getServiceById($service_id){ $this->load->database(); $query = $this->db->query('SELECT * FROM services WHERE service_id = ? LIMIT 1', array($service_id)); if($query->num_rows() > 0){ return $query->result()[0]; } else{ return 0; } } public function getServiceCategoryById($service_category_id){ $this->load->database(); $query = $this->db->query('SELECT * FROM service_categories WHERE service_category_id = ? LIMIT 1', array($service_category_id)); if($query->num_rows() > 0){ return $query->result()[0]; } else{ return 0; } } public function getAllServices(){ $this->load->database(); $query = $this->db->query('SELECT * FROM services JOIN service_categories ON services.service_category_id = service_categories.service_category_id WHERE services.is_deleted != "1" ORDER BY service_type ASC, service_name_hu ASC;'); if($query->num_rows() > 0){ return $query->result(); } else{ return 0; } } public function getAllServiceCategories(){ $this->load->database(); $query = $this->db->query('SELECT * FROM service_categories WHERE is_deleted != "1" ORDER BY service_category_id;'); if($query->num_rows() > 0){ return $query->result(); } else{ return 0; } } public function getAvailableServices(){ $this->load->database(); $query = $this->db->query('SELECT * FROM services WHERE is_enabled = "1" AND is_deleted != "1" ORDER BY service_name_hu ASC;'); if($query->num_rows() > 0){ $serviceArray = array(); foreach($query->result() as $resultItem){ $serviceTmp = array( 'service_name' => $resultItem->service_name_hu.' ('.$resultItem->service_type.')', 'service_id' => $resultItem->service_id ); $serviceArray[] = $serviceTmp; } return $serviceArray; } } public function getAllWorkers(){ $this->load->database(); $query = $this->db->query('SELECT * FROM workers JOIN service_categories ON workers.service_category_id = service_categories.service_category_id WHERE workers.is_deleted != "1" ORDER BY worker_name ASC;'); return $query->result(); } public function getWorkersByCategorySlug($serv_cat_slug){ $this->load->database(); $query = $this->db->query('SELECT * FROM workers JOIN service_categories ON workers.service_category_id = service_categories.service_category_id WHERE workers.is_deleted != "1" AND serv_cat_slug = ? ORDER BY worker_name ASC', array($serv_cat_slug)); return $query->result(); } public function getActiveWorkers($subpage = ''){ $this->load->database(); $subpageString = ''; if($subpage == 'beauty'){ $subpageString = ' AND is_beauty = "1"'; } else if($subpage == 'barber'){ $subpageString = ' AND is_barber = "1"'; } else{ $subpageString = ''; } $query = $this->db->query('SELECT * FROM workers WHERE is_active = "1" '.$subpageString.' AND is_deleted != "1" ORDER BY worker_name ASC;'); return $query->result(); } public function deleteBooking($booking_id){ $this->load->database(); $query = $this->db->query('DELETE FROM bookings WHERE booking_id = ?', array($booking_id)); } public function getAllBookings(){ $this->load->database(); $this->load->model('Service_model'); $query = $this->db->query('SELECT * FROM bookings JOIN workers ON bookings.worker_id = workers.worker_id ORDER BY booking_date DESC, booking_start_time ASC;'); if($query->num_rows() > 0){ $resultsArray = array(); foreach($query->result() as $resultItem){ $resultTmp = (array)$resultItem; if($resultTmp['service_ids'] != ''){ $servicesArray = unserialize($resultTmp['service_ids']); if(is_array($servicesArray)){ $services = array(); foreach($servicesArray as $servicesArrayItem){ $selectedService = $this->Service_model->getServiceById($servicesArrayItem); $services[] = (object)array( 'service_type' => $selectedService->service_type, 'service_name' => $selectedService->service_name_hu, 'service_price' => $selectedService->service_price, 'service_time' => $selectedService->service_time ); } $resultTmp['services'] = $services; } else{ $resultTmp['services'] = array(); } } else{ $resultTmp['services'] = array(); } $resultsArray[] = (object)$resultTmp; } return $resultsArray; } else{ return 0; } } public function getActualBookings(){ $this->load->database(); $this->load->model('Service_model'); $query = $this->db->query('SELECT * FROM bookings JOIN workers ON bookings.worker_id = workers.worker_id WHERE booking_date >= CURDATE() ORDER BY booking_date DESC, booking_start_time ASC;'); if($query->num_rows() > 0){ $resultsArray = array(); foreach($query->result() as $resultItem){ $resultTmp = (array)$resultItem; if($resultTmp['service_ids'] != ''){ $servicesArray = unserialize($resultTmp['service_ids']); if(is_array($servicesArray)){ $services = array(); foreach($servicesArray as $servicesArrayItem){ $selectedService = $this->Service_model->getServiceById($servicesArrayItem); $services[] = (object)array( 'service_type' => $selectedService->service_type, 'service_name' => $selectedService->service_name_hu, 'service_price' => $selectedService->service_price, 'service_time' => $selectedService->service_time ); } $resultTmp['services'] = $services; } else{ $resultTmp['services'] = array(); } } else{ $resultTmp['services'] = array(); } $resultsArray[] = (object)$resultTmp; } return $resultsArray; } else{ return 0; } } public function getActualBookingsByWorkerID($workerID){ $this->load->database(); $this->load->model('Service_model'); $query = $this->db->query('SELECT * FROM bookings JOIN workers ON bookings.worker_id = workers.worker_id WHERE booking_date >= CURDATE() AND bookings.worker_id = ? ORDER BY booking_date DESC, booking_start_time ASC', array($workerID)); if($query->num_rows() > 0){ $resultsArray = array(); foreach($query->result() as $resultItem){ $resultTmp = (array)$resultItem; if($resultTmp['service_ids'] != ''){ $servicesArray = unserialize($resultTmp['service_ids']); if(is_array($servicesArray)){ $services = array(); foreach($servicesArray as $servicesArrayItem){ $selectedService = $this->Service_model->getServiceById($servicesArrayItem); $services[] = (object)array( 'service_type' => $selectedService->service_type, 'service_name' => $selectedService->service_name_hu, 'service_price' => $selectedService->service_price, 'service_time' => $selectedService->service_time ); } $resultTmp['services'] = $services; } else{ $resultTmp['services'] = array(); } } else{ $resultTmp['services'] = array(); } $resultsArray[] = (object)$resultTmp; } return $resultsArray; } else{ return 0; } } public function getBookingById($booking_id){ $this->load->database(); $this->load->model('Service_model'); $query = $this->db->query('SELECT * FROM bookings WHERE booking_id = ? LIMIT 1', array($booking_id)); if($query->num_rows() > 0){ return $query->result()[0]; } else{ return 0; } } public function getWorkerById($worker_id){ $this->load->database(); $query = $this->db->query('SELECT * FROM workers WHERE worker_id = ? LIMIT 1', array($worker_id)); if($query->num_rows() > 0){ return $query->result()[0]; } else{ return 0; } } public function getAvailableTimes($worker_id, $selectedDate, $servicelength, $exclude_booking_id = null) { $this->load->database(); // múltbeli napra ne lehessen foglalni if (strtotime($selectedDate) < strtotime(date('Y-m-d'))) { return []; } // max 3 hónappal előre $today = new DateTime(); $maxDate = (clone $today)->modify('+3 months'); $selected = new DateTime($selectedDate); if ($selected > $maxDate) { return []; } $ts = strtotime($selectedDate); $debugDate = date('Y-m-d (w)', $ts) . ' - ' . date('l', $ts); log_message('error', "📅 DEBUG DATE CHECK for '{$selectedDate}': {$debugDate}"); log_message('error', "⏱ Timezone: " . date_default_timezone_get()); $serviceLengthTime = strtotime($servicelength); $availableTimeArray = []; // --- Override ellenőrzés --- $overrideQuery = $this->db->query(" SELECT * FROM worker_schedule_overrides WHERE worker_id = ? AND date = ? LIMIT 1 ", array($worker_id, $selectedDate)); if ($overrideQuery->num_rows() > 0) { $override = $overrideQuery->row(); if ($override->is_day_off) return []; $dayStartTime = new DateTime($selectedDate.' '.$override->start_time, new DateTimeZone('Europe/Oslo')); $finishTime = new DateTime($selectedDate.' '.$override->end_time, new DateTimeZone('Europe/Oslo')); } else { $weekday = date('w', strtotime($selectedDate)); // 0 = Sunday, 6 = Saturday $weekNumber = date('W', strtotime($selectedDate)); $isOddWeek = $weekNumber % 2 !== 0; $scheduleQuery = $this->db->query(" SELECT * FROM worker_schedule WHERE worker_id = ? AND weekday = ? AND ( is_alternate_week = 0 OR (is_alternate_week = 1 AND " . ($isOddWeek ? "1" : "0") . ") ) ", array($worker_id, $weekday)); if ($scheduleQuery->num_rows() == 0) { return []; } $schedule = $scheduleQuery->row(); $dayStartTime = new DateTime($selectedDate . ' ' . $schedule->start_time, new DateTimeZone('Europe/Oslo')); $finishTime = new DateTime($selectedDate . ' ' . $schedule->end_time, new DateTimeZone('Europe/Oslo')); } // --- Ú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 $now = new DateTime('now', new DateTimeZone('Europe/Oslo')); // kerekítés a következő 15 perces blokkra $minutes = (int)$now->format('i'); $mod = $minutes % 15; if ($mod !== 0) { $now->modify('+' . (15 - $mod) . ' minutes'); } // erre dobunk +1 órát $now->modify('+1 hour'); $now->setTime((int)$now->format('H'), (int)$now->format('i'), 0); // ha ez később van, mint a munkanap kezdete, toljuk fel a nap kezdetét if ($now > $dayStartTime) { $dayStartTime = clone $now; } log_message('error', '⏳ Min start (next 15min +1h, Europe/Oslo): ' . $dayStartTime->format('Y-m-d H:i:s')); } // --- 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(); $lunchRequired = $workerRow && $workerRow->lunch_window_start && $workerRow->lunch_window_end && $shiftSeconds >= 6 * 3600; $allBookings = []; if ($lunchRequired) { if ($exclude_booking_id !== null) { $allBookings = $this->db->query(" SELECT booking_start_time, booking_finish_time FROM bookings WHERE booking_date = ? AND worker_id = ? AND booking_id != ? ", array($selectedDate, $worker_id, $exclude_booking_id))->result(); } else { $allBookings = $this->db->query(" SELECT booking_start_time, booking_finish_time FROM bookings WHERE booking_date = ? AND worker_id = ? ", array($selectedDate, $worker_id))->result(); } } $interval = new DateInterval('PT15M'); list($h, $m) = explode(':', $servicelength); $serviceDuration = new DateInterval('PT' . (int)$h . 'H' . (int)$m . 'M'); for ($current = clone $dayStartTime; $current < $finishTime; $current->add($interval)) { $slotEnd = clone $current; $slotEnd->add($serviceDuration); if ($slotEnd > $finishTime) break; $startTimeStr = $current->format('H:i:s'); $endTimeStr = $slotEnd->format('H:i:s'); if ($exclude_booking_id !== null) { $bookingQuery = $this->db->query(" SELECT * FROM bookings WHERE booking_date = ? AND worker_id = ? AND booking_id != ? AND booking_start_time < ? AND booking_finish_time > ? ", array($selectedDate, $worker_id, $exclude_booking_id, $endTimeStr, $startTimeStr)); } else { $bookingQuery = $this->db->query(" SELECT * FROM bookings WHERE booking_date = ? AND worker_id = ? AND booking_start_time < ? AND booking_finish_time > ? ", array($selectedDate, $worker_id, $endTimeStr, $startTimeStr)); } if ($bookingQuery->num_rows() > 0) continue; // already booked if ($lunchRequired) { // Check: if we book this slot, can a 30-min lunch break still fit somewhere? $hypo = array_merge((array)$allBookings, [(object)[ 'booking_start_time' => $startTimeStr, 'booking_finish_time' => $endTimeStr, ]]); $canStillBreak = $this->computeLunchBreak( $workerRow->lunch_window_start, $workerRow->lunch_window_end, $selectedDate, $hypo, $finishTime, $dayStartTime, $workerRow->lunch_preferred_time ) !== null; if (!$canStillBreak) continue; // booking this slot would eliminate the only break opportunity } $availableTimeArray[] = $startTimeStr; log_message('debug', 'Selected Date: ' . $selectedDate); log_message('debug', 'Weekday: ' . (isset($weekday) ? $weekday : 'N/A')); log_message('debug', 'Worker ID: ' . $worker_id); } return $availableTimeArray; } public function createBooking($bookingArray){ $this->load->database(); $query = $this->db->query("INSERT INTO bookings ( guest_name, guest_email, guest_phone, worker_id, booking_date, booking_start_time, booking_finish_time, service_ids, guest_confirmed, guest_confirm_code, manage_token ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", array( $bookingArray['guest_name'], $bookingArray['guest_email'], $bookingArray['guest_phone'], $bookingArray['worker_id'], $bookingArray['booking_date'], $bookingArray['booking_start_time'], $bookingArray['booking_finish_time'], $bookingArray['service_ids'], $bookingArray['guest_confirmed'], $bookingArray['guest_confirm_code'], $bookingArray['manage_token'] )); } public function getBookingByToken($token){ $this->load->database(); $query = $this->db->query('SELECT * FROM bookings WHERE manage_token = ? LIMIT 1', array($token)); return $query->num_rows() > 0 ? $query->result()[0] : false; } public function getBookingBySlotAndGuest($worker_id, $booking_date, $booking_start_time, $guest_email){ $this->load->database(); $query = $this->db->query('SELECT * FROM bookings WHERE worker_id = ? AND booking_date = ? AND booking_start_time = ? AND guest_email = ? ORDER BY booking_id DESC LIMIT 1', array($worker_id, $booking_date, $booking_start_time, $guest_email)); return $query->num_rows() > 0 ? $query->row() : false; } public function updateBookingCalEvents($booking_id, $worker_event_id, $owner_event_id){ $this->load->database(); $this->db->query("UPDATE bookings SET gcal_event_id_worker = ?, gcal_event_id_owner = ? WHERE booking_id = ?", array($worker_event_id, $owner_event_id, $booking_id)); } public function getWorkerSchedule($worker_id) { return $this->db ->where('worker_id', $worker_id) ->order_by('weekday', 'ASC') ->get('worker_schedule') ->result(); } public function clearWorkerSchedule($worker_id) { $this->load->database(); $this->db->where('worker_id', $worker_id)->delete('worker_schedule'); } public function addWorkerSchedule($data) { $this->db->insert('worker_schedule', $data); } public function getAllWorkerSchedules() { $query = $this->db->query('SELECT * FROM worker_schedule'); return $query->result(); } public function getAllWorkerOverrides() { $query = $this->db->query('SELECT * FROM worker_schedule_overrides'); return $query->result(); } public function getWorkerScheduleOverrides() { $this->load->database(); $query = $this->db->query(" SELECT o.*, w.worker_name FROM worker_schedule_overrides o JOIN workers w ON o.worker_id = w.worker_id ORDER BY o.date DESC "); return $query->result(); } public function createWorkerScheduleOverride($override) { $this->db->insert('worker_schedule_overrides', $override); } public function getBookingsForWorkerDay($worker_id, $date) { $this->load->database(); return $this->db->query(" SELECT booking_start_time, booking_finish_time FROM bookings WHERE worker_id = ? AND booking_date = ? ORDER BY booking_start_time ", [$worker_id, $date])->result(); } public function getLunchGcalEventId($worker_id, $date) { $this->load->database(); $row = $this->db->query("SELECT gcal_event_id FROM worker_lunch_gcal_events WHERE worker_id = ? AND date = ? LIMIT 1", [$worker_id, $date])->row(); return $row ? $row->gcal_event_id : null; } public function upsertLunchGcalEventId($worker_id, $date, $event_id) { $this->load->database(); $existing = $this->getLunchGcalEventId($worker_id, $date); if ($existing) { $this->db->where('worker_id', $worker_id)->where('date', $date)->update('worker_lunch_gcal_events', ['gcal_event_id' => $event_id]); } else { $this->db->insert('worker_lunch_gcal_events', ['worker_id' => $worker_id, 'date' => $date, 'gcal_event_id' => $event_id]); } } public function deleteLunchGcalEventRecord($worker_id, $date) { $this->load->database(); $this->db->where('worker_id', $worker_id)->where('date', $date)->delete('worker_lunch_gcal_events'); } public function getBookingsForWorkerMonth($worker_id, $year, $month) { $this->load->database(); $yearMonth = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT); $query = $this->db->query(" SELECT booking_date, booking_start_time, booking_finish_time FROM bookings WHERE worker_id = ? AND DATE_FORMAT(booking_date,'%Y-%m') = ? ORDER BY booking_date, booking_start_time ", [$worker_id, $yearMonth]); $result = []; foreach ($query->result() as $row) { $result[$row->booking_date][] = $row; } return $result; } public function computeLunchBreak($winStart, $winEnd, $date, $dayBookings, $shiftEnd, $shiftStart = null, $preferredTime = null) { // Lunch break only applies for shifts of 6+ hours if ($shiftStart && ($shiftEnd->getTimestamp() - $shiftStart->getTimestamp()) < 6 * 3600) { return null; } $lunchDuration = new DateInterval('PT30M'); $lunchStep = new DateInterval('PT15M'); $tz = new DateTimeZone('Europe/Oslo'); $winStartDt = new DateTime($date . ' ' . $winStart, $tz); $winEndDt = new DateTime($date . ' ' . $winEnd, $tz); // Clamp window to actual shift hours if ($shiftStart && $winStartDt < $shiftStart) $winStartDt = clone $shiftStart; if ($winEndDt > $shiftEnd) $winEndDt = clone $shiftEnd; $scanEnd = (clone $winEndDt)->sub($lunchDuration); $isFree = function($candidate) use ($lunchDuration, $dayBookings, $date) { $tz = new DateTimeZone('Europe/Oslo'); $candEnd = (clone $candidate)->add($lunchDuration); foreach ($dayBookings as $bk) { $bkS = new DateTime($date . ' ' . $bk->booking_start_time, $tz); $bkE = new DateTime($date . ' ' . $bk->booking_finish_time, $tz); if ($bkS < $candEnd && $bkE > $candidate) return false; } return true; }; // Collect all free candidate slots within window $freeSlots = []; for ($c = clone $winStartDt; $c <= $scanEnd; $c->add($lunchStep)) { if ($isFree($c)) $freeSlots[] = clone $c; } if (!empty($freeSlots)) { // Pick the slot closest to preferred time (or start of window if no preference) $prefDt = $preferredTime ? new DateTime($date . ' ' . $preferredTime, new DateTimeZone('Europe/Oslo')) : clone $winStartDt; $best = null; $bestDiff = PHP_INT_MAX; foreach ($freeSlots as $slot) { $diff = abs($slot->getTimestamp() - $prefDt->getTimestamp()); if ($diff < $bestDiff) { $bestDiff = $diff; $best = $slot; } } $bestEnd = (clone $best)->add($lunchDuration); return ['start' => $best->format('H:i'), 'end' => $bestEnd->format('H:i')]; } return null; } public function getWorkerOverridesByMonth($worker_id, $year, $month) { $this->load->database(); $yearMonth = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT); $query = $this->db->query( "SELECT * FROM worker_schedule_overrides WHERE worker_id = ? AND DATE_FORMAT(date,'%Y-%m') = ?", [$worker_id, $yearMonth] ); $result = []; foreach ($query->result() as $row) { $result[$row->date] = $row; } return $result; } public function getWorkerScheduleOverrideByDate($worker_id, $date) { $this->load->database(); $this->db->where('worker_id', $worker_id); $this->db->where('date', $date); $this->db->limit(1); return $this->db->get('worker_schedule_overrides')->row(); } public function upsertWorkerScheduleOverride($worker_id, $date, $data) { $existing = $this->getWorkerScheduleOverrideByDate($worker_id, $date); if ($existing) { $this->db->where('worker_id', $worker_id); $this->db->where('date', $date); $this->db->update('worker_schedule_overrides', $data); } else { $data['worker_id'] = $worker_id; $data['date'] = $date; $this->db->insert('worker_schedule_overrides', $data); } } public function deleteWorkerScheduleOverrideByDate($worker_id, $date) { $this->load->database(); $this->db->where('worker_id', $worker_id); $this->db->where('date', $date); $this->db->delete('worker_schedule_overrides'); } public function getWorkerScheduleByDay($worker_id, $weekday) { $this->db->where('worker_id', $worker_id); $this->db->where('weekday', $weekday); $query = $this->db->get('worker_schedule'); return $query->row(); // null if no row } public function isEvenWeek($date) { return ((int)date('W', strtotime($date)) % 2) === 0; } public function isWorkerAvailableThisWeek($worker_id, $selectedDate) { $weekday = date('w', strtotime($selectedDate)); $weekNumber = date('W', strtotime($selectedDate)); $isOddWeek = $weekNumber % 2 !== 0; $query = $this->db->query(" SELECT * FROM worker_schedule WHERE worker_id = ? AND weekday = ? AND ( is_alternate_week = 0 OR (is_alternate_week = 1 AND " . ($isOddWeek ? "1" : "0") . ") ) ", array($worker_id, $weekday)); return $query->num_rows() > 0; } public function getBookingsByDateRange($startDate, $endDate, $workerId = null) { $this->load->database(); $sql = 'SELECT b.*, w.worker_name, w.worker_profile_img FROM bookings b JOIN workers w ON b.worker_id = w.worker_id WHERE b.booking_date BETWEEN ? AND ?'; $params = array($startDate, $endDate); if ($workerId) { $sql .= ' AND b.worker_id = ?'; $params[] = $workerId; } $sql .= ' ORDER BY b.booking_date, b.booking_start_time'; $query = $this->db->query($sql, $params); if ($query->num_rows() == 0) return array(); $resultsArray = array(); foreach ($query->result() as $row) { $resultTmp = (array)$row; $resultTmp['services'] = array(); $resultTmp['service_names_joined'] = ''; if (!empty($resultTmp['service_ids'])) { $servicesArr = unserialize($resultTmp['service_ids']); if (is_array($servicesArr)) { $names = array(); foreach ($servicesArr as $sid) { $svc = $this->getServiceById($sid); if (is_object($svc)) { $resultTmp['services'][] = (object)array( 'service_name' => $svc->service_name_hu, 'service_price' => $svc->service_price, 'service_time' => $svc->service_time ); $names[] = $svc->service_name_hu; } } $resultTmp['service_names_joined'] = implode(', ', $names); } } $resultsArray[] = (object)$resultTmp; } return $resultsArray; } } ?>