# Роуты для авто и статистики. from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import func, select from ..deps import get_persistence from ...storage.db import PersistenceService from ...storage.models import Car, Image from ...storage.schemas import CarRead router = APIRouter() @router.get("/cars") def list_cars( page: int = Query(1, ge=1), per_page: int = Query(20, ge=1, le=100), brand: str | None = None, model: str | None = None, year_min: int | None = None, year_max: int | None = None, is_sold: bool | None = None, persistence: PersistenceService = Depends(get_persistence), ): # Список авто с фильтрами. with persistence.session_scope() as session: query = select(Car) if brand: query = query.where(Car.brand.ilike(f"%{brand}%")) if model: query = query.where(Car.model.ilike(f"%{model}%")) if year_min is not None: query = query.where(Car.year >= year_min) if year_max is not None: query = query.where(Car.year <= year_max) if is_sold is not None: query = query.where(Car.is_sold == is_sold) count_query = select(func.count()).select_from(query.subquery()) total = session.execute(count_query).scalar() or 0 offset = (page - 1) * per_page cars = session.execute( query.order_by(Car.last_seen_at.desc()).offset(offset).limit(per_page) ).scalars().all() return { "total": total, "page": page, "per_page": per_page, "pages": (total + per_page - 1) // per_page if per_page else 0, "items": [CarRead.model_validate(car).model_dump(mode="json") for car in cars], } @router.get("/cars/{car_id}") def get_car( car_id: int, persistence: PersistenceService = Depends(get_persistence), ): # Карточка авто с фото. with persistence.session_scope() as session: car = session.get(Car, car_id) if car is None: raise HTTPException(status_code=404, detail="Car not found") return CarRead.model_validate(car).model_dump(mode="json") @router.get("/cars/by-origin/{origin_id}") def get_car_by_origin( origin_id: str, persistence: PersistenceService = Depends(get_persistence), ): # Поиск по origin_id. with persistence.session_scope() as session: car = session.execute( select(Car).where(Car.origin_id == origin_id) ).scalars().first() if car is None: raise HTTPException(status_code=404, detail="Car not found") return CarRead.model_validate(car).model_dump(mode="json") @router.get("/stats") def get_stats(persistence: PersistenceService = Depends(get_persistence)): # Общая статистика. with persistence.session_scope() as session: total_cars = session.execute(select(func.count(Car.id))).scalar() or 0 total_images = session.execute(select(func.count(Image.id))).scalar() or 0 brands = session.execute( select(Car.brand, func.count(Car.id)) .group_by(Car.brand) .order_by(func.count(Car.id).desc()) .limit(20) ).all() return { "total_cars": total_cars, "total_images": total_images, "top_brands": [{"brand": b, "count": c} for b, c in brands], }