from pydantic import BaseModel from datetime import datetime from typing import Optional, List class CategoryResponse(BaseModel): id: int name: str slug: str description: Optional[str] = None icon: Optional[str] = None image_url: Optional[str] = None product_count: int = 0 class Config: from_attributes = True class BrandResponse(BaseModel): id: int name: str slug: str description: Optional[str] = None logo_url: Optional[str] = None website: Optional[str] = None product_count: int = 0 class Config: from_attributes = True class DispensaryResponse(BaseModel): id: int name: str slug: str address: Optional[str] = None city: Optional[str] = None state: Optional[str] = None phone: Optional[str] = None website: Optional[str] = None logo_url: Optional[str] = None rating: Optional[float] = None review_count: int = 0 latitude: Optional[float] = None longitude: Optional[float] = None class Config: from_attributes = True class ProductPriceResponse(BaseModel): dispensary: DispensaryResponse price: float original_price: Optional[float] = None in_stock: bool = True has_deal: bool = False deal_text: Optional[str] = None class Config: from_attributes = True class ProductResponse(BaseModel): id: int name: str slug: str description: Optional[str] = None image_url: Optional[str] = None category: Optional[CategoryResponse] = None brand: Optional[BrandResponse] = None strain_type: Optional[str] = None thc_percentage: Optional[float] = None cbd_percentage: Optional[float] = None weight: Optional[str] = None lowest_price: Optional[float] = None avg_price: Optional[float] = None has_deal: bool = False deal_text: Optional[str] = None original_price: Optional[float] = None dispensary_count: int = 0 created_at: datetime class Config: from_attributes = True class ProductDetailResponse(ProductResponse): prices: List[ProductPriceResponse] = [] class ProductListResponse(BaseModel): products: List[ProductResponse] total: int page: int per_page: int total_pages: int