"""Fleet repositories — Phase 10.2.""" from __future__ import annotations from typing import Sequence from uuid import UUID from sqlalchemy import func, select from app.models.fleet import Fleet, Vehicle, VehicleAssignment, VehicleType from app.models.types import VehicleAssignmentStatus from app.repositories.base import TenantBaseRepository from app.specifications.fleet import FleetListSpec, VehicleListSpec, VehicleTypeListSpec class FleetRepository(TenantBaseRepository[Fleet]): model = Fleet async def get_by_code(self, tenant_id: UUID, code: str) -> Fleet | None: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.code == code, self.model.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_filtered( self, tenant_id: UUID, *, offset: int = 0, limit: int = 20, spec: FleetListSpec | None = None, ) -> Sequence[Fleet]: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: stmt = spec.apply(stmt) else: stmt = stmt.order_by(self.model.created_at.desc()) stmt = stmt.offset(offset).limit(limit) result = await self.session.execute(stmt) return result.scalars().all() async def count_filtered( self, tenant_id: UUID, *, spec: FleetListSpec | None = None ) -> int: stmt = select(func.count()).select_from(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: clauses = spec.filter_clauses() if clauses: stmt = stmt.where(*clauses) result = await self.session.execute(stmt) return int(result.scalar_one()) class VehicleTypeRepository(TenantBaseRepository[VehicleType]): model = VehicleType async def get_by_code(self, tenant_id: UUID, code: str) -> VehicleType | None: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.code == code, self.model.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_filtered( self, tenant_id: UUID, *, offset: int = 0, limit: int = 20, spec: VehicleTypeListSpec | None = None, ) -> Sequence[VehicleType]: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: stmt = spec.apply(stmt) else: stmt = stmt.order_by(self.model.created_at.desc()) stmt = stmt.offset(offset).limit(limit) result = await self.session.execute(stmt) return result.scalars().all() async def count_filtered( self, tenant_id: UUID, *, spec: VehicleTypeListSpec | None = None ) -> int: stmt = select(func.count()).select_from(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: clauses = spec.filter_clauses() if clauses: stmt = stmt.where(*clauses) result = await self.session.execute(stmt) return int(result.scalar_one()) class VehicleRepository(TenantBaseRepository[Vehicle]): model = Vehicle async def get_by_code(self, tenant_id: UUID, code: str) -> Vehicle | None: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.code == code, self.model.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_filtered( self, tenant_id: UUID, *, offset: int = 0, limit: int = 20, spec: VehicleListSpec | None = None, ) -> Sequence[Vehicle]: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: stmt = spec.apply(stmt) else: stmt = stmt.order_by(self.model.created_at.desc()) stmt = stmt.offset(offset).limit(limit) result = await self.session.execute(stmt) return result.scalars().all() async def count_filtered( self, tenant_id: UUID, *, spec: VehicleListSpec | None = None ) -> int: stmt = select(func.count()).select_from(self.model).where( self.model.tenant_id == tenant_id, self.model.is_deleted.is_(False), ) if spec is not None: clauses = spec.filter_clauses() if clauses: stmt = stmt.where(*clauses) result = await self.session.execute(stmt) return int(result.scalar_one()) class VehicleAssignmentRepository(TenantBaseRepository[VehicleAssignment]): model = VehicleAssignment async def list_for_vehicle( self, tenant_id: UUID, vehicle_id: UUID ) -> Sequence[VehicleAssignment]: stmt = ( select(self.model) .where( self.model.tenant_id == tenant_id, self.model.vehicle_id == vehicle_id, self.model.is_deleted.is_(False), ) .order_by(self.model.created_at.desc()) ) result = await self.session.execute(stmt) return result.scalars().all() async def get_active_for_vehicle( self, tenant_id: UUID, vehicle_id: UUID ) -> VehicleAssignment | None: stmt = select(self.model).where( self.model.tenant_id == tenant_id, self.model.vehicle_id == vehicle_id, self.model.status == VehicleAssignmentStatus.ACTIVE, self.model.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none()