prepare("SELECT setting_value FROM company_settings WHERE company_id = ? AND setting_key = ?"); $stmt->bind_param("is", $companyId, $key); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); $stmt->close(); return $row ? $row['setting_value'] : $default; } $baseMileageRate = (float) getCompanySetting($conn, $companyId, 'base_mileage_rate', '2.00'); $baseHireRate = (float) getCompanySetting($conn, $companyId, 'base_hire_rate', '3.50'); $airportSurcharge = (float) getCompanySetting($conn, $companyId, 'airport_surcharge', '5.00'); $autoDispatchEnabled = getCompanySetting($conn, $companyId, 'auto_dispatch_enabled', '0') == '1'; $autoDispatchMaxDistance = (int) getCompanySetting($conn, $companyId, 'auto_dispatch_max_distance', '10'); if ($editId > 0) { $stmt = $conn->prepare("SELECT * FROM bookings WHERE id = ? AND company_id = ?"); $stmt->bind_param("ii", $editId, $companyId); $stmt->execute(); $result = $stmt->get_result(); $editBooking = $result->fetch_assoc(); $stmt->close(); } if ($copyId > 0 && !$editBooking) { $stmt = $conn->prepare("SELECT * FROM bookings WHERE id = ? AND company_id = ?"); $stmt->bind_param("ii", $copyId, $companyId); $stmt->execute(); $result = $stmt->get_result(); $copyData = $result->fetch_assoc(); if ($copyData) { unset($copyData['id']); $copyData['status'] = 'pending_dispatch'; $editBooking = $copyData; } $stmt->close(); } $drivers = []; $stmt = $conn->prepare("SELECT id, driver_name, callsign, status, latitude, longitude, current_zone, phone FROM drivers WHERE company_id = ? AND is_active = 1 ORDER BY driver_name"); $stmt->bind_param("i", $companyId); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { $drivers[] = $row; } $stmt->close(); $vehicles = []; $stmt = $conn->prepare("SELECT id, callsign FROM vehicles WHERE company_id = ? AND status = 'active' ORDER BY callsign"); $stmt->bind_param("i", $companyId); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { $vehicles[] = $row; } $stmt->close(); $accounts = []; $stmt = $conn->prepare("SELECT id, company_name FROM accounts WHERE company_id = ? AND status = 'active' ORDER BY company_name"); $stmt->bind_param("i", $companyId); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { $accounts[] = $row; } $stmt->close(); $zones = []; $zoneStmt = $conn->prepare("SELECT zone_code, zone_name FROM zones WHERE company_id = ? AND is_active = 1"); $zoneStmt->bind_param("i", $companyId); $zoneStmt->execute(); $zoneResult = $zoneStmt->get_result(); while ($zoneRow = $zoneResult->fetch_assoc()) { $zones[] = $zoneRow; } $zoneStmt->close(); $vehicleTypes = ['Saloon', 'Estate', 'MPV6', 'MPV8', 'Hatchback', 'SUV', 'Minibus', 'Luxury', 'Executive', 'WAV']; $priorityOptions = ['Low', 'Medium', 'High', 'Emergency']; $luggageOptions = range(0, 15); $passengerOptions = range(1, 20); $repeatDaysList = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Fortnightly']; $capabilitiesList = [ 'wheelchair' => '♿ Wheelchair Access', 'child_seat' => '👶 Child Seat', 'pet_friendly' => '🐾 Pet Friendly', 'xl_luggage' => '🧳 XL Luggage', 'airport_meet' => '✈️ Airport Meet', 'corporate' => '🏢 Corporate', 'female_driver' => '👩 Female Driver', 'dbs_checked' => '✅ DBS Checked', 'multilingual' => '🌍 Multilingual' ]; function autoAssignDriver($pickup_lat, $pickup_lng, $companyId, $conn, $maxDistance = 10) { $stmt = $conn->prepare(" SELECT id, driver_name, callsign, status, ( 6371 * acos( GREATEST(-1, LEAST(1, cos(radians(?)) * cos(radians(COALESCE(latitude, 0))) * cos(radians(COALESCE(longitude, 0)) - radians(?)) + sin(radians(?)) * sin(radians(COALESCE(latitude, 0))) )) ) ) AS distance_km FROM drivers WHERE company_id = ? AND status = 'available' AND latitude IS NOT NULL AND longitude IS NOT NULL HAVING distance_km < ? ORDER BY distance_km ASC LIMIT 1 "); $stmt->bind_param("dddid", $pickup_lat, $pickup_lng, $pickup_lat, $companyId, $maxDistance); $stmt->execute(); $result = $stmt->get_result(); $driver = $result->fetch_assoc(); $stmt->close(); return $driver; } $isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $response = ['success' => false, 'message' => '', 'booking_ref' => '']; try { $bookingRef = $editBooking['booking_ref'] ?? 'BK-' . date('Ymd') . '-' . rand(100, 999); $bookingDate = !empty($_POST['booking_date']) ? $_POST['booking_date'] : date('Y-m-d'); $bookingTime = !empty($_POST['booking_time']) ? $_POST['booking_time'] : date('H:i:s'); $assigned_driver_id = !empty($_POST['driver_id']) ? $_POST['driver_id'] : null; if ($autoDispatchEnabled && !$assigned_driver_id && !empty($_POST['pickup_lat']) && !empty($_POST['pickup_lng'])) { $nearestDriver = autoAssignDriver($_POST['pickup_lat'], $_POST['pickup_lng'], $companyId, $conn, $autoDispatchMaxDistance); if ($nearestDriver) $assigned_driver_id = $nearestDriver['id']; } $capabilities_selected = isset($_POST['capabilities']) && is_array($_POST['capabilities']) ? implode(',', $_POST['capabilities']) : ''; if (isset($_POST['booking_id']) && !empty($_POST['booking_id'])) { $stmt = $conn->prepare("UPDATE bookings SET customer_name = ?, customer_phone = ?, email = ?, pickup_address = ?, pickup_note = ?, destination = ?, dest_note = ?, via = ?, via_note = ?, vehicle_type = ?, driver_id = ?, price = ?, distance = ?, duration = ?, notes = ?, office_note = ?, company = ?, your_ref = ?, our_ref = ?, priority = ?, flight_number = ?, flight_origin = ?, passengers = ?, suitcases = ?, capabilities = ?, repeat_days = ?, repeat_end = ?, return_time = ?, account_id = ?, loyalty_card = ?, booking_date = ?, booking_time = ?, pickup_time = ?, status = ?, pickup_lat = ?, pickup_lng = ?, zone_code = ?, updated_at = NOW() WHERE id = ? AND company_id = ?"); $stmt->bind_param( "ssssssssssiddssssssssiississsssssddssii", $_POST['customer_name'], $_POST['customer_phone'], $_POST['email'], $_POST['pickup_address'], $_POST['pickup_note'], $_POST['destination'], $_POST['dest_note'], $_POST['via'], $_POST['via_note'], $_POST['vehicle_type'], $assigned_driver_id, $_POST['price'], $_POST['distance'], $_POST['duration'], $_POST['notes'], $_POST['office_note'], $_POST['company'], $_POST['your_ref'], $_POST['our_ref'], $_POST['priority'], $_POST['flight_number'], $_POST['flight_origin'], $_POST['passengers'], $_POST['luggage'], $capabilities_selected, $_POST['repeat_days'], $_POST['repeat_end'], $_POST['return_time'], $_POST['account_id'] ?: null, $_POST['loyalty_card'], $bookingDate, $bookingTime, $bookingTime, $_POST['status'], $_POST['pickup_lat'] ?? null, $_POST['pickup_lng'] ?? null, $_POST['zone_code'] ?? 'TWN', $_POST['booking_id'], $companyId ); if (!$stmt->execute()) throw new Exception($stmt->error); $response = ['success' => true, 'message' => 'Booking updated successfully', 'booking_ref' => $bookingRef]; } else { $now = date('Y-m-d H:i:s'); $pendingStatus = 'pending_dispatch'; $defaultZone = 'TWN'; $sql = "INSERT INTO bookings SET company_id = ?, booking_ref = ?, customer_name = ?, customer_phone = ?, email = ?, pickup_address = ?, pickup_note = ?, destination = ?, dest_note = ?, via = ?, via_note = ?, vehicle_type = ?, driver_id = ?, price = ?, distance = ?, duration = ?, notes = ?, office_note = ?, company = ?, your_ref = ?, our_ref = ?, priority = ?, flight_number = ?, flight_origin = ?, passengers = ?, suitcases = ?, capabilities = ?, repeat_days = ?, repeat_end = ?, return_time = ?, account_id = ?, loyalty_card = ?, booking_date = ?, booking_time = ?, pickup_time = ?, status = ?, pickup_lat = ?, pickup_lng = ?, zone_code = ?, created_at = ?, updated_at = ?"; $stmt = $conn->prepare($sql); if (!$stmt) throw new Exception("Prepare failed: " . $conn->error); $values = [ $companyId, $bookingRef, !empty($_POST['customer_name']) ? $_POST['customer_name'] : '', !empty($_POST['customer_phone']) ? $_POST['customer_phone'] : '', !empty($_POST['email']) ? $_POST['email'] : '', !empty($_POST['pickup_address']) ? $_POST['pickup_address'] : '', !empty($_POST['pickup_note']) ? $_POST['pickup_note'] : '', !empty($_POST['destination']) ? $_POST['destination'] : '', !empty($_POST['dest_note']) ? $_POST['dest_note'] : '', !empty($_POST['via']) ? $_POST['via'] : '', !empty($_POST['via_note']) ? $_POST['via_note'] : '', !empty($_POST['vehicle_type']) ? $_POST['vehicle_type'] : '', $assigned_driver_id, !empty($_POST['price']) ? (float)$_POST['price'] : 0, !empty($_POST['distance']) ? (float)$_POST['distance'] : 0, !empty($_POST['duration']) ? (int)$_POST['duration'] : 0, !empty($_POST['notes']) ? $_POST['notes'] : '', !empty($_POST['office_note']) ? $_POST['office_note'] : '', !empty($_POST['company']) ? $_POST['company'] : '', !empty($_POST['your_ref']) ? $_POST['your_ref'] : '', !empty($_POST['our_ref']) ? $_POST['our_ref'] : '', !empty($_POST['priority']) ? $_POST['priority'] : 'Medium', !empty($_POST['flight_number']) ? $_POST['flight_number'] : '', !empty($_POST['flight_origin']) ? $_POST['flight_origin'] : '', !empty($_POST['passengers']) ? (int)$_POST['passengers'] : 1, !empty($_POST['luggage']) ? (int)$_POST['luggage'] : 0, $capabilities_selected, !empty($_POST['repeat_days']) ? $_POST['repeat_days'] : '', !empty($_POST['repeat_end']) ? $_POST['repeat_end'] : null, !empty($_POST['return_time']) ? $_POST['return_time'] : null, !empty($_POST['account_id']) ? (int)$_POST['account_id'] : null, !empty($_POST['loyalty_card']) ? $_POST['loyalty_card'] : '', !empty($_POST['booking_date']) ? $_POST['booking_date'] : date('Y-m-d'), !empty($_POST['booking_time']) ? $_POST['booking_time'] : date('H:i:s'), !empty($_POST['booking_time']) ? $_POST['booking_time'] : date('H:i:s'), $pendingStatus, isset($_POST['pickup_lat']) && $_POST['pickup_lat'] !== '' ? (float)$_POST['pickup_lat'] : null, isset($_POST['pickup_lng']) && $_POST['pickup_lng'] !== '' ? (float)$_POST['pickup_lng'] : null, !empty($_POST['zone_code']) ? $_POST['zone_code'] : $defaultZone, $now, $now ]; $types = ''; foreach ($values as $v) { if (is_int($v)) $types .= 'i'; elseif (is_float($v)) $types .= 'd'; else $types .= 's'; } $stmt->bind_param($types, ...$values); if (!$stmt->execute()) throw new Exception($stmt->error); $response = ['success' => true, 'message' => 'Booking created successfully', 'booking_ref' => $bookingRef]; } $stmt->close(); } catch(Exception $e) { $response = ['success' => false, 'message' => $e->getMessage()]; error_log("Booking error: " . $e->getMessage()); } if ($isAjax) { header('Content-Type: application/json'); echo json_encode($response); exit; } else { $savedBookingRef = $response['success'] ? $response['booking_ref'] : ''; $message = $response['message']; $messageType = $response['success'] ? 'success' : 'error'; } } $savedCapabilities = []; if (!empty($editBooking['capabilities'])) $savedCapabilities = explode(',', $editBooking['capabilities']); $currentDate = date('Y-m-d'); $currentTime = date('H:i'); $roleDisplay = ucfirst(str_replace('_', ' ', $userType)); $availableCount = count(array_filter($drivers, fn($d) => $d['status'] == 'available')); $busyCount = count(array_filter($drivers, fn($d) => $d['status'] == 'busy')); $totalCount = count($drivers); ?> FleetCortex - <?php echo $editId ? 'Edit Booking' : 'New Booking'; ?>
FleetCortex

