Commit Graph
132 Commits
Author SHA1 Message Date
Hamza-Ayed 1243e5a3b2 chore: initialize new database schema and update marketing tool dependencies 2026-08-04 12:30:54 +03:00
Hamza-Ayed 3b0b257528 تعديل منفذ Nginx في env.example 2026-07-29 03:00:35 +03:00
Hamza-Ayed f428b8b300 تحديث ملف .env.example ببيانات قواعد البيانات الجديدة 2026-07-29 02:58:22 +03:00
Hamza-Ayed 5dcdcd8a3a ضبط بورتات الدوكر لتفادي التعارض مع siro 2026-07-29 02:47:03 +03:00
Hamza-Ayed d34550e1ca إضافة الهوية الجديدة Tripz 2026-07-29 02:41:05 +03:00
Hamza-Ayed b9a97effe5 إضافة الهوية الجديدة Tripz 2026-07-29 02:31:04 +03:00
Hamza-AyedandClaude Opus 5 ecbe245b77 fix(driver): ضمّ حزم get و get_storage داخل المستودع
apps/driver كان يشير إلى `../../Intaleq/packages/get` خارج المستودع — وهو
مسار يُحل من apps/driver إلى Tripz/Intaleq/ غير الموجود، فلا يمرّ
`flutter pub get` إطلاقاً. (فجوة docs/30 §2.6.)

