"""Router API pour les boutiques.""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.repositories.shop import ShopRepository from app.schemas.common import PaginatedResponse, SuccessResponse from app.schemas.shop import ( ShopCreate, ShopResponse, ShopUpdate, ShopWithItemCount, ) router = APIRouter(prefix="/shops", tags=["Shops"]) @router.get("", response_model=PaginatedResponse[ShopWithItemCount]) async def list_shops( page: int = 1, page_size: int = 20, db: AsyncSession = Depends(get_db), ) -> PaginatedResponse[ShopWithItemCount]: """Liste toutes les boutiques avec le nombre d'objets.""" repo = ShopRepository(db) skip = (page - 1) * page_size shops_with_count = await repo.get_all_with_item_count(skip=skip, limit=page_size) total = await repo.count() items = [ ShopWithItemCount( id=shop.id, name=shop.name, description=shop.description, url=shop.url, address=shop.address, created_at=shop.created_at, updated_at=shop.updated_at, item_count=count, ) for shop, count in shops_with_count ] return PaginatedResponse.create(items=items, total=total, page=page, page_size=page_size) @router.get("/{shop_id}", response_model=ShopWithItemCount) async def get_shop( shop_id: int, db: AsyncSession = Depends(get_db), ) -> ShopWithItemCount: """Récupère une boutique par son ID.""" repo = ShopRepository(db) result = await repo.get_with_item_count(shop_id) if result is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Boutique {shop_id} non trouvée", ) shop, item_count = result return ShopWithItemCount( id=shop.id, name=shop.name, description=shop.description, url=shop.url, address=shop.address, created_at=shop.created_at, updated_at=shop.updated_at, item_count=item_count, ) @router.post("", response_model=ShopResponse, status_code=status.HTTP_201_CREATED) async def create_shop( data: ShopCreate, db: AsyncSession = Depends(get_db), ) -> ShopResponse: """Crée une nouvelle boutique.""" repo = ShopRepository(db) if await repo.name_exists(data.name): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Une boutique avec le nom '{data.name}' existe déjà", ) shop = await repo.create( name=data.name, description=data.description, url=data.url, address=data.address, ) await db.commit() return ShopResponse.model_validate(shop) @router.put("/{shop_id}", response_model=ShopResponse) async def update_shop( shop_id: int, data: ShopUpdate, db: AsyncSession = Depends(get_db), ) -> ShopResponse: """Met à jour une boutique.""" repo = ShopRepository(db) existing = await repo.get(shop_id) if existing is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Boutique {shop_id} non trouvée", ) if data.name and data.name != existing.name: if await repo.name_exists(data.name, exclude_id=shop_id): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Une boutique avec le nom '{data.name}' existe déjà", ) shop = await repo.update( shop_id, name=data.name, description=data.description, url=data.url, address=data.address, ) await db.commit() return ShopResponse.model_validate(shop) @router.delete("/{shop_id}", response_model=SuccessResponse) async def delete_shop( shop_id: int, db: AsyncSession = Depends(get_db), ) -> SuccessResponse: """Supprime une boutique.""" repo = ShopRepository(db) result = await repo.get_with_item_count(shop_id) if result is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Boutique {shop_id} non trouvée", ) shop, item_count = result if item_count > 0: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"Impossible de supprimer : {item_count} objet(s) sont associés à cette boutique", ) await repo.delete(shop_id) await db.commit() return SuccessResponse(message="Boutique supprimée avec succès", id=shop_id)