111 lines
4.9 KiB
PHP
111 lines
4.9 KiB
PHP
<?php
|
|
/**
|
|
* driver_assurance/eligibility.php — حساب أهلية السائق للتأمين
|
|
* ─────────────────────────────────────────────────────────────
|
|
* قرار المالك: التأمين ليس خدمة تُمنح لكل من سجّل، بل مكافأة استمرار.
|
|
* لا يستحقّه السائق إلا بعد عدد رحلات مكتملة وتقييم جيد.
|
|
*
|
|
* المنطق التجاري خلفه: القسط كلفة متكررة تتحمّلها الشركة عن السائق أو
|
|
* تخصمها من أرباحه. منحه لمن قد يختفي بعد أسبوع يحوّل الأداة من
|
|
* ولاء إلى نزيف — والسائق الذي أتمّ مئتي رحلة بتقييم جيد أثبت أنه
|
|
* باقٍ، وهو بالضبط من نريد قفله معنا.
|
|
*
|
|
* الأرقام في جدول الخطط لا في هذا الملف: الشريك سيغيّرها، ومصر تختلف
|
|
* عن الأردن، وتعديل صف أرخص من نشر إصدار.
|
|
*/
|
|
|
|
/**
|
|
* يقيس السائق مقابل شروط خطة.
|
|
*
|
|
* @return array{
|
|
* eligible: bool,
|
|
* rides: int, rating: float, account_days: int,
|
|
* reasons: string[]
|
|
* }
|
|
*/
|
|
function assuranceCheckEligibility(PDO $con, string $driverId, array $plan): array
|
|
{
|
|
$rides = 0;
|
|
$rating = 0.0;
|
|
$days = 0;
|
|
|
|
try {
|
|
// الرحلات المكتملة فقط. الحالة مكتوبة بحرفين مختلفين في
|
|
// الجدول تاريخياً ('Finished' و'finished')، وإغفال أحدهما
|
|
// يُنقص عدّاد السائق إلى النصف تقريباً.
|
|
$st = $con->prepare("
|
|
SELECT COUNT(*) FROM ride
|
|
WHERE driver_id = ? AND status IN ('Finished', 'finished')
|
|
");
|
|
$st->execute([$driverId]);
|
|
$rides = (int) $st->fetchColumn();
|
|
|
|
$st = $con->prepare("SELECT AVG(rating) FROM ratingDriver WHERE driver_id = ?");
|
|
$st->execute([$driverId]);
|
|
$avg = $st->fetchColumn();
|
|
// سائق بلا تقييمات ليس سيئاً — لكنه أيضاً غير مثبَت. عدد
|
|
// الرحلات المطلوب يضمن أن تقييماته وصلت على أي حال.
|
|
$rating = $avg === null || $avg === false ? 0.0 : round((float) $avg, 2);
|
|
|
|
$st = $con->prepare("SELECT DATEDIFF(NOW(), created_at) FROM driver WHERE id = ? LIMIT 1");
|
|
$st->execute([$driverId]);
|
|
$d = $st->fetchColumn();
|
|
$days = ($d === false || $d === null) ? 0 : (int) $d;
|
|
} catch (PDOException $e) {
|
|
error_log('[assurance] تعذّر حساب الأهلية: ' . $e->getMessage());
|
|
return [
|
|
'eligible' => false, 'rides' => 0, 'rating' => 0.0, 'account_days' => 0,
|
|
'reasons' => ['تعذّر التحقق حالياً'],
|
|
];
|
|
}
|
|
|
|
$minRides = (int) ($plan['min_completed_rides'] ?? 200);
|
|
$minRating = (float) ($plan['min_rating'] ?? 4.50);
|
|
$minDays = (int) ($plan['min_account_days'] ?? 30);
|
|
|
|
// نجمع كل الأسباب لا أوّلها: السائق يستحق أن يعرف كل ما ينقصه
|
|
// دفعةً واحدة، لا أن يعالج شرطاً فيُفاجأ بالتالي.
|
|
$reasons = [];
|
|
if ($rides < $minRides) {
|
|
$reasons[] = "أكمل $minRides رحلة (لديك $rides)";
|
|
}
|
|
if ($rating < $minRating) {
|
|
$reasons[] = "تقييمك يجب ألّا يقل عن $minRating (تقييمك " . ($rating ?: '—') . ')';
|
|
}
|
|
if ($days < $minDays) {
|
|
$reasons[] = "مضيّ $minDays يوماً على حسابك (مضى $days)";
|
|
}
|
|
|
|
return [
|
|
'eligible' => empty($reasons),
|
|
'rides' => $rides,
|
|
'rating' => $rating,
|
|
'account_days' => $days,
|
|
'reasons' => $reasons,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* الوثيقة النشطة للسائق مع بيانات خطتها، أو null.
|
|
*/
|
|
function assuranceActivePolicy(PDO $con, string $driverId): ?array
|
|
{
|
|
try {
|
|
$st = $con->prepare("
|
|
SELECT p.*, pl.code, pl.name_ar AS plan_name, pl.premium, pl.currency,
|
|
pl.billing_cycle, pl.coverage_summary,
|
|
pr.name AS provider_name, pr.name_ar AS provider_name_ar
|
|
FROM driver_insurance_policies p
|
|
JOIN insurance_plans pl ON pl.id = p.plan_id
|
|
JOIN insurance_providers pr ON pr.id = pl.provider_id
|
|
WHERE p.driver_id = ? AND p.status = 'active'
|
|
ORDER BY p.id DESC LIMIT 1
|
|
");
|
|
$st->execute([$driverId]);
|
|
return $st->fetch(PDO::FETCH_ASSOC) ?: null;
|
|
} catch (PDOException $e) {
|
|
error_log('[assurance] تعذّر جلب الوثيقة: ' . $e->getMessage());
|
|
return null;
|
|
}
|
|
}
|