"""Routing repositories — Phase 10.6.""" from __future__ import annotations from typing import Sequence from uuid import UUID from sqlalchemy import func, select from app.models.routing import OptimizationRun, RoutePlan, RouteStop from app.repositories.base import TenantBaseRepository from app.specifications.routing import OptimizationRunListSpec, RoutePlanListSpec class RoutePlanRepository(TenantBaseRepository[RoutePlan]): model = RoutePlan async def get_by_code(self, tenant_id: UUID, code: str) -> RoutePlan | 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: RoutePlanListSpec | None = None, ) -> Sequence[RoutePlan]: 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: RoutePlanListSpec | 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 RouteStopRepository(TenantBaseRepository[RouteStop]): model = RouteStop async def list_for_plan( self, tenant_id: UUID, route_plan_id: UUID ) -> Sequence[RouteStop]: stmt = ( select(self.model) .where( self.model.tenant_id == tenant_id, self.model.route_plan_id == route_plan_id, self.model.is_deleted.is_(False), ) .order_by(self.model.sequence.asc()) ) result = await self.session.execute(stmt) return result.scalars().all() class OptimizationRunRepository(TenantBaseRepository[OptimizationRun]): model = OptimizationRun async def list_filtered( self, tenant_id: UUID, *, offset: int = 0, limit: int = 20, spec: OptimizationRunListSpec | None = None, ) -> Sequence[OptimizationRun]: 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: OptimizationRunListSpec | 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())