feat: نقطة الرحلة المعلّقة للتقييم + اختبار E2E شامل

نقطة التقييم عند الفتح (طلب المالك): GET /trips/rating/pending يرجع أحدث
رحلة منتهية لم يقيّمها المستخدم (سائقاً أو راكباً) + العدد. التطبيق يناديها
عند كل فتح ليفرض شاشة التقييم قبل رحلة جديدة. TripsService.
finishedForParticipant يجلب المنتهية، و RatingsService.pendingRating يطرح
المقيَّمة باستعلام واحد.

scripts/e2e-test.mjs: اختبار شامل متكامل لكل وظائف الباك إند —
- تسجيل الدخول/الحساب + تطبيع الهاتف (نفس الرقم بصيغتين = حساب واحد)
- إعداد السائق: تقديم + ملف (رقم وطني مشفّر) + مركبة + اعتماد + إعادة دخول
  للحصول على دور driver في التوكن
- الرصيد التشغيلي (مكافأة التسجيل) + عدم الحجب
- اتصال السائق ورفع الموقع (Redis) + المطابقة + /trips/available
- طلب رحلة (تسعير + عرض) + كل الحالات (assigned→...→completed→paid)
- WebSocket: اتصال JWT + رصد trip:update (اختياري، يتخطّى إن غاب
  socket.io-client)
- خصم العمولة من الرصيد التشغيلي عند الإنهاء
- تسوية المحفظة عند paid (خصم الأجرة من الراكب)
- التقييم: رحلة معلّقة → تقييم الطرفين → تُمسح المعلّقة + منع التكرار
- السحب بـOTP خطوتين (طلب بلا خصم → تأكيد بالرمز → حجز)

أوامر التشغيل في docs/15 (مع/بلا WebSocket). يتطلّب OTP_DEV_MODE=true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-17 20:05:29 +03:00
co-authored by Claude Opus 4.8
parent a58f611063
commit feb2a9663d
6 changed files with 387 additions and 2 deletions
+13
View File
@@ -72,3 +72,16 @@ docker run --rm --network tripz-net -e BASE=http://tripz-api:4010/api \
docker run --rm --network tripz-net -e BASE=http://tripz-api:4010/api \
-v /home/tripz-llc/backend/scripts:/s node:22-alpine node /s/location-test.mjs
```
```
# اختبار شامل متكامل (E2E) — كل وظائف الباك إند من الدخول للتقييم للسحب
# مع WebSocket:
docker run --rm --network tripz-net -e BASE=http://tripz-api:4010/api \
-e WS=http://tripz-api:4010 -v /home/tripz-llc/backend/scripts:/s \
node:22-alpine sh -c "cd /tmp && npm i socket.io-client --silent 2>/dev/null; \
NODE_PATH=/tmp/node_modules node /s/e2e-test.mjs"
# أو REST فقط (بلا WebSocket):
docker run --rm --network tripz-net -e BASE=http://tripz-api:4010/api \
-v /home/tripz-llc/backend/scripts:/s node:22-alpine node /s/e2e-test.mjs
# يتطلّب OTP_DEV_MODE=true.
```
+1
View File
@@ -127,6 +127,7 @@
| G4 | **`tenant` في Redis** | كاش `resolve` (slug↔UUID) + `config` مع إبطال عند الإنشاء/التعديل. | ✅ `tenant:{slugOrId}` (TTL ساعة) |
| G5 | **التعرفة و ride-types في Redis** | كاش مع **إبطال صريح** عند إنشاء تعرفة/نوع جديد. | ✅ `tariff:{t}:{city}:{class}` و `ridetypes:{t}` (TTL 15د) |
| G6 | **التقييم بتراكم يومي** | مجموع/عدد في Redis، والقاعدة تُكتب **مرة واحدة يومياً** لكل طرف (حجز الكتابة ذرّي بـLua). التأخير مقصود ليبعد الاحتكاك. **للطرفين معاً**. | ✅ + أُضيف `ratings.target_user_id` و`users.rating` — تقييم السائق للراكب كان يُخزَّن **بلا هدف فلا يُجمَّع أبداً** |
| — | **رحلة معلّقة للتقييم عند الفتح** | `GET /trips/rating/pending` — يرجع أحدث رحلة منتهية لم يقيّمها المستخدم (سائقاً أو راكباً) + العدد. التطبيق يناديها عند كل فتح ليفرض شاشة التقييم قبل رحلة جديدة (طلب المالك). | ✅ |
| — | **كاش الخرائط** | route/reverse/geocode في Redis بإحداثيات مقرَّبة 4 خانات (~11م). | ✅ TTL يوم. لا يُخزَّن الرجوع لخط مستقيم ولا استجابة فاشلة |
| G7 | **سعة Redis** | رصد مساحة أكبر أو Redis منفصل عند الحاجة (خصوصاً dispatch + المواقع). حالياً DB 3 مشترك — راجع docs/14. | ⏳ قرار تشغيلي — يُراجَع بعد المجموعة H |