- docs/00-15: دراسة، بنية، محرك تعرفة، تسعير، نموذج استئجار، تكاملات، بيانات، realtime، خطة، devops، لاندنج، مخاطر، اصطلاحات سيرفر، تدفق نشر - backend/: NestJS 11 على Docker (health + tenants + عزل tenant_id + بادئة tripz_ + Redis DB 3) - apps/rider, apps/driver, dashboards/admin-web, dashboards/superadmin-web (هياكل) - sync-to-server.sh + .gitignore Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.0 KiB
4.0 KiB
04 — محرك التعرفة
المبدأ
محرك قواعد يقرأ تعريف التعرفة كـ وثيقة JSON لكل مجموعة (مستأجر × مدينة × فئة خدمة). يغطي كل قدرات Onde الموثقة ويضيف ما يحتاجه سوقنا (العداد المنظّم الأردني، تقريب العملة).
الأوضاع المدعومة
| الوضع | الوصف | مثال سوق |
|---|---|---|
time_and_distance |
زمن + مسافة معاً | عام |
time_or_distance |
يبدّل حسب عتبة سرعة (تحت العتبة = دقيقة/زحمة، فوقها = كم) | العداد المنظّم — عمّان |
fixed_quote |
سعر مقفول لحظة تحديد الوجهة | يلا غو / كريم |
zone_matrix |
مصفوفة منطقة ← منطقة (PostGIS) | مطار ← وسط البلد |
المكوّنات
- فتحة عداد (flag down) + سعر/كم + سعر/دقيقة + رسوم خدمة/حجز.
- نوافذ زمنية: نهار/ليل/جمعة/أعياد بجدولة صريحة.
- Surge بسقف معلن (مضاعف حسب العرض/الطلب في خلايا H3، قابل للتعطيل حيث يمنعه المنظّم).
- رسوم إضافية مسماة: بدل تطبيق، مطار، أمتعة.
- بدل انتظار: بالدقيقة أو بزيادات ثوانٍ.
- رسوم إلغاء متدرجة بمرحلة الرحلة + حد أدنى للأجرة.
- قواعد تقريب لكل عملة (أقرب 0.05 دينار؛ أقرب 500 ل.س...).
- سياسة إعادة الاحتساب: متى يُكسر السعر المقفول (انحراف مسار > نسبة محددة).
واجهة المحرك (الباك إند)
tariff.quote(input) → يحسب سعراً تقديرياً/مقفولاً قبل الطلب
tariff.finalize(trip) → يحسب السعر النهائي عند الإنهاء
tariff.cancelFee(trip) → رسم الإلغاء حسب المرحلة
كلها نقية، مختبَرة بوحدات (نفس المدخل = نفس المخرج).
مثال — عمّان على العداد المنظّم (أرقام رسمية)
{
"tenant": "amman-operator-x",
"service_class": "taxi-yellow",
"currency": "JOD",
"rounding": { "increment": 0.05, "mode": "nearest" },
"mode": "time_or_distance",
"speed_threshold_kmh": 18,
"windows": [
{ "name": "day", "from": "06:00", "to": "22:00",
"flag": 0.39, "per_km": 0.28, "per_min_waiting": 0.48 },
{ "name": "night", "from": "22:00", "to": "06:00",
"flag": 0.40, "per_km": 0.33, "per_min_waiting": 0.55 }
],
"booking_fee": 0.25,
"min_fare": 1.00,
"surge": { "enabled": false },
"cancellation": [
{ "stage": "after_assign", "after_sec": 120, "fee": 0.50 },
{ "stage": "driver_arrived", "fee": 1.00 }
],
"recalc_policy": { "fixed_quote": false }
}
قيم الانتظار بالدقيقة تقديرية للتوضيح وتُضبط من الزيادات الرسمية (كل 35 ثانية) عند التفعيل؛ فتحة العداد وسعر الكيلومتر هما الرقمان الرسميان المعتمدان.
مخطط التخزين
- الجدول
tariffs:id, tenant_id, city, service_class, definition (jsonb), version, active_from. - إصدارات (versioning) — التعرفة النافذة وقت الرحلة تُثبَّت في
trip.tariff_versionللمراجعة. - مناطق
zone_matrixتُخزَّن كـ PostGIS polygons في pricing-zones.
قواعد
- لا سعر بلا تعرفة نافذة مطابقة — خطأ صريح لا افتراض صامت.
- كل رحلة تحفظ نسخة من التعرفة المستخدمة (audit trail + مطلب المنظّم).
- التقريب آخر خطوة دائماً بعد جمع كل المكوّنات.
← السابق: 03-mobile-plan · التالي: 05-pricing-billing