0
You are editing booking EDIT MODE
TIME ● Live
PICKUP
Note
VIA
Note
DEST
Note
NAME
COMPANY
DRIVER NOTE
PHONE
CAPABILITIES
$label): ?>
onchange="updateCapabilitiesDisplay()">
PASS
LUG
REQ VEHICLE
VEHICLE TYPE
DRIVER
ACCOUNT
YOUR REF
OUR REF
PRIORITY
LOYALTY
RETURN TIME
FLIGHT #
LUGGAGE NOTE
REPEAT
REPEAT END
FLT ORIGIN
RETURN FLT
OFFICE NOTE
EMAIL
PREBOOK TIMELINE
10
15
30
45
11
15
30
45
12
VEH0ETA0min
AVERAGE ETA0min
Distance mi
Duration min
Price£
Tariff: Mileage £/mi + Hire £
CallsignStatusZoneETA
ZoneVehClearBusyBook

Passenger History

Enter a phone number to check active bookings
Press F2 or click the history button after entering a phone number
No Booking History
Enter a phone number to view booking history
No Favorites
No saved addresses found
No Call Records
No call details found
No Change History
No audit trail found
No Transactions
No payment records found
🖼️
NO PICTURES ATTACHED
No images uploaded for this journey

Edit Pricing

Custom %

Send Confirmation

📞 PhoneNo phone
✉️ EmailNo email

Send Message

Keyboard Shortcuts

F2 Passenger HistoryF9 Tariff & Estimation
Insert Manual Price OverrideAlt+A Add Via / Mid-Trip Stop
Alt+R Return JourneyCtrl+Enter Save & Book
Home Save & HoldEnd Save & Book
Ctrl+P Call PassengerCtrl+D Call Driver
Ctrl+H Passenger HistoryEsc Close / Clear Form