ضُمّت نسخة **انطلق** تحديداً (App/Intaleq/packages) لا فرع apps/rider:
الفرعان يختلفان فعلاً — snackbar_controller.dart و get_queue.dart وغيرهما
مختلفة بين النسختين، فاستعارة فرع rider كانت ستغيّر سلوك السائق صامتة.

  apps/driver/packages/get         (3.5 م.ب، 202 ملف dart مع get_storage)
  apps/driver/packages/get_storage
  pubspec: ../../Intaleq/packages/* → ./packages/*  (3 مواضع، منها
  dependency_overrides سطر 142)

المستودع صار مكتفياً ذاتياً: لا تبعية مسار خارج شجرته. لم يُمسّ App/Intaleq.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 05:16:10 +03:00
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
Hamza-AyedandClaude Opus 5 9909d9b4c1 chore: أرشفة تطبيقات ولوحات تريبز التي سيحلّ محلها كود سيرو
استكمال قرار 2026-07-27 (كوميت fff76c9 أرشف الباك إند):
  apps/rider          → apps/rider-archive-cubit
  apps/driver         → apps/driver-archive-cubit
  dashboards/admin-web    → dashboards/admin-web-archive
  dashboards/service-web  → dashboards/service-web-archive

إعادة تسمية بلا تعديل محتوى. rider/driver كانا إعادة بناء Cubit مبنية على
عقد NestJS المؤرشف. admin-web و service-web نموذجان بملف HTML واحد (164 و
128 سطراً) — يحلّ محلهما siro_admin و siro_service المكتملان.

يُحمل من المؤرشف ولا يُعاد اكتشافه: عقد map-saas المثبَّت بالتجربة في
apps/rider-archive-cubit/lib/core/api/ (x-api-key ترويسة، reverse مصفوفة،
route في points) ودرس مسار FCM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 05:12:04 +03:00
Hamza-AyedandClaude Opus 5 fff76c949f chore: أرشفة باك إند NestJS إلى backend-archive
قرار المالك 2026-07-27: الباك إند المعتمد صار باك إند سيرو PHP، ويُنقل
إلى هذا المستودع كنسخة جديدة باسم «انطلق» على api.intaleqapp.com.

backend/ → backend-archive/ (305 ملفاً، إعادة تسمية بلا تعديل محتوى)
+ README-ARCHIVE.md يوضّح سبب الأرشفة وسبب عدم الحذف: scripts/e2e-test.mjs
  هو أدق توثيق سلوكي لدورة الرحلة كاملة، ويبقى مرجعاً عند بناء الوحدات
  الناقصة في باك إند PHP (المحفظتان · الاستحقاقات · محرّك التسعير · الوحدات).

مسارات backend/ في docs/*.md لم تُعدَّل عمداً — سجلّ تاريخي.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 04:54:35 +03:00
Hamza-AyedandClaude Opus 5 75b80bd299 refactor(marketing): تفكيك الموقع إلى وحدات + توحيد الباقات الثلاث
- marketing: index.html من 2274 إلى 775 سطراً، والباقي إلى
  styles/ (tokens·base·components·sections·responsive) و
  js/ (app·i18n·calculator·analytics) و i18n/ بخمس لغات
  (ar·en·fr·es·tr) عبر سمة data-i18n.
- docs/05 + docs/33 + لوحة السوبر-أدمن: الباقات صارت ثلاثاً
  (إطلاق · نمو · سيادة) بدل الأربع، وتحديث docs/31 بما يطابقها.
- docs/36: توثيق سيرو إكسبرس للتوصيل.
- تنظيف استيرادات غير مستعملة في apps/rider و apps/driver.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 04:53:19 +03:00
Hamza-Ayed 5675a4d928 fix: update marketing page content and formatting in index.html 2026-07-24 23:55:29 +03:00
Hamza-Ayed 7ab18358ce Embed dedicated MyHub operations video and Dispatch Reseller partner video 2026-07-24 22:51:55 +03:00
Hamza-Ayed 1434b1da39 Direct standalone Gemini and Meta Graph API in studio.html 2026-07-24 17:52:08 +03:00
Hamza-Ayed 1f27d3ab7b Update to gemini-flash-lite-latest & dynamic AI image generation 2026-07-24 17:23:50 +03:00
Hamza-Ayed 7c05b0d9ab Direct standalone Gemini and Meta Graph API in studio.html 2026-07-24 17:18:11 +03:00
Hamza-Ayed 6fe7a093a9 Add Web AI Marketing Studio with Voice Recorder and Live Facebook Preview 2026-07-24 17:04:44 +03:00
Hamza-Ayed 16d7ec0364 Add NestJS Admin Facebook Publishing API with Image Support 2026-07-24 17:00:52 +03:00
Hamza-Ayed 0b9dca5d75 Direct PAGE_ID/feed endpoint update 2026-07-24 16:51:33 +03:00
Hamza-Ayed b47102f36b Support scripts/.env path 2026-07-24 16:49:21 +03:00
Hamza-Ayed eacd71349e Support scripts/.env path 2026-07-24 16:44:58 +03:00
Hamza-Ayed b2261d9192 Clean env enforcement & add Gemini AI Post Generator 2026-07-24 16:38:47 +03:00
Hamza-Ayed 4621ede040 Update codebase 2026-07-24 16:18:06 +03:00
Hamza-Ayed ed15bae804 Update codebase 2026-07-24 16:17:10 +03:00
Hamza-Ayed 1515a7bfc9 Dynamic Page ID match 2026-07-24 16:10:19 +03:00
Hamza-Ayed 6d66f33bc3 Dynamic Page ID match 2026-07-24 16:07:06 +03:00
Hamza-Ayed 9995656a84 Update scripts with new Meta Access Token 2026-07-24 16:05:44 +03:00
Hamza-Ayed 075e21e557 Update publish-now script with auto Page Token resolution 2026-07-24 16:00:32 +03:00
Hamza-Ayed 535d5b40ef Update codebase 2026-07-24 15:58:57 +03:00
Hamza-Ayed f9b55ddf94 docs: update siro audit documentation with recent findings 2026-07-24 05:37:13 +03:00
Hamza-Ayed 1be74d764d docs: update marketing index and audit documentation for the Siro release 2026-07-24 05:37:08 +03:00
Hamza-AyedandClaude Opus 4.8 7b02b27d92 feat(marketing): consent-gated measurement layer + pricing-intelligence legal brief
البند ٢ — استخبارات التسعير (docs/35 جديد):
- توصيف تقني دقيق من كود سيرو: المصدر ليس "كشط أسعار معلنة" بل
  بوت أندرويد على أجهزة حقيقية يشغّل 7 تطبيقات منافسة مُسمّاة
  بمعرّف الحزمة (standalone_worker.php:665) بدفعات حتى 100 مهمة
- فصل ثلاثة أخطار مستقلة: الوصول الآلي · قانون المنافسة · البيانات
- الخطر الأكبر (لم يكن موثّقاً): بيع المحرّك لمشغّلَين في نفس المدينة
  = ترتيب hub-and-spoke تقع مسؤوليته على المحور أي Tripz
- ضابط مقترح: مشغّل واحد لكل مدينة، في العقد وفي الكود
- تنظيف صياغة الموقع: صفر أسماء منافسين، وحُذفت "اعرف كيف يسعّر
  منافسك قبل أن يعرف هو" لأنها تصلح دليل نيّة في نزاع

البند ٣ — طبقة القياس (docs/32 §5):
- شريط موافقة بأربع لغات، الرفض بنفس بروز القبول
- البكسل لا يُحمَّل قبل الموافقة (مطلوب لزوّار الاتحاد الأوروبي:
  الموقع بالفرنسية والإسبانية)
- 8 أحداث تغطي القمع كاملاً حتى Lead بمعامل القناة
- PIXEL_ID فارغ عمداً: لا شيء ينكسر ولا شيء يُقاس حتى يُملأ

تحقُّق: صفر أخطاء console · صفر عناصر i18n فارغة في اللغات الأربع ·
fbq غير معرّف قبل الموافقة · الأحداث تُطلق بعدها

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 05:14:28 +03:00
Hamza-AyedandClaude Opus 4.8 8cbaa89642 refactor(pricing): restructure add-ons 7→3, safety+payments to core, transit as own product line
تنفيذ توصيات المراجعة النقدية التي لم تُنفَّذ في الجولة السابقة:

- حذف «الأمان والامتثال» $79 كوحدة → النواة (سبب قانوني: بيع الأمان
  يُنشئ وثيقة إدانة يوم يقع حادث عند مستأجر لم يشترِ الوحدة)
- حذف «حزمة المدفوعات» $99 → النواة (الحلقة الأساسية لا ترقية)
- دمج «ذكاء الأسطول» $99 في باقة أسطول+ (تناقض تسموي)
- «المواصلات» تخرج من الشبكة → قسم #transit مستقل بجمهوره وCTA خاص
- شريط .core-band يعرض ما لا يُباع كحجة بيع
- إصلاح الانقلاب السعري: كانت سيادة $879 أرخص من أسطول+ محمّلة $903
  الآن: علامة $585 < أسطول+ $599 < سيادة $879
- الشارات ← «متاح الآن» بتأكيد المالك أنها تعمل في إنتاج سيرو
- تصحيح سردية docs/33 §0 المستحيلة (كانت تبني التوسّع على باقة
  تنتهي بعد 90 يوماً)

الترجمات مكتملة في اللغات الأربع — تحقُّق برمجي: صفر عناصر فارغة.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 05:06:40 +03:00
Hamza-AyedandClaude Opus 4.8 822e4e8724 refactor: correct add-ons pricing, remove duplicate AI section, mark all modules as coming-soon
✨ تحسينات رئيسية:

1️⃣ إصلاحات توثيقية (docs/21, docs/33):
   - S18 ليست مشكلة — النظام يفرض سحب الرصيد الكامل فقط
   - إضافة تنبيه حالة عن عدم جاهزية الوحدات

2️⃣ إصلاحات الموقع (marketing/index.html):
   - حذف قسم #ai-modules المكرر (التكرار المحرج)
   - إضافة رابط «الإضافات» في القائمة العلوية (4 لغات)
   - تغيير جميع الشارات إلى «قريباً الربع القادم» (حماية قانونية)
   - 7 وحدات مدفوعة واضحة مع أسعار + وصف

3️⃣ النموذج التجاري:
   - النواة رخيصة = سلاح اكتساب
   - الوحدات = هامش الربح الحقيقي (land-and-expand)
   - بدون تكرار محرج للزائر

⚠️ الحد الأدنى قبل التسويق:
   - S4 و S5 تُصلح قبل أول استنساخ على سيرفر مستأجر
   - جرد صدق بند بند على إنتاج سيرو

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 04:59:23 +03:00
Hamza-Ayed 213b459912 feat: implement splash and onboarding flows, update app assets, and add project design documentation 2026-07-24 04:15:07 +03:00
Hamza-AyedandClaude Fable 5 9f7bc31408 feat(auth): separate rider/driver identities per phone
Same phone can now hold distinct rider and driver accounts (and wallets)
within a tenant. Unique constraint moves from (tenant, phone_bidx) to
(tenant, phone_bidx, role); login creates/finds the record matching the
app's x-app-role header. Fixes rider-app login returning role:driver for
a phone previously registered as a driver.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 15:21:01 +03:00
Hamza-Ayed c67453aeba feat: configure custom app icons and add splash screen support for Android and iOS 2026-07-19 18:20:41 +03:00
Hamza-Ayed 603f0c676d fix: add missing dependencies in TripsService constructor for tests 2026-07-19 16:47:05 +03:00
Hamza-Ayed e577afdb2c fix: add missing OnModuleInit import in notifications service 2026-07-19 16:43:07 +03:00
Hamza-AyedandClaude Fable 5 eebc2ccfb9 docs(compose): comment the firebase key mount (secret ships via scp, boot survives its absence)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:26:10 +03:00
Hamza-Ayed c4dfeb4c6f feat: implement core architecture, design system, localization, and trip features for both driver and rider apps. 2026-07-19 16:21:58 +03:00
Hamza-Ayed 959e2fa758 Update backend to use firebase-admin SDK for FCM 2026-07-19 16:21:43 +03:00
Hamza-AyedandClaude Opus 4.8 978a7489e6 docs: record the kazan-based pricing rebuild and its server proof
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 02:13:21 +03:00
Hamza-AyedandClaude Opus 4.8 2045896b95 fix(test): expect fixed to be rejected + flush tariff cache before testing
الدورة السابقة أعلنت الفشل والنظام سليم — العطل كان في السكربت:

1. **`fixed` تُرفض بـ400 وهذا هو المطلوب** (أُخرجت من الزرع عمداً)، لكن
   السكربت كان يعدّها فئة متوقَّعة فأسقط التغطية إلى 72/81. صارت في
   `REJECTED_CLASSES`: الرفض يُتحقَّق منه صراحةً، وغيابه هو الفشل.

2. **429 على `send-otp`** (10 لكل 5 دقائق) عند تشغيلتين متتاليتين — يُنتظر
   ويُعاد بدل الإبلاغ عن فشل ليس في النظام.

3. **إبطال كاش التعرفة صار خطوة في الدورة.** `getActive` تكاشي 900 ثانية،
   و**Redis حاوية منفصلة لا تتأثر بإعادة تشغيل الـapi** — وتطبيق
   `tariffs.sql` مباشرةً على القاعدة يتجاوز التطبيق فلا يُبطل شيئاً. النتيجة
   أن النظام خدم أسعاراً قديمة عبر دورتَي نشر كاملتين وهو يعلن النجاح.
   المسح الآن مبنيّ في السكربت لا متروك للتذكّر.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 02:09:05 +03:00
Hamza-Ayed 7e06b1241f feat: add automated stress testing script for driver location tracking and trip lifecycle simulation 2026-07-19 01:51:47 +03:00
Hamza-AyedandClaude Opus 4.8 e9beeb90b4 feat: rebuild pricing on Siro's live kazan table + close two fare leaks
## الأرقام صارت من جدول `kazan` الحيّ لا من تقدير
العمولة 11٪/12٪/14٪ مطابقة حرفياً. وثلاثة تصحيحات على الخام:
- **محورا الأردن مقلوبان**: أعمدة الفئات تحمل سعر الدقيقة (0.043) وأعمدة
  النوافذ سعر الكيلومتر (0.184) — عكس مصر وسوريا. قراءتها كما هي تجعل
  رحلة 27 كم بأقلّ من دينارين.
- **نِسَب الفئات في مصر وسوريا معطوبة**: الكهربائي 0.23 والفان 0.25–0.40 من
  الاقتصادي، أي فان أرخص من اقتصادي. نِسَب الأردن وحدها متماسكة فاعتُمدت.
- سعر الكيلو في مصر 4 جنيهات لا 3.5 (قرار المالك).

## البنية صارت مطابقة لسيرو — وهي ما سيكتب فيه بوت استخبارات الأسعار
سعر الكيلو يتغيّر بالفئة فقط (رقم يعرفه السوق)، وسعر الدقيقة بالنافذة فقط.
**لا فتحة عدّاد** (`startPrice = 0` في كل صفوف سيرو): الحدّ الأدنى أرضية لا
رسم يُضاف — «ما في رحلة أقل من 20 جنيهاً». `fuelPrice` محفوظ كمدخل للبوت.

## تسريبان أغلقهما الاختبار الحيّ (بموافقة المالك)
1. **فئة مجهولة = رحلة مجانية**: `service_class` يأتي من الطلب بلا تحقّق،
   والاستثناء كان يُبتلع فتُنشأ رحلة بـ`quoted_fare = null` ثم تُسوّى بصفر.
   صار الطلب يُرفض بـ400 — الفشل الصريح أأمن من الصامت.
2. **`fixed` لا تُزرع**: سعر ثابت بلا جدول خطوط يعني رقماً واحداً لكل
   الوجهات — أظهر الاختبار رحلة 55.8 كم بـ2.5 ديناراً مقابل 23.2 للاقتصادي.

300 اختبار خضر.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 01:38:20 +03:00
Hamza-AyedandClaude Opus 4.8 f58f2e2e2c chore: gate the test loop behind a real health check
ضاعت دورتان كاملتان على السبب نفسه: تسلسل `up -d && restart && <اختبار>`
كان يشغّل الاختبار بينما الـapi ساقطة، فيظهر خطأ الإقلاع كـ`EAI_AGAIN` داخل
الاختبار — أي في المكان الخطأ تماماً، فيُشخَّص كعطل شبكة أو عطل سكربت.

`verify-and-test.sh` يجعل الدورة واحدة ومحروسة:
- يفحص `.env` قبل الإقلاع ويصلّح التعارض القاتل (OTP_DEV_MODE=true مع
  NODE_ENV=production — حارس `main.ts` ينهي العملية لا يحذّر، فتدخل الحاوية
  حلقة إعادة تشغيل).
- يميّز «حلقة إعادة تشغيل» عن «بطء إقلاع»: الأولى خطأ إقلاع يُطبع سببه من
  اللوغ فوراً بدل انتظار عقيم.
- **لا اختبار قبل ردّ /health فعلياً** — هذه هي البوابة التي كانت غائبة.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 01:11:43 +03:00
Hamza-AyedandClaude Opus 4.8 5838e92980 fix(test): read OTP from Redis instead of requiring OTP_DEV_MODE
نصيحتي السابقة بتفعيل `OTP_DEV_MODE=true` على السيرفر كانت خاطئة: حارس في
`main.ts` يرفض الإقلاع عند `OTP_DEV_MODE=true` مع `NODE_ENV=production`،
فسقطت حاوية الـapi في حلقة إعادة تشغيل وظهر الفشل كـ`EAI_AGAIN` في السكربت.

الحارس صحيح ولا يُضعَف لأجل اختبار: رمز ثابت على سيرفر متاح للإنترنت يعني
أن معرفة رقم هاتف تكفي لدخول أي حساب.

السكربت صار يقرأ الرمز الحقيقي من Redis (`send-otp` يخزّنه قبل محاولة
الإرسال، فيبقى محفوظاً حتى حين يفشل الإرسال لرقم وهمي). عميل RESP أدنى على
`node:net` بلا تبعيات — الحاوية عابرة بلا `node_modules`. المفتاح يستعمل
UUID المستأجر لا الـslug، فتُجلب خريطة الـslug→UUID من `/admin/tenants`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 01:01:51 +03:00
Hamza-AyedandClaude Opus 4.8 7501b0bb33 fix(test): pricing script declared success after doing nothing
عطلان في سكربت التسعير، كشفهما أول تشغيل حقيقي:

1. **إعلان نجاح على العدم** — الأخطر. فشل تسجيل الدخول فجُمع صفر صفّ، فمرّ
   كل تحقّق فراغاً وطبع «الاختبار ناجح». اختبار يعلن النجاح وهو لم ينفّذ
   شيئاً أسوأ من اختبار يفشل: الفشل يُرى. أُضيف حارس عدم + تحقّق تغطية
   (المنفَّذ مقابل المتوقَّع)، وكلاهما يُخرج برمز فشل.

2. **تسجيل الدخول تجاوز `send-otp`** — تجاوز التطوير في `verifyOtp` مشروط
   بـ`OTP_DEV_MODE=true`، وبدونه لا رمز في Redis فيُرفض الثابت 1234 بـ401.
   صار يمرّ بـ`send-otp` ويأخذ `dev_code` من استجابتها، ويقول صراحةً حين
   يكون الوضع التطويري مطفأً بدل أن يفشل بلا تفسير.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 00:54:13 +03:00
Hamza-AyedandClaude Opus 4.8 900c78bb97 fix: seed starting tariffs on tenant provision, not for siro only
ثغرة كُشفت على السيرفر: `SeedService` يزرع التعرفة لـ«سيرو» وحده، فمستأجرا
`intaleq` و`yalla` وُلدا بلا تسعير وبقيا كذلك حتى شُغّل `tariffs.sql` يدوياً.

الأثر صامت لا ظاهر: بلا تعرفة فعّالة لا يُقفل سعر للراكب، ثم تأخذ
`settleFare` القيمة `quoted_fare ?? 0` — رحلة مجانية وعمولة صفر.

`provision()` صار يزرع كل فئات الخدمة بعملة البلد ومنطقته الزمنية. مستودع
التعرفة محقون مباشرةً لا عبر `TariffService`: تلك الوحدة تستورد وحدة
المستأجرين، فالاستيراد المتبادل دورة.

وسطر لوغ الزرع كان يطبع 9 دائماً (ثابتاً لا عدّاداً) فلا يميّز «زُرعت» من
«كانت موجودة» — وهو الفرق الوحيد الذي يُقرأ منه.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 00:45:26 +03:00