26 KiB
22 — الخريطة الشاملة: من باك إند مكتمل إلى منصّة كاملة مماثلة لسيرو
بعد اكتمال المجموعات A–K (باك إند النواة) واختبار E2E بـ43 محكّاً على السيرفر، هذه خريطة بقية المنتج: كل ما في سيرو + طبقة الـSaaS متعددة المستأجرين + تطبيق فلاتر مُعاد بناؤه. مبنية على دراسة كود سيرو الفعلي لا التخمين. كل مجموعة تُنفَّذ بعد إقرارك، مجموعة مجموعة (أسلوبنا المتّفق).
آخر تحديث: 2026-07-19 — تصحيح حالات M3/O2/O5/P على واقع الكود (كانت الوثيقة متأخرة عن الكوميتات)، + ربط كتالوج الميزات 27.
0. ما درسته في سيرو (سطح الميزات الكامل)
| المكوّن | ما هو | التقنية |
|---|---|---|
siro_rider · siro_driver |
تطبيقا الراكب والسائق | Flutter/GetX |
siro_admin |
تطبيق أدمن المستأجر | Flutter (متعدد المنصات) |
siro_service |
تطبيق خدمة العملاء | Flutter |
transit_dashboard |
لوحة المواصلات | ويب (Vite/JS) |
backend/pricing-engine |
تسعير ديناميكي/ذكاء أسعار المنافسين (انحدار · تجميع · surge · مناطق) | Node/TS |
backend/marketing_engine |
بوتات تسويق آلية + مولّد تعليقات Gemini + مهام مجدولة + تقارير | PHP + Python |
android_bot · socialBot |
بوتات | Kotlin/Android |
backend/Admin/geofence |
السياج الجغرافي | PHP |
backend/transit + وضع الباص |
نظام المواصلات (خطوط باص) | PHP + Flutter |
driver_assurance |
تأمين السائق | PHP |
متحكّم موقع السائق (location_controller.dart) |
تسجيل كل 3ث · رفع دفعات كل دقيقتين · واعٍ للبطارية (توفير عند 20%) · سوكت للبثّ + دفعات للحفظ · وضع باص منفصل · عتبة محفظة −200 | Flutter |
1. قراراتك المفتوحة — توصياتي
1.1 لوحة الأدمن/السوبر-أدمن/خدمة العملاء: ويب أم تطبيق؟
توصيتي: ويب للثلاثة (الأدمن · السوبر-أدمن · خدمة العملاء)، والموبايل (راكب/سائق) يبقى فلاتر.
- لماذا ويب: لا احتكاك متجر (تحديث فوري) · يعمل على سطح المكتب حيث يعمل المشغّلون فعلاً · بناء وصيانة أسهل من فلاتر · معيار الصناعة (لوحات أوبر/بولت ويب). سيرو استعمل فلاتر للأدمن لأنه أراد تطبيقاً واحداً، لكن للوحة تحكّم SaaS الويب أنسب.
- لماذا الموبايل يبقى فلاتر: GPS في الخلفية · overlay · إشعارات · كاميرا/حيوية وجه — كلها تحتاج أصيلاً (native).
- يطابق قرار بنية المستودع السابق:
dashboards/admin-web·dashboards/superadmin-web.
1.2 مواصفات السيرفر (بحث الحمل: 1.15M رحلة/يوم على صندوق مشترك واحد)
| الدور | المواصفات | الحمل |
|---|---|---|
| سيرفر مستأجر مشترك (launch/brand) | 8 vCPU · 32GB · NVMe | عدة مستأجرين صغار على نفس الصندوق (عزل بالبادئة) |
| سيرفر مستأجر سيادي (sovereign) | 8 vCPU · 16–32GB · NVMe مخصّص | مستأجر واحد كبير حتى ~1M/يوم |
| السيرفر الاحتياطي | مماثل أو أصغر | نسخة Postgres متدفّقة (streaming replica) + Redis AOF |
| Control Plane (سوبر-أدمن + فوترة) | 4 vCPU · 8GB | يدير كل المستأجرين، منفصل |
- العنق دائماً Postgres (بركة الاتصالات) لا الـCPU/RAM. Redis 4–8GB يكفي (نصوص صغيرة).
- الاحتياطي: تكرار فيزيائي متدفّق لـPostgres (hot standby) +
docker composeجاهز للإقلاع. RPO ≈ ثوانٍ، RTO ≈ دقائق. - التوسّع: نسخ API أفقية خلف Nginx (الـredis-io-adapter مبني أصلاً) قبل تقسيم القاعدة.
1.3 كتالوج الميزات: أساسية مقابل مدفوعة (يوسّع المجموعة K)
| فئة | ميزات |
|---|---|
| نواة (كل الباقات) | رحلات · مطابقة · محفظة · تقييم · إشعارات · دردشة · مكالمات · وثائق · مركبات |
| علامة+ | محرّك تعرفة كامل · country pack · أنواع رحلات مخصّصة · dispatch |
| أسطول+ | API/Webhooks · تقارير متقدمة · بوابة شركات |
| مدفوعة منفصلة (add-ons) | 🤖 التسعير الديناميكي · 📊 استخبار السوق · 📣 محرّك التسويق/البوتات · 🚌 المواصلات · 🛡️ تأمين السائق · المفاوض الذكي · شرائح السائقين |
| سيادة | كل الميزات + عزل داخل الدولة |
1.4 توفير المستأجر من السوبر-أدمن (الخيارات التي تزوّدها)
عند إنشاء مستأجر، السوبر-أدمن يحدّد: الاسم · اللوغو · الدولة (country pack) · وسائل الدفع · الباقة · الميزات المفعّلة · الحدود العددية. أغلبها مبني في K (tenants.features/settings)؛ الناقص: رفع اللوغو + توليد الحزمة (§2 المجموعة N).
1.5 طبقات التطبيق (lite / pro / max) — قرار المالك 2026-07-18 🔒
المطلوب: تُولَّد تطبيقات بـ«نسخ» متفاوتة الميزات، ولا يستطيع من يفكّك نسخة أدنى رؤية ميزات النسخ الأعلى.
القرار: نسخة = بناء مُولَّد، لا fork للكود. مستودع واحد؛ الطبقة تُشتق من باقة المستأجر عبر مانيفست N3.
ثلاث نسخ منسوخة يدوياً = كل إصلاح باغ ×٣ وتباعد خلال شهرين. الطبقة صفة للمستأجر لا قائمةَ متجرٍ إضافية (كل مستأجر له bundle ID خاصه أصلاً). و
lite/pro/maxليست مفهوماً جديداً — هي presets فوق كتالوج §1.3.
1) أعلام const لكل ميزة — لا Map وقت التشغيل.
بناء AOT يعمل tree-shaking: كود محروس بعلم const قيمته false يُحذف من الـbinary فيزيائياً. هذا ما يحقّق مناعة التفكيك. علم مستقل لكل ميزة (FF_NEGOTIATOR…)؛ لو قرأناها من Map وقت التشغيل بقي الكود كاملاً في الملف وضاع الغرض.
2) الطبقة الأصيلة موحّدة عبر كل الطبقات (شرط Shorebird). Shorebird يرقّع Dart فقط. بتوحيد Kotlin/الصلاحيات/NDK تصير ترقية مستأجر من lite إلى pro patch فورياً بلا مراجعة متجر؛ ولو اختلف الأصيل صار كل ترقية إصداراً جديداً وانتظار مراجعة — أي نخسر أهم ميزة تشغيلية عندنا.
3) طبقتا إعداد، لكلٍّ دورة حياة:
| الطبقة | متى تُحسم | تحوي | التغيير يسري بـ |
|---|---|---|---|
BuildConfig مولَّد (const) |
وقت البناء (N3) | هوية المستأجر · BASE_URL · ألوان · أصول · أعلام الميزات | إصدار/patch |
مانيفست ريموت (GET /tenant/config) |
كل إقلاع | تشغيل/إطفاء ضمن المبنيّ · وسائل الدفع · ترتيبات · وضع صيانة | فوراً |
القاعدة الحاكمة: الفعّال = المبني في الـbinary ∩ المانيفست ∩ استحقاقات السيرفر.
4) الحدّ الأمني يبقى السيرفر. التجريد من الـbinary دفاعٌ إضافي وحجمٌ أصغر وUX بلا أزرار مقفلة — لا بديل عن FeatureGuard (docs/19 — K5). أثقل ملكية فكرية (تسعير · مطابقة · surge) سيرفرية أصلاً ولا تظهر في التطبيق.
5) تطبيقاتنا المنشورة (rider/driver بمعرّفات tripz-mobile-store-identity) تبقى بناء max كاملاً — لا نفتّت قوائم منشورة.
البنية المقابلة في فلاتر (Q5): feature-first — كل ميزة موديول مستقل يسجّل نفسه في DI والراوتر فقط إذا علمه مفعّل، فيكون الإقفال من نقطة واحدة لا if مبعثرة في الشاشات.
2. المجموعات القادمة (تكملةً لـA–K)
المجموعة L — إكمال نموذج التسعير (B9/B10/B11 + الديناميكي)
| # | البند |
|---|---|
| L1 | B9: نقاط CRUD لتحرير التعرفة من لوحة الأدمن (jsonb موجود؛ نحتاج واجهة + تحقّق) |
| L2 | B10: كتالوج أنواع رحلات عالمي جاهز (بدل 6 مبثوثة) — المستأجر يختار منه |
| L3 | B11: بُعد تسعير بالوزن (شحن/توصيل) بجانب المسافة/الزمن |
| L4 | التسعير الديناميكي (من pricing-engine): surge حسب الطلب/العرض في المنطقة + مناطق تسعير. add-on مدفوع. 🔵 جهة الاستقبال جاهزة: tariff.engine يطبّق surge.multiplier × مضاعف geofence. الناقص: البوت الذي يكتب المضاعف (جرد كرونات سيرو الكامل في 27 §4). |
المجموعة M — ميزات التشغيل المتقدّمة (F سابقاً)
| # | البند |
|---|---|
| M1 | المفاوض الذكي: الراكب يعرض سعراً، السائق يقبل/يفاوض (نمط inDrive). |
| M2 | شرائح السائقين (tiers): برونزي/فضي/ذهبي حسب الأداء → أولوية عروض/عمولة أقل. |
| M3 | السياج الجغرافي (من Admin/geofence): مناطق مسموح/ممنوع · تسعير حسب المنطقة · حظر دخول. 🔵 مبني بالكود (a15e65c + fef1235، 2026-07-18): modules/geofence — Redis pub-sub، geofence_promo push عند دخول المنطقة، مضاعف تسعير في tariff.engine. الناقص: واجهة أدمن لرسم المناطق (R4 في 27) + إثبات سيرفر. |
| M4 | تأمين السائق (driver_assurance). |
المجموعة N — طبقة الـSaaS: السوبر-أدمن وتوليد التطبيق ⭐ (الهدف الأساسي) — 🔵 قيد التنفيذ
| # | البند | الحالة |
|---|---|---|
| N1 | لوحة سوبر-أدمن (ويب): إنشاء مستأجر · اسم/لوغو/دولة/دفع/باقة/ميزات · مراقبة. | ✅ الباك إند (provision · summary · app-manifest · payment-methods · branding · overview · status خلف PlatformGuard) + dashboards/superadmin-web/index.html (نظرة شاملة + تعليق/تفعيل). التصميم مؤجَّل عمداً لآخر المشوار. |
| N1a | تعليق المستأجر يسري فعلياً (2026-07-18). | ✅ كان tenant.status يُكتب ويُعرض بلا أي فرض — أي أن «تعطيل المستأجر» زخرفة والمستأجر غير الدافع يظل يشتغل. الفرض الآن في JwtStrategy (نقطة واحدة، نفس حجّة ربط الجهاز D2) + AuthService.resolveTenant (يخنق sendOtp وverifyOtp معاً). القراءة مكيَّشة (Redis أولاً) والإبطال يجعل التعليق فورياً؛ وتعذّر القراءة يمرّر لا يقطع المنصة كلها (G). |
| N1b | النظرة الشاملة: GET /admin/overview?days= — رحلات · GMV · إيراد المنصة (العمولة) لكل مستأجر. |
✅ استعلام واحد مجمَّع لكل المستأجرين (لا N+1). revenue = مجموع العمولة وهو الرقم الذي يهمّ عند التسعير، لا الـGMV. |
| N1c | خدمة اللوحات الثلاث على الإنترنت. | ✅ تُخدم من نفس أصل الـAPI عبر useStaticAssets: /panel/superadmin · /panel/admin · /panel/service — بلا CORS وبلا دومين/شهادة ثانية، وترث TLS القائم (docs/20). المجلد مربوط bind من compose فتعديل HTML يظهر بتحديث الصفحة بلا إعادة بناء. |
| N1d | تعيين أول أدمن للمستأجر. | ✅ POST /platform/users/role صار يُنشئ المستخدم إن لم يوجد. كان يشترط دخولاً سابقاً، وهذه بيضة ودجاجة: مستأجر مزوَّد حديثاً بلا مستخدمين، فلا سبيل لصنع أول أدمن — أي أن لوحته لا يمكن الدخول إليها إطلاقاً. زر «تعيين أدمن» في لوحة السوبر-أدمن. |
| N2 | رفع اللوغو + توليد الأيقونات/splash. | ✅ الرفع مع تحقّق (image-meta.ts: PNG/JPEG · حدّ أدنى 512×512 · مربّع ±5٪ · سقف 5MB) — لوغو صغير أو مستطيل كان يُنتج أيقونة ممطوطة في كل تطبيقات المستأجر ولا يُكتشف إلا بعد بناءٍ ونشر. لم نُدخل sharp: التوليد نفسه شغل flutter_launcher_icons في N3، والباك إند لا يحتاج إلا التحقّق (قراءة ترويسة بلا اعتمادية). زر رفع في اللوحة. |
| N3 | سكربت توليد التطبيق الواحد: bundle ID · أيقونات/splash من اللوغو · FCM · إضافات Kotlin/C++ الأصيلة (overlay · method channels · NDK) · بناء · Shorebird. | 🔵 scripts/generate-tenant-app.sh — يجلب المانيفست ويضبط الهيكل؛ خطوات فلاتر موسومة [Q] تُوصَل عند بناء المجموعة Q (المشروع غير موجود بعد). ✅ يولّد الآن lib/core/build_config.dart بأعلام const (§1.5) · يضبط applicationId وPRODUCT_BUNDLE_IDENTIFIER وandroid:label · يجلب اللوغو ويكتب إعدادات flutter_launcher_icons/flutter_native_splash · و--build اختياري يشغّل Shorebird. |
| N4 | لوحة أدمن المستأجر (ويب): سائقون (اعتماد) · رحلات · مراجعة وثائق · سحوبات (تحويل/فشل). | ✅ dashboards/admin-web/index.html + نقاط سرد إدارية (/drivers/admin/list · /trips/admin/list · /payouts/admin/list خلف RolesGuard admin/dispatcher). التعرفة والتقارير تُضاف مع L. |
| N5 | لوحة خدمة العملاء (ويب): بحث مستخدم برقمه (فهرس أعمى) · رحلاته · تفاصيل رحلة بالمعرّف. | ✅ dashboards/service-web/index.html + GET /admin/users/search · /trips/admin/list?rider=. الشكاوى تحتاج وحدة complaints (لا توجد بعد — بند لاحق). |
| N6 | كتالوج تسعير الميزات (قرار المالك 2026-07-19، أُعيد تأكيده مع قائمة الميزات الكاملة — 27-feature-catalog): جدول feature_catalog — المفتاح · الاسم العربي · الفئة (نواة/باقة/add-on) · سعر شهري · رسم إعداد · الوصف — والسوبر-أدمن يحرّر الأسعار من اللوحة. يوسّع K2: الكتالوج نفسه يغذّي الاستحقاقات الافتراضية والتسعير معاً. الإضافات المسعّرة أولاً: استخبار السوق · البوتات/التسويق · التسعير الديناميكي · المواصلات · المفاوض · شرائح السائقين · تأمين السائق. | ⬜ |
| N7 | مولّد عرض السعر (الفوترة التعاقدية): في لوحة السوبر-أدمن — اختيار باقة + إضافات ⇒ عرض سعر مجمّع (إعداد مرة واحدة + شهري) يُطبع/يُرسل للعميل عند التعاقد. عند الاعتماد: تُكتب tenants.features آلياً من البنود المختارة (تكامل K3 — لا إدخال يدوي مزدوج ينسى ميزة) + سجل اشتراك شهري يظهر في overview (N1b). | ⬜ |
مصادقة اللوحتين: هاتف + OTP → JWT بدور admin/dispatcher (نفس تدفّق الموبايل). كل الحماية على السيرفر (RolesGuard) — الواجهة عرض فقط. الوصول للوحة معيَّن بـ?tenant=<slug>.
اختبار الحراسة: E2E يثبت أن السائق/الراكب (غير أدمن) يُرفضان من كل النقاط الإدارية (403).
اختبار: backend/scripts/provision-test.mjs (يتطلّب PLATFORM_SECRET) — يثبت الحارس، التزويد، تصفية الدفع، الاستحقاقات، والمانيفست.
المجموعة O — التحليلات والمواصلات والتسويق
| # | البند |
|---|---|
| O1 | تحليل بيانات المواقع: driver_tracks (مبني في H) → خرائط حرارية · تنبّؤ الطلب · سلوك السائق (H6/H7 المؤجَّلتان). |
| O2 | نظام المواصلات (transit + وضع الباص): خطوط · محطات · بثّ موقع الباص منفصل. add-on. 🔵 microservice مبني (backend-transit/ منفصل بقاعدته — f30209b + 4aeab52) + لوحة مشرف. الناقص: التكامل مع تطبيقي الراكب/السائق + كرونات transit الثلاثة (27 §4). |
| O3 | محرّك التسويق (marketing_engine): بوتات آلية · مولّد تعليقات Gemini · مهام مجدولة · تقارير. add-on. |
| O4 | البوتات (socialBot · android_bot): نسخ + تهيئة كـadd-ons مدفوعة خلف الاستحقاقات. |
| O5 | مراجعة المهام المجدولة (cron) وترتيبها — قرار المالك 2026-07-18. ✅ الجرد اكتمل (27 §4 — 24 كروناً بجدولتها من مستودع سيرو نفسه، ومنها فجوة cron_ride_timeout = R1). التوحيد على BullMQ نفسه ⬜. تُجرد كل المهام الدورية (تسويات · تقارير · تجميع التقييمات · تنظيف · استخبار السوق والأخبار) في مكان واحد بجدولة موحّدة عبر BullMQ (بادئة tripz_). المطلوب: مهمة واحدة لا تعمل مرتين عند تشغيل أكثر من نسخة، وسجلّ تنفيذ يُظهر آخر نجاح/فشل — لا مهام صامتة. |
المجموعة P — إكمال المدفوعات (بوابات حقيقية) 💰
تُقرأ 24-tenant-wallet-revenue أولاً — فلسفة المال (إيراد مقابل أمانة) تحكم كل بند هنا.
| # | البند | الحالة |
|---|---|---|
| P0 | محفظتا المستأجر: tenant_wallet (إيراد) وtenant_pending (أمانات) كدفترين مضافَين فقط. الفصل بمحفظتين لا بحقل حالة — استعلامٌ ينسى الشرط يجعل المالك يسحب من مال الركّاب. |
✅ مبني بالكود (b1a060c — modules/tenant-wallet) |
| P1 | بوابات فعلية: PayMob (مصر) · CliQ (الأردن) · MTN/SyriaTel/شام كاش (سوريا) — جدول لكل وسيلة + محوّل موحّد. | 🔵 PayMob + cash + invoice عبر payment-gateway.registry (d4ac38c، مع إغلاق ثغرة webhook). CliQ · MTN/SyriaTel · شام كاش ⬜ |
| P2 | تسوية بالرسائل (كليك/شام كاش بلا API): تطبيق أندرويد يرفع الرسالة خاماً → webhook → استخراج بـGemini → مطابقة فاتورة. تفرّد على مرجع العملية، وطابور مراجعة لما لا يُطابَق. | ✅ مبني بالكود (da035e4 — sms-settlement.service + raw_sms + integrations/gemini) |
| P3 | رسم العملية إيراداً: 35 ل.س · 5 ج.م · 20 قرشاً — من إعداد المستأجر لا من الكود (سيرو كتب الرقم مرتين فتناقضا وسرّب مالاً). | ✅ (b1a060c — transaction-fee.ts + spec) |
| P4 | تقارير المستأجر: الدخل حسب الوسيلة/اليوم · شحن السائقين مقابل الأمانات · العمولات · المعلّق غير المسوّى. | ⬜ |
| P5 | تصحيح revenue في /admin/overview: يحسب عمولة الرحلات فقط؛ الإيراد الحقيقي = عمولة الرحلات + شحن السائقين + رسوم العمليات، والأمانات تُستثنى. |
✅ (b1a060c) |
ملحق P (2026-07-18، غير مخطط أصلاً): وحدة billing كاملة لاشتراكات المستأجرين أنفسهم (SaaS):
tenant-subscription+superadmin-payment+ webhook PayMob + اعتماد حوالة بنكية (d239f51). هذا نصف N6/N7 العملي — الناقص كتالوج الأسعار والحاسبة.
المجموعة Q — تطبيق فلاتر (إعادة بناء كاملة) 📱
إعادة استعمال الأصيل الثابت (Kotlin/iOS من التطبيق القديم Ride/Tripz)، وإعادة بناء Dart من الصفر بـCubit+Bloc (لا GetX). راجع tripz-mobile-store-identity لمعرّفات المتاجر التي يجب الحفاظ عليها.
📜 القانون المُلزِم: 23-flutter-conventions — يُقرأ كاملاً قبل أي كود Dart. الحالة (2026-07-18): هيكل التطبيقين متطابق حرفياً (
core/+features/auth+features/home)؛ Dart القديم (GetX) أُزيل من السائق مع الإبقاء على الأصيل والإضافات وشهادات التوقيع وShorebird وFirebase. طبقة الشبكة تُرسلx-device-idوتجدّد التوكن عند 401 مرة واحدة. الحزم موحّدة بين التطبيقين والـAPI صار https حصراً (usesCleartextTraffic=falseفي الاثنين).
| # | البند |
|---|---|
| Q1 | الأساس: splash · onboarding · login (هاتف+OTP، بلا كلمة مرور) · الخريطة (flutter_map + بلاطات انطلق). |
| Q2 | الراكب: صفحة الطلب · اختيار الوجهة/التوقفات · widgets الرحلة · تتبّع السائق حياً · الدفع · التقييم (شاشة إجبارية عند وجود رحلة معلّقة). |
| Q3 | السائق: overlay العرض · قبول · widgets الرحلة · متحكّم الموقع (تسجيل 3ث/رفع دفعات/واعٍ للبطارية — نمط سيرو) · حيوية الوجه · الرصيد/الشحن. |
| Q4 | الخرائط المتقدّمة: خريطة حرارية · خريطة تنبّؤية (من O1). |
| Q5 | البنية التحتية للتطبيق: طبقة الشبكة (توقيع HMAC · x-device-id) · country pack ديناميكي · flavors · طبقتا الإعداد وأعلام const حسب §1.5 · موديولات feature-first تُسجَّل حسب العلم. |
| Q6 | نظام التصميم الثابت — 26-flutter-design-system (قرار المالك 2026-07-19): tokens · ثيم ليلي/نهاري من بذرة المستأجر · خطوط ثابتة (Inter + IBM Plex Sans Arabic مضمّنة محلياً) · اتجاه وخط يتبعان اللغة · TripzScaffold + عدة مكونات core/ui/ · ARB للترجمة. يُبنى قبل شاشات Q1–Q3 — ترتيب البناء في 26 §11. |
3. ترتيب التنفيذ المقترح
- L (التسعير) — يكمل النواة المالية، باك إند صرف، سريع.
- N ⭐ (السوبر-أدمن + توليد التطبيق) — الهدف الأساسي؛ يجعل المنتج قابلاً للبيع لمستأجر جديد.
- Q (فلاتر) — بالتوازي مع N، لأنه أطول جزء.
- M (ميزات متقدّمة) · P (بوابات) · O (تحليلات/بوتات) — add-ons تُباع تِباعاً.
4. ما لا أعرفه بعد (أحتاج دراسة أعمق قبل تنفيذ كل مجموعة)
- تفاصيل
pricing-engine(خوارزميات surge الفعلية) — قبل L4. - بروتوكول
intaleq_mapsوبلاطات انطلق للـflutter_map — قبل Q1. - تفاصيل إضافات Kotlin/C++ (overlay/NDK) وربطها بـbundle ID — قبل N3.
- API بوابات الدفع الفعلية (PayMob/CliQ/MTN) — قبل P1.
← ذو صلة: 17-backend-backlog · 05-pricing-billing · 06-tenant-model · 19-entitlements-licensing · 20-tls