From e070c2d9a8890cc9eb83e685c3b5e05f644be8c5 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 7 Aug 2026 02:37:30 +0300 Subject: [PATCH] Update: 2026-08-07 02:37:30 --- backend/ride/pricing/pricing_helper.php | 63 ++++++++++++++++++++ backend/ride/rides/cancel_fee_helper.php | 26 +++----- backend/ride/rides/cancel_ride_by_driver.php | 8 ++- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/backend/ride/pricing/pricing_helper.php b/backend/ride/pricing/pricing_helper.php index 31c9dacc..16551c52 100644 --- a/backend/ride/pricing/pricing_helper.php +++ b/backend/ride/pricing/pricing_helper.php @@ -167,3 +167,66 @@ function estimateDriverEarningsAdvantage( ]; } ?> + +/** + * ‏صف التسعير الصحيح لدولة هذه الرحلة. + * + * ⚠️ ‏لا تستخدم "SELECT * FROM kazan LIMIT 1" أبداً. جدول kazan يحمل صفاً + * ‏لكل دولة بمقاييس متباعدة جداً: + * Syria 40 SYP/كم · 9 SYP/دقيقة + * Egypt 3.5 EGP/كم · 0.8 EGP/دقيقة + * Jordan 0.284 JOD/كم· 0.05 JOD/دقيقة + * ‏فـ LIMIT 1 يعيد أول صف (سوريا) ويطبّق أسعارها على رحلة أردنية — أي + * ‏مئات الأضعاف. حدث هذا فعلاً في مسارَي الإلغاء. + * + * ‏مصدر الدولة: driver.site عبر الرحلة — نفس ما يفعله finish_ride_updates.php. + * ‏وإن تعذّر (رحلة بلا سائق مثلاً) نقع على $fallbackCountry. + * + * @return array ‏صف kazan، أو مصفوفة فارغة إن لم يُوجد شيء إطلاقاً. + */ +function getKazanForRide(PDO $con, $rideId, string $fallbackCountry = 'Syria', $driverId = null): array +{ + $country = ''; + + try { + if (!empty($driverId) && (string) $driverId !== '0') { + // ‏مسار الإلغاء يصفّر ride.driver_id قبل الوصول إلى هنا، فالانضمام + // ‏عبر الرحلة يرجع فارغاً. المستدعي يمرّر السائق الذي يعرفه. + $stmt = $con->prepare("SELECT site FROM driver WHERE id = ? LIMIT 1"); + $stmt->execute([$driverId]); + } else { + $stmt = $con->prepare(" + SELECT d.site AS country_code + FROM ride r + LEFT JOIN driver d ON d.id = r.driver_id + WHERE r.id = ? LIMIT 1 + "); + $stmt->execute([$rideId]); + } + $country = (string) ($stmt->fetchColumn() ?: ''); + } catch (PDOException $e) { + error_log("[pricing] تعذّر تحديد دولة الرحلة $rideId: " . $e->getMessage()); + } + + if ($country === '') { + $country = $fallbackCountry; + error_log("[pricing] الرحلة $rideId بلا دولة معروفة — السقوط على $country"); + } + + try { + $stmt = $con->prepare("SELECT * FROM kazan WHERE country = ? LIMIT 1"); + $stmt->execute([$country]); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$row) { + error_log("[pricing] لا صف kazan للدولة $country — السقوط على $fallbackCountry"); + $stmt->execute([$fallbackCountry]); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + } + + return $row ?: []; + } catch (PDOException $e) { + error_log("[pricing] تعذّر جلب أسعار $country: " . $e->getMessage()); + return []; + } +} diff --git a/backend/ride/rides/cancel_fee_helper.php b/backend/ride/rides/cancel_fee_helper.php index 8e40e9f0..3600f77e 100644 --- a/backend/ride/rides/cancel_fee_helper.php +++ b/backend/ride/rides/cancel_fee_helper.php @@ -41,21 +41,16 @@ function computePassengerCancelFee( // ‏لا أحد تحرّك، فلا أحد يستحق تعويضاً. وهذه أغلب حالات الإلغاء. if (empty($driverId) || (string) $driverId === '0') { $exemptReason = 'no_driver_assigned'; - try { - $stmtCur = $con->prepare("SELECT currency, country FROM kazan LIMIT 1"); - $stmtCur->execute(); - $rowCur = $stmtCur->fetch(PDO::FETCH_ASSOC) ?: []; - $currency = !empty($rowCur['currency']) - ? (string) $rowCur['currency'] - : getCurrencyByCountry((string) ($rowCur['country'] ?? 'Syria')); - } catch (PDOException $e) { /* الافتراضي يكفي */ } + $rowCur = getKazanForRide($con, $rideId); + $currency = !empty($rowCur['currency']) + ? (string) $rowCur['currency'] + : getCurrencyByCountry((string) ($rowCur['country'] ?? 'Syria')); return 0.0; } // ── سياسة الدولة ──────────────────────────────────────── - $stmtKazan = $con->prepare("SELECT * FROM kazan LIMIT 1"); - $stmtKazan->execute(); - $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: []; + // ‏أسعار دولة هذه الرحلة تحديداً — لا أول صف في الجدول. + $kazan = getKazanForRide($con, $rideId, 'Syria', $driverId); // ‏العمود currency هو المرجع، وgetCurrencyByCountry احتياط إن كان فارغاً. $currency = !empty($kazan['currency']) @@ -137,13 +132,8 @@ function applyCancelFeeTransfer(PDO $con, $passengerId, $driverId, $rideId, floa return; } - try { - $stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1"); - $stmtKazan->execute(); - $country = strtolower((string) ($stmtKazan->fetchColumn() ?: 'jordan')); - } catch (PDOException $e) { - $country = 'jordan'; - } + $kazanRow = getKazanForRide($con, $rideId, 'Syria', $driverId); + $country = strtolower((string) ($kazanRow['country'] ?? 'jordan')); $walletServer = "https://walletintaleq.intaleq.xyz"; if ($country === 'jordan') { diff --git a/backend/ride/rides/cancel_ride_by_driver.php b/backend/ride/rides/cancel_ride_by_driver.php index 31b0bc09..e7859659 100644 --- a/backend/ride/rides/cancel_ride_by_driver.php +++ b/backend/ride/rides/cancel_ride_by_driver.php @@ -226,9 +226,11 @@ try { // + دقائق الانتظار × سعر الدقيقة حسب وقت اليوم // ‏كل المدخلات مسجَّلة على الخادم؛ لا شيء منها من العميل. // ───────────────────────────────────────────────────────── - $stmtKazan = $con->prepare("SELECT * FROM kazan LIMIT 1"); - $stmtKazan->execute(); - $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: []; + // ‏أسعار دولة هذه الرحلة تحديداً. كان "LIMIT 1" يعيد أول صف + // ‏(سوريا) فيطبّق 40 SYP/كم على رحلة أردنية سعرها 0.284 JOD/كم. + // ‏$driverId يُمرَّر صراحةً: القسم ٣ صفّر ride.driver_id قبل هذه + // ‏النقطة، فالبحث عبر الرحلة كان سيرجع بلا دولة ويقع على سوريا. + $kazan = getKazanForRide($con, $rideId, 'Syria', $driverId); $country = $kazan['country'] ?? 'Jordan'; $compensationCap = (float) ($kazan['cancelCompensationCap'] ?? 0);