Update: 2026-08-07 02:19:07

This commit is contained in:
Hamza-Ayed
2026-08-07 02:19:07 +03:00
parent b492034bad
commit 3081aea802
3 changed files with 274 additions and 4 deletions
@@ -1,5 +1,7 @@
<?php
require_once __DIR__ . '/../../connect.php';
require_once __DIR__ . '/../../connect.php';
require_once __DIR__ . '/../pricing/pricing_helper.php';
require_once __DIR__ . '/cancel_fee_helper.php';
try {
$con_ride = Database::get('ride');
@@ -18,8 +20,10 @@ if (!$rideId) {
}
try {
// جلب بيانات الرحلة للتحقق (مع passenger_id للإدراج في canecl)
$stmt = $con->prepare("SELECT driver_id, passenger_id, status FROM ride WHERE id = ?");
// ‏SELECT * لا قائمة أعمدة: نحتاج rideTimeStart و carType لحساب الرسم،
// ‏وأسماء بعض الأعمدة متضاربة بين الschema والقاعدة الحية (carType /
// ‏car_type). النجمة تجعل الاستعلام يعمل في كل الحالات.
$stmt = $con->prepare("SELECT * FROM ride WHERE id = ?");
$stmt->execute([$rideId]);
$ride = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -64,8 +68,47 @@ try {
$insertCanecl->execute([$driverId, $passengerId, $rideId, $reason]);
}
// =================================================================
// 1.5 رسم الإلغاء — تعويض للسائق لا إيراد للشركة
//
// ‏متماثل مع تعويض عدم الحضور في cancel_ride_by_driver.php: من ضيّع
// ‏وقت الآخر يعوّضه. الفرق أن الزمن يُحتسب من لحظة القبول لا من لحظة
// ‏الوصول — السائق كان في طريقه لا واقفاً ينتظر.
//
// ‏المبلغ لا يأتي من العميل بأي حال، ويُحسب من أسعار kazan نفسها.
// =================================================================
$cancelFee = 0.0;
$feeExemptReason = '';
try {
$cancelFee = computePassengerCancelFee(
$con, $redisLocation ?? null, $rideId, $ride, $driverId, $feeExemptReason
);
} catch (Throwable $eFee) {
// ‏فشل حساب الرسم لا يمنع الإلغاء أبداً — الإلغاء حق للراكب.
error_log("[cancel_ride_by_passenger] تعذّر حساب الرسم: " . $eFee->getMessage());
}
if ($cancelFee > 0) {
// ‏عدّاد عدم الحضور — للتقارير وقرارات الحظر اليدوية.
try {
$con->prepare("UPDATE passengers SET noShowCount = noShowCount + 1 WHERE id = ?")
->execute([$ride['passenger_id'] ?? '']);
} catch (PDOException $eCnt) {
error_log("[cancel_ride_by_passenger] عدّاد عدم الحضور غير مُرحَّل بعد: "
. $eCnt->getMessage());
}
}
$con->commit();
// ‏التحويل المالي بعد الـcommit لا داخله: نداءات S2S شبكية قد تستغرق
// ‏ثوانٍ، وإبقاء المعاملة مفتوحة خلالها يقفل صفوف ride تحت ضغط.
if ($cancelFee > 0) {
applyCancelFeeTransfer(
$con, $ride['passenger_id'] ?? '', $driverId, $rideId, $cancelFee
);
}
// تحديث السيرفر البعيد (Remote DB)
if (isset($con_ride)) {
try {
@@ -155,7 +198,12 @@ try {
'passenger_id' => $ride['passenger_id'] ?? '',
]);
jsonSuccess(null, "Ride cancelled successfully");
// ‏الرسم يُرجَع للتطبيق ليعرضه صراحةً. خصم صامت من المحفظة يكتشفه
// ‏الراكب لاحقاً هو أسرع طريق لشكوى ولمراجعة سيئة.
jsonSuccess([
'cancel_fee' => $cancelFee ?? 0,
'fee_exempt' => ($cancelFee ?? 0) > 0 ? '' : ($feeExemptReason ?? ''),
], "Ride cancelled successfully");
} catch (PDOException $e) {
if ($con->inTransaction()) $con->rollBack();