Update: 2026-08-07 05:29:18

This commit is contained in:
Hamza-Ayed
2026-08-07 05:29:18 +03:00
parent b938e287c6
commit 0b8b687ce1
5 changed files with 208 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
<?php
// ============================================================
// pending_rating.php — آخر رحلة منتهية لم تُقيَّم بعد
//
// ‏لماذا نقطة مستقلة:
// ‏شاشة التقييم لا تُفتح اليوم إلا عبر needsReview في
// ‏getRideStatusFromStartApp.php، وذاك محصور بنافذة ساعة واحدة — وهي
// ‏نافذة مقصودة لاستئناف رحلة **قائمة** لا للتقييم. النتيجة أن من يغلق
// ‏التطبيق فور نزوله (وهو السلوك الغالب) لا يُطلب منه تقييم أبداً.
//
// ‏توسيع تلك النافذة كان سيجعل التطبيق يفتح شاشة رحلة على رحلة انتهت.
// ‏لذلك: نقطة منفصلة تسأل سؤالاً واحداً — «هل عليّ تقييم متأخر؟» — بلا
// ‏أي علاقة بحالة الرحلة الجارية.
//
// ── قاعدتان لا واحدة ──
// ‏الرحلات في قاعدة ride والتقييمات في primary، وهما منفصلتان فيزيائياً
// ‏فلا انضمام ممكن. استعلامان: آخر الرحلات المنتهية من ride، ثم أيّها
// ‏مقيَّم في primary. الحد الصغير يبقي التكلفة ضئيلة.
// ============================================================
require_once __DIR__ . '/../../connect.php';
try {
$con_ride = Database::get('ride');
} catch (Exception $e) {
error_log("[pending_rating] Ride DB unavailable: " . $e->getMessage());
jsonError("Service unavailable", 503);
}
// ‏من يسأل: راكب يقيّم سائقه، أو سائق يقيّم راكبه.
$role_ = filterRequest("role") === 'driver' ? 'driver' : 'passenger';
// ‏الهوية من الـJWT لا من الطلب — وإلا قرأ أي أحد رحلات غيره.
$userId = $user_id ?? '';
if (empty($userId)) {
jsonError("Unauthorized", 401);
}
// ‏نافذة معقولة: تقييم رحلة نسيها صاحبها بلا قيمة، ويزعجه.
const PENDING_RATING_WINDOW_DAYS = 7;
// ‏عدد الرحلات التي نفحصها. آخر رحلة غير مقيّمة عملياً ضمن آخر قليل،
// ‏فلا داعي لمسح تاريخ المستخدم كله.
const PENDING_RATING_SCAN_LIMIT = 10;
try {
// ── ١) آخر الرحلات المنتهية من قاعدة الرحلات ──────────────
$col = $role_ === 'driver' ? 'driver_id' : 'passenger_id';
$stmt = $con_ride->prepare("
SELECT id, driver_id, passenger_id, price, carType,
start_location, end_location, rideTimeFinish
FROM ride
WHERE `$col` = ?
AND status = 'Finished'
AND rideTimeFinish >= NOW() - INTERVAL " . PENDING_RATING_WINDOW_DAYS . " DAY
ORDER BY rideTimeFinish DESC
LIMIT " . PENDING_RATING_SCAN_LIMIT
);
$stmt->execute([$userId]);
$rides = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($rides)) {
jsonSuccess(['pending' => false], "No pending rating");
}
// ── ٢) أيّها مقيَّم؟ استعلام واحد لكلها ───────────────────
$ids = array_column($rides, 'id');
$ph = implode(',', array_fill(0, count($ids), '?'));
// ‏الراكب يقيّم السائق في ratingDriver (العمود ride_id)،
// ‏والسائق يقيّم الراكب في ratingPassenger (العمود rideId).
$ratedSql = $role_ === 'driver'
? "SELECT rideId AS rid FROM ratingPassenger WHERE rideId IN ($ph)"
: "SELECT ride_id AS rid FROM ratingDriver WHERE ride_id IN ($ph)";
$stmtRated = $con->prepare($ratedSql);
$stmtRated->execute($ids);
$rated = array_flip($stmtRated->fetchAll(PDO::FETCH_COLUMN));
// ── ٣) أول رحلة غير مقيّمة (الأحدث أولاً) ─────────────────
$target = null;
foreach ($rides as $r) {
if (!isset($rated[$r['id']]) && !isset($rated[(string) $r['id']])) {
$target = $r;
break;
}
}
if (!$target) {
jsonSuccess(['pending' => false], "No pending rating");
}
// ── ٤) اسم الطرف الآخر ────────────────────────────────────
// ‏من primary: جداول driver/passengers تعيش هناك، والاسم مشفَّر.
$otherId = $role_ === 'driver' ? $target['passenger_id'] : $target['driver_id'];
$otherName = '';
try {
$table = $role_ === 'driver' ? 'passengers' : 'driver';
$stmtName = $con->prepare("SELECT first_name FROM `$table` WHERE id = ? LIMIT 1");
$stmtName->execute([$otherId]);
$raw = $stmtName->fetchColumn();
if ($raw && !empty($encryptionHelper)) {
$dec = $encryptionHelper->decryptData($raw);
$otherName = ($dec !== false && $dec !== '') ? $dec : '';
}
} catch (Throwable $e) {
// ‏الاسم تحسين لا شرط — الشاشة تعمل بدونه.
error_log("[pending_rating] تعذّر جلب اسم الطرف الآخر: " . $e->getMessage());
}
jsonSuccess([
'pending' => true,
'rideId' => (string) $target['id'],
'targetId' => (string) $otherId,
'targetName' => $otherName,
'price' => $target['price'],
'carType' => $target['carType'],
'finishedAt' => $target['rideTimeFinish'],
], "Pending rating found");
} catch (PDOException $e) {
error_log("[pending_rating] " . $e->getMessage());
jsonError("DB Error", 500);
}