from uuid import UUID from fastapi import APIRouter, Depends, Response from sqlalchemy.orm import Session from app.api.schemas import OfferIn, OfferOut, PriceIn, PriceOut, page, parse_page from app.errors import AppError from app.persistence.db import get_session from app.persistence.repositories import CatalogRepository from app.services.ingestion_service import IngestionService router = APIRouter(prefix="/api/v1") @router.post("/variants/{variant_id}/offers", status_code=201) def create_offer(variant_id: UUID, payload: OfferIn, session: Session = Depends(get_session)) -> OfferOut: offer = IngestionService(session).create_offer(variant_id, payload.model_dump()) return OfferOut.model_validate(offer.__dict__) @router.get("/offers/{offer_id}") def get_offer(offer_id: UUID, session: Session = Depends(get_session)) -> OfferOut: offer = CatalogRepository(session).get_offer(offer_id) if offer is None: raise AppError(404, "NOT_FOUND", "offer not found", {"id": str(offer_id)}) return OfferOut.model_validate(offer.__dict__) @router.post("/offers/{offer_id}/prices") def add_price(offer_id: UUID, payload: PriceIn, response: Response, session: Session = Depends(get_session)) -> PriceOut: observation, created = IngestionService(session).add_price(offer_id, payload.model_dump()) response.status_code = 201 if created else 200 return PriceOut.model_validate(observation.__dict__) @router.get("/offers/{offer_id}/prices") def list_prices(offer_id: UUID, limit: int = 50, offset: int = 0, session: Session = Depends(get_session)): if CatalogRepository(session).get_offer(offer_id) is None: raise AppError(404, "NOT_FOUND", "offer not found", {"id": str(offer_id)}) limit, offset = parse_page(limit, offset) items, total = CatalogRepository(session).list_observations(offer_id, limit, offset) return page([PriceOut.model_validate(item.__dict__) for item in items], limit, offset, total)