import uuid from datetime import datetime, date from decimal import Decimal from typing import Literal from pydantic import BaseModel, ConfigDict, model_validator class StoreCreate(BaseModel): name: str location: str | None = None url: str | None = None store_type: str | None = None class StoreUpdate(BaseModel): name: str | None = None location: str | None = None url: str | None = None store_type: str | None = None class StoreResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID name: str location: str | None url: str | None store_type: str | None class ProductCreate(BaseModel): name: str brand: str | None = None category: str | None = None description: str | None = None default_unit: str | None = None barcode: str | None = None price: Decimal | None = None quantity_per_unit: Decimal | None = None default_store_id: uuid.UUID | None = None image_path: str | None = None thumbnail_path: str | None = None tags: list[str] | None = None class ProductUpdate(BaseModel): name: str | None = None brand: str | None = None category: str | None = None description: str | None = None default_unit: str | None = None barcode: str | None = None price: Decimal | None = None quantity_per_unit: Decimal | None = None default_store_id: uuid.UUID | None = None image_path: str | None = None thumbnail_path: str | None = None tags: list[str] | None = None class ProductResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID name: str brand: str | None category: str | None description: str | None default_unit: str | None barcode: str | None price: Decimal | None quantity_per_unit: Decimal | None default_store_id: uuid.UUID | None frequency_score: int last_purchased_at: date | None avg_interval_days: Decimal | None image_path: str | None thumbnail_path: str | None tags: list[str] | None class ListItemCreate(BaseModel): product_id: uuid.UUID | None = None custom_name: str | None = None quantity: Decimal | None = None unit: str | None = None @model_validator(mode='after') def must_have_name(self) -> 'ListItemCreate': if not self.product_id and not self.custom_name: raise ValueError('product_id ou custom_name requis') return self class ListItemUpdate(BaseModel): is_checked: bool | None = None quantity: Decimal | None = None unit: str | None = None price_recorded: Decimal | None = None class ListItemResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID product_id: uuid.UUID | None custom_name: str | None display_name: str quantity: Decimal | None unit: str | None is_checked: bool price_recorded: Decimal | None carried_over: bool sort_order: int | None class ShoppingListCreate(BaseModel): name: str | None = None store_id: uuid.UUID | None = None week_date: date | None = None class ShoppingListUpdate(BaseModel): name: str | None = None store_id: uuid.UUID | None = None status: Literal['draft', 'active', 'done'] | None = None class ShoppingListResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID name: str | None store_id: uuid.UUID | None week_date: date | None status: str created_at: datetime item_count: int checked_count: int class ShoppingListDetailResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID name: str | None store_id: uuid.UUID | None week_date: date | None status: str created_at: datetime item_count: int checked_count: int items: list[ListItemResponse]