if (!function_exists('tt_driver_can_accept_job')) { /** * Şoförün yeni iş alıp alamayacağını kontrol eder: * 1. Set kiralama: Başlangıç saatinden itibaren 20 saat başka iş alamaz. Öncesinde ve sonrasında serbest. * 2. Transfer: Başlangıç saati + KM dakika + 30 dk intikal ilavesi süresince başka iş alamaz. Öncesinde ve sonrasında serbest. * 3. Tur işleri: Tur başlangıç tarih/saatinden tur bitiş tarih/saatine kadar + 30 dk intikal süresince başka iş alamaz. Öncesinde ve sonrasında serbest. * 4. Saatlik tahsis: Başlangıç tarih/saati + seçilen saatlik paket + tahmini km (dk) + 30 dk intikal süresince başka iş alamaz. Öncesinde ve sonrasında serbest. * * Bu aralıklar haricinde istediği kadar iş alabilir. Süresi dolmuş eski işler engel teşkil etmez. */ function tt_driver_can_accept_job(PDO $pdo, string $driverId, string $targetTransferId = '', ?array $targetJobData = null): array { $driverId = trim($driverId); if ($driverId === '') return ['allowed' => false, 'code' => 'DRIVER_REQUIRED', 'message' => 'Şoför kimliği bulunamadı.']; // 1. Hedef iş kaydını belirle $targetRow = $targetJobData; $targetTransferId = trim($targetTransferId); if ($targetRow === null && $targetTransferId !== '') { $candidates = [$targetTransferId]; if (str_starts_with($targetTransferId, 'tour_')) $candidates[] = substr($targetTransferId, 5); else $candidates[] = 'tour_' . $targetTransferId; if (str_starts_with($targetTransferId, 'rental_')) $candidates[] = substr($targetTransferId, 7); else $candidates[] = 'rental_' . $targetTransferId; $candidates = array_values(array_unique(array_filter($candidates, static fn($v) => $v !== ''))); // transfers tablosunda ara if (tt_das_table_exists($pdo, 'transfers')) { try { $inPlaceholders = implode(',', array_fill(0, count($candidates), '?')); $st = $pdo->prepare("SELECT * FROM transfers WHERE id IN ($inPlaceholders) LIMIT 1"); $st->execute($candidates); $targetRow = $st->fetch(PDO::FETCH_ASSOC) ?: null; } catch (Throwable) {} } // tour_requests tablosunda ara if ($targetRow === null && tt_das_table_exists($pdo, 'tour_requests')) { try { $cleanId = str_starts_with($targetTransferId, 'tour_') ? substr($targetTransferId, 5) : $targetTransferId; $st = $pdo->prepare("SELECT * FROM tour_requests WHERE id = ? LIMIT 1"); $st->execute([$cleanId]); $trRow = $st->fetch(PDO::FETCH_ASSOC) ?: null; if ($trRow) { $trRow['service_type'] = 'tour'; $targetRow = $trRow; } } catch (Throwable) {} } // enterprise_jobs tablosunda ara if ($targetRow === null && tt_das_table_exists($pdo, 'enterprise_jobs')) { try { $inEjPlaceholders = implode(',', array_fill(0, count($candidates), '?')); $st = $pdo->prepare("SELECT * FROM enterprise_jobs WHERE id IN ($inEjPlaceholders) OR source_transfer_id IN ($inEjPlaceholders) LIMIT 1"); $st->execute(array_merge($candidates, $candidates)); $targetRow = $st->fetch(PDO::FETCH_ASSOC) ?: null; } catch (Throwable) {} } // jobs tablosunda ara if ($targetRow === null && tt_das_table_exists($pdo, 'jobs')) { try { $st = $pdo->prepare("SELECT * FROM jobs WHERE id = ? LIMIT 1"); $st->execute([$targetTransferId]); $targetRow = $st->fetch(PDO::FETCH_ASSOC) ?: null; } catch (Throwable) {} } } // Hedef işin zaman penceresi $targetWindow = null; $targetStart = null; $targetEnd = null; if ($targetRow !== null && is_array($targetRow)) { $targetWindow = tt_get_job_time_window($pdo, $targetRow); $targetStart = (int)($targetWindow['start_ts'] ?? 0); $targetEnd = (int)($targetWindow['end_ts'] ?? 0); // Eğer hedef işin başlangıcı geçmişte kalmışsa (anlık iş alımı), başlangıcı şu an olarak al if ($targetStart > 0 && $targetStart < time()) { $duration = max(1800, (int)($targetWindow['duration_seconds'] ?? 3600)); $targetStart = time(); $targetEnd = $targetStart + $duration; $targetWindow['start_ts'] = $targetStart; $targetWindow['end_ts'] = $targetEnd; } } else { // Hedef iş verisi doğrudan bulunamazsa varsayılan olarak şu andan itibaren 1 saat kabul et $targetStart = time(); $targetEnd = $targetStart + 3600; } // Şoförün mevcut aktif işlerini çek $activeJobs = tt_driver_get_active_jobs_records($pdo, $driverId, $targetTransferId); $activeCount = count($activeJobs); $now = time(); // Her bir aktif iş için zaman penceresini hesapla ve çakışma kontrolü yap foreach ($activeJobs as $activeJob) { $actWin = tt_get_job_time_window($pdo, $activeJob); $actStart = (int)($actWin['start_ts'] ?? 0); $actEnd = (int)($actWin['end_ts'] ?? 0); if ($actStart <= 0 || $actEnd <= 0) continue; // KURAL: Eğer mevcut işin süresi ÇOKTAN BİTMİŞSE (actEnd <= now): // Bu iş şoförü yeni iş almaktan engelleyemez! (iş bitiminden sonra istediği kadar iş alabilir) if ($actEnd <= $now) { continue; } // İki zaman aralığı çakışıyor mu? // Hedef iş: [targetStart, targetEnd] // Aktif iş: [actStart, actEnd] // Çakışma koşulu: targetStart < actEnd && actStart < targetEnd if ($targetStart < $actEnd && $actStart < $targetEnd) { $conflictType = (string)($actWin['service_type'] ?? 'transfer'); $conflictTitle = (string)($actWin['title'] ?? 'Aktif İş'); $conflictStartStr = date('H:i', $actStart); $conflictEndStr = date('H:i', $actEnd); if (date('Y-m-d', $actStart) !== date('Y-m-d', $actEnd)) { $conflictStartStr = date('d.m.Y H:i', $actStart); $conflictEndStr = date('d.m.Y H:i', $actEnd); } $msg = ''; if ($conflictType === 'set_rental' || ($targetWindow['service_type'] ?? '') === 'set_rental') { $msg = 'Setlere araç kiralama işi başlangıcından itibaren 20 saat başka iş alamazsınız (' . $conflictStartStr . ' - ' . $conflictEndStr . '). Bu aralık haricinde dilediğiniz gibi iş alabilirsiniz.'; } elseif ($conflictType === 'tour' || ($targetWindow['service_type'] ?? '') === 'tour') { $msg = 'Tur işi süresince başka iş alamazsınız (+30 dk intikal ilavesi: ' . $conflictStartStr . ' - ' . $conflictEndStr . '). Bu aralık haricinde dilediğiniz gibi iş alabilirsiniz.'; } elseif ($conflictType === 'hourly_rental' || ($targetWindow['service_type'] ?? '') === 'hourly_rental') { $msg = 'Saatlik araç tahsis süresince başka iş alamazsınız (seçilen paket + km + 30 dk intikal: ' . $conflictStartStr . ' - ' . $conflictEndStr . '). Bu aralık haricinde dilediğiniz gibi iş alabilirsiniz.'; } else { $msg = 'Transfer süresince başka iş alamazsınız (başlangıç saati + mesafe dk + 30 dk intikal: ' . $conflictStartStr . ' - ' . $conflictEndStr . '). Bu aralık haricinde dilediğiniz gibi iş alabilirsiniz.'; } return [ 'allowed' => false, 'code' => 'SCHEDULE_CONFLICT', 'message' => $msg, 'active_count' => $activeCount, 'conflict_job_id' => (string)($actWin['id'] ?? ''), 'conflict_title' => $conflictTitle, 'conflict_type' => $conflictType, 'conflict_window' => [ 'start' => date('Y-m-d H:i', $actStart), 'end' => date('Y-m-d H:i', $actEnd), ], 'target_window' => [ 'start' => date('Y-m-d H:i', $targetStart), 'end' => date('Y-m-d H:i', $targetEnd), ], ]; } // Çakışmıyorsa bu aktif iş engel oluşturmaz, diğer aktif işleri kontrol et } // Çakışma yok, serbest! return [ 'allowed' => true, 'active_count' => $activeCount, 'target_window' => $targetWindow, ]; } } if (!function_exists('tt_driver_has_active_job')) { function tt_driver_has_active_job(PDO $pdo, string $driverId, string $excludeTransferId = ''): bool { $check = tt_driver_can_accept_job($pdo, $driverId, $excludeTransferId); return !$check['allowed']; } }