from pydantic import BaseModel, field_serializer from typing import Optional, Dict, Any from datetime import datetime # --- Photo Response --- class PhotoResponse(BaseModel): """Photo metadata for item responses.""" thumbnail_url: str full_url: str uploaded_at: datetime # --- Categories --- class CategoryBase(BaseModel): name: str description: Optional[str] = None class CategoryCreate(CategoryBase): pass class Category(CategoryBase): id: int class Config: from_attributes = True # --- Colors --- class ColorBase(BaseModel): name: str class ColorCreate(ColorBase): pass class Color(ColorBase): id: int class Config: from_attributes = True # --- Items --- class ItemBase(BaseModel): name: str category: str category_id: Optional[int] = None type: Optional[str] = None barcode: str part_number: Optional[str] = None color: Optional[str] = None description: Optional[str] = None connector: Optional[str] = None size: Optional[str] = None ocr_text: Optional[str] = None specs: Optional[str] = None quantity: float = 0.0 min_quantity: float = 1.0 image_url: Optional[str] = None box_label: Optional[str] = None labels_data: Optional[str] = None photo_path: Optional[str] = None photo_thumbnail_path: Optional[str] = None photo_upload_date: Optional[datetime] = None class ItemCreate(ItemBase): extracted_image_bytes: Optional[str] = None # Base64-encoded image data from AI extraction image_processing: Optional[Dict[str, Any]] = None # {crop_bounds, rotation_degrees, confidence} from AI class Item(ItemBase): id: int photo_path: Optional[str] = None photo_thumbnail_path: Optional[str] = None photo_upload_date: Optional[datetime] = None photo: Optional[PhotoResponse] = None class Config: from_attributes = True @field_serializer('photo_upload_date', when_used='json') def serialize_photo_upload_date(self, value: Optional[datetime]) -> Optional[str]: """Serialize datetime to ISO format string for JSON.""" return value.isoformat() if value else None