Files
Hamza-AyedandClaude Opus 5 4d8414c96b feat: استيراد كود سيرو إلى تريبز (سيرو @ecfe7568) — بلا تعديل
قرار المالك 2026-07-27: باك إند سيرو PHP هو المعتمد، وتطبيقاته المجرّبة
ميدانياً تحل محل إعادة البناء المؤرشفة. سيرو نفسه لم يُمسّ.

الخريطة:
  backend · payment_server · loction_server · ride_server ·
  passenger_server · docker · dashboard · stress_test  → الجذر
  siro_rider  → apps/rider          siro_driver  → apps/driver
  siro_admin  → dashboards/admin    siro_service → dashboards/service
  android_bot → apps/android_bot    socialBot    → apps/socialBot

نُسخ المتعقَّب في git سيرو فقط عبر `git archive` (3,198 ملفاً / ~169 م.ب)
لا `cp -r` — فاستُثنيت مخلفات البناء تلقائياً. بلا أي تعديل محتوى عمداً:
كل ما يلي يصير فرقاً مقروءاً مقابل المصدر.

لم يُستورد وسببه: siromove.com (الموقع التسويقي يبقى marketing/ في تريبز،
سيرو فيه 8 ملفات) · docs و planning (تريبز له docs/ الخاص) · deploy.sh
(ليس نشراً على سيرفر بل `git add . && git push origin --all` — فخّ في
مستودع آخر) · transit_dashboard (بانتظار قرار مصير backend-transit و
dashboards/transit-web).

⚠️ لا يبني بعد — ثلاثة نواقص متوقعة ومقصودة:
1. `.env` و `lib/env/env.g.dart` غير متعقَّبين في سيرو (أسرار لكل مستأجر):
   كل تطبيق فلاتر يحتاج .env خاصاً ثم توليد env.g.dart بـ build_runner.
2. إعدادات Firebase (9 ملفات google-services.json و GoogleService-Info.plist)
   يستبعدها .gitignore تريبز — ولكل مستأجر مشروع Firebase خاص أصلاً.
3. apps/driver في سيرو يشير إلى `../../Intaleq/packages/get` خارج المستودع →
   يجب ضمّ الحزم داخله أسوة بـ apps/rider.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 05:14:13 +03:00

97 lines
4.1 KiB
PHP

<?php
// cron_ride_timeout.php
// 🔥 أُعيدت كتابته بالكامل: كان يعتمد على جدول waitingRides الذي لم يعد
// يُملأ من تدفق add_ride.php الحقيقي (addWaitingRide.php لا يُستدعى من هناك)،
// فكانت الرحلات العالقة بحالة 'waiting' لا تُصفَّر أبداً. الآن يعمل مباشرة
// على جدول ride باستخدام أعمدة date/time المكتوبة فعلياً عند الإنشاء.
require_once __DIR__ . '/../../core/bootstrap.php';
require_once __DIR__ . '/../../functions.php';
error_log("⏰ [Cleanup Cron] Started cleaning old waiting rides...");
$minutesLimit = 15;
try {
$con = Database::get('main');
// =========================================================
// الخطوة 1: جلب الرحلات العالقة (status='waiting' منذ أكثر من 15 دقيقة)
// =========================================================
$sqlSelect = "SELECT id, passenger_id FROM ride
WHERE status = 'waiting'
AND TIMESTAMP(`date`, `time`) < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
$stmtSelect = $con->prepare($sqlSelect);
$stmtSelect->execute();
$staleRides = $stmtSelect->fetchAll(PDO::FETCH_ASSOC);
$updatedCount = 0;
if (!empty($staleRides)) {
$sqlUpdate = "UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'";
$stmtUpdate = $con->prepare($sqlUpdate);
// نسخة أرشيفية (best-effort)
$con_ride = null;
try {
$con_ride = Database::get('ride');
} catch (Exception $e) {
error_log("[cron_ride_timeout] Secondary ride DB unavailable: " . $e->getMessage());
}
$stmtUpdate2 = $con_ride ? $con_ride->prepare(
"UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'"
) : null;
foreach ($staleRides as $ride) {
$rideId = $ride['id'];
$stmtUpdate->execute([$rideId]);
$updatedCount += $stmtUpdate->rowCount();
if ($stmtUpdate2) {
try {
$stmtUpdate2->execute([$rideId]);
} catch (PDOException $e) {
error_log("[cron_ride_timeout] Secondary DB update failed for #$rideId: " . $e->getMessage());
}
}
// 🆕 تنظيف Redis + إعلام أي سائقين ما زالوا يرون هذا الطلب على أنه ملغى
sendToLocationServer('cancel_ride', [
'ride_id' => $rideId,
'driver_id' => 0,
'reason' => 'timeout',
]);
}
}
// =========================================================
// الخطوة 2: تنظيف جدول waitingRides القديم (إن وُجدت صفوف فيه من مسار قديم)
// =========================================================
$deletedCount = 0;
try {
$sqlDelete = "DELETE FROM waitingRides WHERE created_at < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
$stmtDelete = $con->prepare($sqlDelete);
$stmtDelete->execute();
$deletedCount = $stmtDelete->rowCount();
} catch (PDOException $e) {
error_log("[cron_ride_timeout] waitingRides cleanup skipped: " . $e->getMessage());
}
if ($updatedCount > 0 || $deletedCount > 0) {
$msg = "✅ [Cleanup Cron] Success: Timed out $updatedCount ride(s) in ride table, and cleaned $deletedCount legacy waitingRides row(s).";
error_log($msg);
echo json_encode(["status" => "success", "message" => $msg]);
} else {
$msg = "💤 [Cleanup Cron] No expired rides found.";
error_log($msg);
echo json_encode(["status" => "success", "message" => "Nothing to clean."]);
}
} catch (PDOException $e) {
$errorMsg = "❌ [Cleanup Cron] Error: " . $e->getMessage();
error_log($errorMsg);
echo json_encode(["status" => "failure", "message" => "An internal error occurred."]);
}
?>