P2: ride types + class-aware matching + round-trip + dispatch + wallet + FCM + WS live location/WebRTC

- ride-types: per-tenant catalog (economy/comfort/electric/family_van/women/scooter), seeded
- matching now class-scoped (geo:drivers:{tenant}:{class}); trips match by requested type
- trips: is_round_trip (doubles distance for fare) + payment_method + wallet settlement on paid
- dispatch: operator creates trip for phone customer (role-guarded)
- wallet: balance + credit/debit + txns + self topup; wallet-paid trips settle rider→driver
- notifications: FCM device tokens + best-effort push (assign event)
- realtime: trip:join, live driver:location broadcast, WebRTC call signaling (offer/answer/ice/end)
- migration InitP2 (ride_types, wallets, wallet_txns, device_tokens, trips.is_round_trip)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 17:39:56 +03:00
co-authored by Claude Opus 4.8
parent ccb80d9e53
commit 16df6258c1
30 changed files with 737 additions and 27 deletions
@@ -73,9 +73,15 @@ export class DriversService {
driver.is_online = online;
await this.repo.save(driver);
if (!online) {
await this.matching.removeDriver(tenantId, driver.id);
await this.matching.removeDriver(tenantId, driver.service_class, driver.id);
} else if (driver.last_lat != null && driver.last_lng != null) {
await this.matching.addDriver(tenantId, driver.id, driver.last_lat, driver.last_lng);
await this.matching.addDriver(
tenantId,
driver.service_class,
driver.id,
driver.last_lat,
driver.last_lng,
);
}
return driver;
}
@@ -93,7 +99,7 @@ export class DriversService {
driver.last_lng = lng;
await this.repo.save(driver);
if (driver.is_online) {
await this.matching.addDriver(tenantId, driver.id, lat, lng);
await this.matching.addDriver(tenantId, driver.service_class, driver.id, lat, lng);
}
return { ok: true };
}