diff --git a/backend/Admin/driver/getDriverGiftPayment.php b/backend/Admin/driver/getDriverGiftPayment.php index 48316959..2af90ccf 100644 --- a/backend/Admin/driver/getDriverGiftPayment.php +++ b/backend/Admin/driver/getDriverGiftPayment.php @@ -53,14 +53,18 @@ if ($stmt->rowCount() > 0) { $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); // Decrypt sensitive fields + $fieldsToDecrypt = ['phone', 'email', 'first_name', 'last_name', 'name_arabic', 'national_number', 'address', 'gender', 'site', 'birthdate']; foreach ($rows as &$row) { - if (!empty($row['phone'])) { - $row['phone'] = $encryptionHelper->decryptData($row['phone']); - } - if (!empty($row['name_arabic'])) { - $row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']); + foreach ($fieldsToDecrypt as $f) { + if (!empty($row[$f])) { + $dec = $encryptionHelper->decryptData($row[$f]); + if ($dec !== false && $dec !== null) { + $row[$f] = $dec; + } + } } } + unset($row); jsonSuccess($rows); diff --git a/backend/Admin/getPassengerDetailsByPassengerID.php b/backend/Admin/getPassengerDetailsByPassengerID.php index 9fe8a384..4085850b 100644 --- a/backend/Admin/getPassengerDetailsByPassengerID.php +++ b/backend/Admin/getPassengerDetailsByPassengerID.php @@ -63,14 +63,12 @@ $sql = "SELECT FROM `passengers` WHERE - passengers.id = '$passengerID' -GROUP BY - `passengers`.`id` + passengers.id = :pid ORDER BY countPassengerRide DESC"; $stmt = $con->prepare($sql); -$stmt->execute(); +$stmt->execute([':pid' => $passengerID]); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); // ✅ فك تشفير الحقول الحساسة diff --git a/backend/Admin/getPassengerbyEmail.php b/backend/Admin/getPassengerbyEmail.php index 7ff59ba0..bc6a5f45 100644 --- a/backend/Admin/getPassengerbyEmail.php +++ b/backend/Admin/getPassengerbyEmail.php @@ -1,18 +1,20 @@ encryptData(filterRequest("passengerEmail")); -$passengerId = filterRequest("passengerId"); -$passengerphone = $encryptionHelper->encryptData(filterRequest("passengerphone")); +$rawEmail = filterRequest("passengerEmail"); +$rawPhone = filterRequest("passengerphone"); +$passengerEmail = !empty($rawEmail) ? $encryptionHelper->encryptData($rawEmail) : '___NON_EXISTENT___'; +$passengerId = filterRequest("passengerId"); +$passengerphone = !empty($rawPhone) ? $encryptionHelper->encryptData($rawPhone) : '___NON_EXISTENT___'; /** * الفهرس الأعمى: يسمح بالبحث بعد نقل التخزين إلى AES-GCM العشوائي. * تُبقى المقارنة القديمة في نفس الاستعلام كاحتياط حتى تنتهي تعبئة الفهارس. */ global $blindIndex; -$emailBidx = $blindIndex ? $blindIndex->index('passengers.email', filterRequest("passengerEmail")) : null; -$phoneBidx = $blindIndex ? $blindIndex->index('passengers.phone', filterRequest("passengerphone")) : null; +$emailBidx = (!empty($rawEmail) && $blindIndex) ? $blindIndex->index('passengers.phone', $rawEmail) : null; +$phoneBidx = (!empty($rawPhone) && $blindIndex) ? $blindIndex->index('passengers.phone', $rawPhone) : null; $sql = "SELECT `passengers`.`id`, diff --git a/backend/Admin/rides/admin_get_rides_by_phone.php b/backend/Admin/rides/admin_get_rides_by_phone.php index 410318fe..0428f443 100644 --- a/backend/Admin/rides/admin_get_rides_by_phone.php +++ b/backend/Admin/rides/admin_get_rides_by_phone.php @@ -22,6 +22,10 @@ $raw = normalizePhone($phone); // شَفِّر قبل الاستعلام $enc_raw = $encryptionHelper->encryptData($raw); +global $blindIndex; +$pBidx = $blindIndex ? $blindIndex->index('passengers.phone', $raw) : null; +$dBidx = $blindIndex ? $blindIndex->index('driver.phone', $raw) : null; + try { error_log("[get_last_ride] Searching phone normalized=$raw"); diff --git a/backend/Admin/rides/monitorRide.php b/backend/Admin/rides/monitorRide.php index b4330c4a..f3d9a519 100644 --- a/backend/Admin/rides/monitorRide.php +++ b/backend/Admin/rides/monitorRide.php @@ -60,16 +60,16 @@ if ($driver) { } //------------------------------------------------------------------------ -// 2) جلب آخر رحلة حالتها نشطة (Apply, Applied, Arrived, Begin) +// 2) جلب آخر رحلة حالتها نشطة //------------------------------------------------------------------------ -$activeStatuses = "'Apply','Applied','Arrived','arrived','Begin'"; +$activeStatuses = "'apply','applied','arrived','begin','accepted','started','claimed','new','nothing','waiting','wait','pending','searching'"; if ($userType == 'driver') { error_log("[MONITOR_RIDE] 4. Searching for active ride for Driver ID: " . $driverID); $rideQuery = $con->prepare(" SELECT * FROM ride - WHERE driver_id = :driverID AND status IN ($activeStatuses) + WHERE driver_id = :driverID AND LOWER(status) IN ($activeStatuses) ORDER BY id DESC LIMIT 1 "); $rideQuery->execute([':driverID' => $driverID]); @@ -77,7 +77,7 @@ if ($userType == 'driver') { error_log("[MONITOR_RIDE] 4. Searching for active ride for Customer ID: " . $customerID); $rideQuery = $con->prepare(" SELECT * FROM ride - WHERE passenger_id = :customerID AND status IN ($activeStatuses) + WHERE passenger_id = :customerID AND LOWER(status) IN ($activeStatuses) ORDER BY id DESC LIMIT 1 "); $rideQuery->execute([':customerID' => $customerID]); @@ -100,25 +100,28 @@ if (!$ride) { $rideDriverID = $ride['driverID'] ?? $ride['driver_id']; error_log("[MONITOR_RIDE] 5. Fetching info for Driver ID from Ride: " . $rideDriverID); -$driverInfoQuery = $con->prepare(" - SELECT id, first_name, last_name, phone - FROM driver - WHERE id = :driverID - LIMIT 1 -"); +$driverInfo = null; +if ($rideDriverID) { + $driverInfoQuery = $con->prepare(" + SELECT id, first_name, last_name, phone + FROM driver + WHERE id = :driverID + LIMIT 1 + "); -$driverInfoQuery->execute([':driverID' => $rideDriverID]); -$driverInfo = $driverInfoQuery->fetch(PDO::FETCH_ASSOC); + $driverInfoQuery->execute([':driverID' => $rideDriverID]); + $driverInfo = $driverInfoQuery->fetch(PDO::FETCH_ASSOC); -if ($driverInfo) { - $driverInfo['phone'] = $encryptionHelper->decryptData($driverInfo['phone']); - $driverInfo['first_name'] = $encryptionHelper->decryptData($driverInfo['first_name']); - $driverInfo['last_name'] = $encryptionHelper->decryptData($driverInfo['last_name']); - $fullName = $driverInfo['first_name'] . " " . $driverInfo['last_name']; - $driverInfo['fullname'] = $fullName; - error_log("[MONITOR_RIDE] 5. Driver Info Found: " . $fullName); -} else { - error_log("[MONITOR_RIDE] 5. WARNING: Driver info not found for ID " . $rideDriverID); + if ($driverInfo) { + $driverInfo['phone'] = $encryptionHelper->decryptData($driverInfo['phone']); + $driverInfo['first_name'] = $encryptionHelper->decryptData($driverInfo['first_name']); + $driverInfo['last_name'] = $encryptionHelper->decryptData($driverInfo['last_name']); + $fullName = trim(($driverInfo['first_name'] ?? '') . " " . ($driverInfo['last_name'] ?? '')); + $driverInfo['fullname'] = $fullName ?: "Unknown Driver"; + error_log("[MONITOR_RIDE] 5. Driver Info Found: " . $fullName); + } else { + error_log("[MONITOR_RIDE] 5. WARNING: Driver info not found for ID " . $rideDriverID); + } } //------------------------------------------------------------------------ @@ -127,14 +130,21 @@ if ($driverInfo) { error_log("[MONITOR_RIDE] 6. Querying Tracking DB for Driver ID: " . $rideDriverID); -$locationQuery = $con_tracking->prepare(" - SELECT latitude, longitude, speed, heading, updated_at - FROM car_locations - WHERE driver_id = :driverID AND status = 'ON' - ORDER BY updated_at DESC LIMIT 1 -"); -$locationQuery->execute([':driverID' => $rideDriverID]); -$location = $locationQuery->fetch(PDO::FETCH_ASSOC); +$location = null; +if ($rideDriverID && isset($con_tracking) && $con_tracking) { + try { + $locationQuery = $con_tracking->prepare(" + SELECT latitude, longitude, speed, heading, updated_at + FROM car_locations + WHERE driver_id = :driverID AND status = 'ON' + ORDER BY updated_at DESC LIMIT 1 + "); + $locationQuery->execute([':driverID' => $rideDriverID]); + $location = $locationQuery->fetch(PDO::FETCH_ASSOC) ?: null; + } catch (Throwable $e) { + error_log("[MONITOR_RIDE] Tracking query exception: " . $e->getMessage()); + } +} if ($location) { error_log("[MONITOR_RIDE] 6. Location Found: Lat=" . $location['latitude'] . " Lng=" . $location['longitude']); diff --git a/backend/Admin/v2/financial/settlements.php b/backend/Admin/v2/financial/settlements.php index 9fe905c6..42028104 100644 --- a/backend/Admin/v2/financial/settlements.php +++ b/backend/Admin/v2/financial/settlements.php @@ -18,7 +18,7 @@ try { COUNT(r.id) as total_rides FROM driver d LEFT JOIN ride r ON d.id = r.driver_id AND LOWER(r.status) IN ('finished','completed') - GROUP BY d.id + GROUP BY d.id, d.first_name, d.last_name, d.phone HAVING total_earned > 0 ORDER BY total_earned DESC LIMIT 50 diff --git a/backend/connect.php b/backend/connect.php index ca40671b..9e26b084 100644 --- a/backend/connect.php +++ b/backend/connect.php @@ -37,6 +37,9 @@ $role = $decoded->role ?? 'passenger'; // 3. Database Connection try { $con = Database::get('main'); + try { $con_tracking = Database::get('tracking'); } catch (Throwable $e) { $con_tracking = $con; } + try { $con_ride = Database::get('ride'); } catch (Throwable $e) { $con_ride = $con; } + try { $con_transit = Database::get('transit'); } catch (Throwable $e) { $con_transit = $con; } } catch (Exception $e) { http_response_code(500); exit(json_encode(['error' => 'Database connection failed'])); diff --git a/dashboard/siro-admin/index.html b/dashboard/siro-admin/index.html index 690f9644..ab21943e 100644 --- a/dashboard/siro-admin/index.html +++ b/dashboard/siro-admin/index.html @@ -360,13 +360,13 @@ ID - Name - Phone - Email - Rating - Trips - Cancellations - Status + Name + Phone + Email + Rating + Trips + Cancellations + Status @@ -398,13 +398,13 @@ ID - Name - Contact - Trips - Rating - Cancellations - Joined - Status + Name + Contact + Trips + Rating + Cancellations + Joined + Status @@ -458,8 +458,8 @@ ID - Name - Phone + Name + Phone Type Requested role Requested at diff --git a/dashboard/siro-admin/js/app.js b/dashboard/siro-admin/js/app.js index 9c1fd4e3..ed810caf 100644 --- a/dashboard/siro-admin/js/app.js +++ b/dashboard/siro-admin/js/app.js @@ -458,6 +458,56 @@ 'This browser is registered as a trusted device:': 'هذا المتصفح مسجّل كجهاز موثوق:', 'The endpoint responded successfully but returned no data yet.': 'استجاب الـ API بنجاح لكنه لم يُرجِع بياناتاً بعد.', 'No records recorded for this yet — the table is empty in the database.': 'لا توجد سجلات بعد — الجدول فارغ في قاعدة البيانات.', + // Database and API Field Translations + 'Total Revenue': 'إجمالي الإيرادات', + 'Company Profit': 'أرباح الشركة', + 'Total Driver Pay': 'إجمالي مستحقات السائقين', + 'Total Platform Commission': 'عمولة المنصة', + 'Cash Payments': 'الدفع النقدي', + 'Digital Payments': 'الدفع الرقمي', + 'Total Earned': 'إجمالي الأرباح', + 'First Name': 'الاسم الأول', + 'Last Name': 'اسم العائلة', + 'Full Name': 'الاسم الكامل', + 'Driver Id': 'معرّف السائق', + 'Passenger Id': 'معرّف الراكب', + 'Created At': 'تاريخ الإنشاء', + 'Updated At': 'تاريخ التحديث', + 'Birthdate': 'تاريخ الميلاد', + 'Gender': 'الجنس', + 'National Number': 'الرقم الوطني', + 'Address': 'العنوان', + 'Site': 'الموقع', + 'Active Routes': 'المسارات النشطة', + 'Active Enrollments': 'التسجيلات النشطة', + 'Average Pci': 'متوسط PCI', + 'Market Share Percent': 'نسبة الحصة السوقية', + 'Total Anomalies': 'حالات الشذوذ', + 'Total Surge Opportunities': 'فرص الفورة', + 'Report Date': 'تاريخ التقرير', + 'Date': 'التاريخ', + 'User Type': 'نوع المستخدم', + 'User': 'المستخدم', + 'Ride Details': 'تفاصيل الرحلة', + 'Driver Details': 'تفاصيل السائق', + 'Driver Location': 'موقع السائق', + 'Price': 'السعر', + 'Price For Driver': 'حصة السائق', + 'Price For Passenger': 'المبلغ من الراكب', + 'Distance': 'المسافة', + 'Payment Method': 'طريقة الدفع', + 'Car Type': 'نوع السيارة', + 'Start Location': 'موقع البداية', + 'End Location': 'موقع النهاية', + 'Cancel Reason': 'سبب الإلغاء', + 'Driver First Name': 'اسم السائق الأول', + 'Driver Last Name': 'اسم عائلة السائق', + 'Passenger First Name': 'اسم الراكب الأول', + 'Passenger Last Name': 'اسم عائلة الراكب', + 'Contact': 'معلومات الاتصال', + 'Click any row to open the full profile': 'اضغط على أي سطر لفتح الملف الشخصي الكامل', + 'Search by passenger ID, phone or email': 'البحث برقم الراكب، الهاتف، أو البريد الإلكتروني', + 'Search rides by phone number': 'البحث في الرحلات برقم الهاتف', 'Yes': 'نعم', 'No': 'لا', 'Click any row to open the full profile': 'اضغط على أي سطر لفتح الملف الشخصي الكامل', @@ -3339,11 +3389,12 @@ } function humanize(key) { - return String(key) + const s = String(key) .replace(/[_-]+/g, ' ') .replace(/([a-z])([A-Z])/g, '$1 $2') .replace(/\b\w/g, (m) => m.toUpperCase()) .trim(); + return t(key) || t(s) || s; } function msgNode(text) {