prepare("SELECT * FROM scheduled_rides WHERE id = ? LIMIT 1"); $stmt->execute([$bookingId]); $booking = $stmt->fetch(PDO::FETCH_ASSOC); if (!$booking) { jsonError('Booking not found', 404); } // ‏الملكية: الحجز يحمل نقاط انطلاق ووجهة الراكب — لا يُلغيه غيره. if ((string) $booking['passenger_id'] !== (string) $passengerId) { error_log("[scheduled/cancel] SECURITY: محاولة إلغاء حجز غير مملوك" . " (booking=$bookingId caller=$passengerId)"); jsonError('Forbidden', 403); } if ($booking['status'] === 'dispatched') { jsonError('Ride already created — cancel it from the active ride screen', 409); } if ($booking['status'] !== 'scheduled') { jsonSuccess(['id' => $bookingId, 'status' => $booking['status']], 'Booking is not active'); } $con->prepare(" UPDATE scheduled_rides SET status = 'cancelled', cancelled_reason = ? WHERE id = ? AND status = 'scheduled' ")->execute([$reason ? mb_substr($reason, 0, 255) : null, $bookingId]); jsonSuccess(['id' => $bookingId, 'status' => 'cancelled'], 'Booking cancelled'); } catch (PDOException $e) { error_log('[scheduled/cancel] ' . $e->getMessage()); jsonError('DB Error', 500); }