Audit đặt xe + bản đồ · 2026-08-17
Domain: D-RIDES · D-DRIVER · WP: WP-RIDE-AUDIT-BOOKING-01 · WP-SEED-DRIVER-01 · WP-FE-RIDE-SHEET-DRAG-01 · WP-FE-RIDE-MAP-CTRL-01
Surfaces: CON (mobile/) · API (api/)
1. Kết quả smoke
npm run smoke:ride (API local :3011, DB local đã seed):
| # | Check | Trước | Sau |
|---|---|---|---|
| 1 | auth OTP consumer | PASS | PASS |
| 2 | POST /rides/quotes |
PASS | PASS |
| 3 | quote theo tuyến đường thật | FAIL · road 3.06 km = chim bay 3.06 km · welife-haversine |
PASS · road 4.73 km vs chim bay 3.06 km · mapbox |
| 4 | polyline đủ điểm vẽ tuyến | FAIL · 0 điểm | PASS · 166 điểm |
| 5 | ETA hợp lý | PASS · 5 phút (sai) | PASS · 17 phút |
| 6 | options 3 hạng xe | PASS | PASS |
| 7 | POST /rides (CASH) |
PASS | PASS |
| 8 | auto-match gán tài xế ngay | PASS · CONFIRMED | PASS · CONFIRMED |
| 9 | GET /rides/:id có driver brief |
PASS · Lê Thị Ngọc Anh | PASS |
| 10 | driver có ảnh đại diện thật | — (field chưa tồn tại) | PASS · randomuser.me/.../women/44.jpg |
| 11 | driver có biển số + rating | PASS · 51G-123.45 ★4.9 | PASS |
| 12 | GET /rides/:id/tracking |
PASS | PASS |
| 13 | cancel dọn dữ liệu | PASS | PASS |
Tổng: 13/13 PASS (trước: 11 PASS / 2 FAIL).
Ảnh hưởng giá: cùng chuyến Bến Thành → Landmark 81, CAR = 27.300đ (chim bay) vs 35.670đ (tuyến thật) → sai −23% doanh thu/chuyến.
2. Lỗi gốc: routing chết âm thầm → chim bay
Log API: Mapbox directions failed → next: fetch failed + OSRM directions failed → Haversine: fetch failed, trong khi curl cùng URL trả 200.
Nguyên nhân: máy dev có TLS inspection (proxy/AV) → fetch của Node báo UNABLE_TO_VERIFY_LEAF_SIGNATURE. RoutesService.directions bắt lỗi và fallback Haversine im lặng, nên:
distanceMeters/durationSec/fareAmounttính theo đường thẳng.polylinechỉ là nội suy thẳng → FE (pickRoadPolyline) loại bỏ → map không vẽ tuyến.
Đây chính là mục "Routing OSRM/Mapbox PARTIAL — BLOCKED_EXTERNAL" trong FUNCTIONAL-AUDIT-2026-08-06: không phải blocker bên ngoài, mà là TLS trust store của máy dev.
Đã sửa:
| Lớp | Thay đổi |
|---|---|
scripts/api-dev.mjs (mới) |
npm run api:dev tự thêm NODE_OPTIONS=--use-system-ca khi Node hỗ trợ (không hạ TLS verify) |
api/src/modules/routing/routing.service.ts |
fetchJson gắn mã lỗi + gợi ý TLS vào message thay vì fetch failed trần |
mobile/.../RideQuoteScreen.tsx |
Không có tuyến thật → hiện rõ "Giá tạm tính theo đường thẳng" thay vì im lặng |
3. Tài xế trong DB (trước: rỗng)
api/prisma/seed.ts chưa từng seed tài xế → auto-match luôn no_driver_nearby trên máy mới; chỉ có 1 tài xế do smoke tạo, không ảnh đại diện.
Thêm seedDrivers(): 6 tài xế APPROVED + isOnline + GPS quanh Q1 (BIKE ×3, CAR ×2, CAR_PLUS ×1), rating 4.6–5.0, ảnh đại diện thật; backfill avatarUrl cho user role DRIVER còn thiếu.
| Tài xế | Xe | Biển số | GPS | ★ |
|---|---|---|---|---|
| Nguyễn Văn Hùng | BIKE | 59H1-234.56 | 10.7795, 106.6982 | 4.9 |
| Trần Minh Tuấn | BIKE | 59F1-678.90 | 10.7731, 106.7041 | 4.8 |
| Đặng Thị Mai | BIKE | 59M1-345.67 | 10.7684, 106.7032 | 4.6 |
| Lê Thị Ngọc Anh | CAR | 51G-123.45 | 10.7812, 106.7015 | 4.9 |
| Phạm Quốc Bảo | CAR | 51H-456.78 | 10.7702, 106.6978 | 4.7 |
| Võ Thành Danh | CAR_PLUS | 51K-789.01 | 10.7758, 106.7086 | 5.0 |
GET /rides/:id trước đây không trả ảnh (dù User.avatarUrl có sẵn) → driverBrief thêm avatarUrl, RideDetailScreen render Image (fallback icon khi null).
Verify: npm run drivers:check.
4. Bản đồ · thanh trượt
| Hạng mục | Trước | Sau |
|---|---|---|
| Sheet kéo được | Chỉ RideHome (PanResponder viết tay) |
RideHome · RideQuote · RideMatching · RideDetail qua hook chung useOverlaySheetDrag |
| Mức snap | cứng 0.30 / 0.72 | theo màn: quote 0.48↔0.78 · matching 0.44↔0.80 · detail 0.52↔0.84 (overlaySheetLevels) |
| Map ở RideDetail | cố định height={240} |
full màn, sheet phủ lên, kéo để xem nhiều map |
| Nút bản đồ | không có (showsMyLocationButton={false}) |
showControls: bám tài xế · về điểm đón · xem toàn tuyến |
| Nội dung sheet dài | tràn màn (không scroll) | ScrollView trong sheet |
5. Còn lại (không nằm trong turn này)
- GPS tài xế lưu in-memory (
RidesRealtimeService) → restart API mất vị trí cuối; FE bù bằng polltracking4s. RideMatchingchưa listenride:location(chỉride:status) — chấp nhận được vì match xong là chuyển sangRideDetail.- Seed tài xế
isOnline=truecố định; chưa có job hạ online khi tài xế thật lâu không ping. - Ảnh đại diện dùng
randomuser.me; muốn offline hoàn toàn thì re-host MinIO nhưnpm run demo:map-images.
6. Cách chạy lại
npm run infra:up
cd api && npm run prisma:seed && cd ..
npm run api:dev # tự bật --use-system-ca
npm run smoke:ride # 13 checks
npm run drivers:check # danh sách tài xế + avatar