import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Driver } from './entities/driver.entity'; import { UsersService } from '../users/users.service'; import { MatchingService } from '../matching/matching.service'; @Injectable() export class DriversService { constructor( @InjectRepository(Driver) private readonly repo: Repository, private readonly users: UsersService, private readonly matching: MatchingService, ) {} findByUser(tenantId: string, userId: string): Promise { return this.repo.findOne({ where: { tenant_id: tenantId, user_id: userId } }); } findById(tenantId: string, id: string): Promise { return this.repo.findOne({ where: { tenant_id: tenantId, id } }); } /** تسجيل السائق بالوثائق — ينشئ سجل driver ويرفع دور المستخدم إلى driver. */ async apply( tenantId: string, userId: string, data: Partial, ): Promise { let driver = await this.findByUser(tenantId, userId); if (!driver) { driver = this.repo.create({ tenant_id: tenantId, user_id: userId, service_class: data.service_class ?? 'economy', vehicle_make: data.vehicle_make, vehicle_model: data.vehicle_model, vehicle_plate: data.vehicle_plate, vehicle_color: data.vehicle_color, docs: data.docs ?? {}, verification_status: 'pending', }); driver = await this.repo.save(driver); } // يصير دور المستخدم "driver" (يظهر في التوكن عند إعادة الدخول). await this.users.setRole(tenantId, userId, 'driver'); return driver; } async approve(tenantId: string, driverId: string): Promise { const driver = await this.findById(tenantId, driverId); if (!driver) throw new NotFoundException('Driver not found'); driver.verification_status = 'approved'; return this.repo.save(driver); } /** يبدّل حالة الاتصال؛ عند الاتصال يُضاف لفهرس GEO، وعند الفصل يُزال. */ async setOnline( tenantId: string, userId: string, online: boolean, ): Promise { const driver = await this.findByUser(tenantId, userId); if (!driver) throw new NotFoundException('Driver profile not found'); driver.is_online = online; await this.repo.save(driver); if (!online) { await this.matching.removeDriver(tenantId, 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); } return driver; } /** تحديث الموقع الجاري: Redis GEO + لقطة في Postgres. */ async updateLocation( tenantId: string, userId: string, lat: number, lng: number, ): Promise<{ ok: boolean }> { const driver = await this.findByUser(tenantId, userId); if (!driver) throw new NotFoundException('Driver profile not found'); driver.last_lat = lat; driver.last_lng = lng; await this.repo.save(driver); if (driver.is_online) { await this.matching.addDriver(tenantId, driver.id, lat, lng); } return { ok: true }; } }