# models/schema/vendor_product.py """ Pydantic schemas for vendor product catalog operations. Used by admin vendor product endpoints for: - Product listing and filtering - Product statistics - Product detail views - Catalog vendor listings """ from pydantic import BaseModel, ConfigDict class VendorProductListItem(BaseModel): """Product item for vendor catalog list view.""" model_config = ConfigDict(from_attributes=True) id: int vendor_id: int vendor_name: str | None = None vendor_code: str | None = None marketplace_product_id: int | None = None vendor_sku: str | None = None title: str | None = None brand: str | None = None price: float | None = None currency: str | None = None effective_price: float | None = None effective_currency: str | None = None is_active: bool | None = None is_featured: bool | None = None is_digital: bool | None = None image_url: str | None = None source_marketplace: str | None = None source_vendor: str | None = None created_at: str | None = None updated_at: str | None = None class VendorProductListResponse(BaseModel): """Paginated vendor product list response.""" products: list[VendorProductListItem] total: int skip: int limit: int class VendorProductStats(BaseModel): """Vendor product statistics.""" total: int active: int inactive: int featured: int digital: int physical: int by_vendor: dict[str, int] class CatalogVendor(BaseModel): """Vendor with products in catalog.""" id: int name: str vendor_code: str class CatalogVendorsResponse(BaseModel): """Response for catalog vendors list.""" vendors: list[CatalogVendor] class VendorProductDetail(BaseModel): """Detailed vendor product information. Products are independent entities - all fields are populated at creation. Source values are kept for "view original source" comparison only. """ id: int vendor_id: int vendor_name: str | None = None vendor_code: str | None = None marketplace_product_id: int vendor_sku: str | None = None # Product identifiers gtin: str | None = None gtin_type: str | None = None # ean13, ean8, upc, isbn, etc. # Product fields with source comparison price: float | None = None price_cents: int | None = None price_source: float | None = None # For "view original source" feature sale_price: float | None = None sale_price_cents: int | None = None sale_price_source: float | None = None currency: str | None = None currency_source: str | None = None brand: str | None = None brand_source: str | None = None condition: str | None = None condition_source: str | None = None availability: str | None = None availability_source: str | None = None primary_image_url: str | None = None primary_image_url_source: str | None = None is_digital: bool | None = None product_type: str | None = None # Vendor-specific fields is_featured: bool | None = None is_active: bool | None = None display_order: int | None = None min_quantity: int | None = None max_quantity: int | None = None # Supplier tracking supplier: str | None = None supplier_product_id: str | None = None cost: float | None = None # What vendor pays to acquire product margin_percent: float | None = None # Tax/profit info tax_rate_percent: int | None = None net_price: float | None = None vat_amount: float | None = None profit: float | None = None profit_margin_percent: float | None = None # Digital fulfillment download_url: str | None = None license_type: str | None = None fulfillment_email_template: str | None = None # Source info source_marketplace: str | None = None source_vendor: str | None = None source_gtin: str | None = None source_sku: str | None = None # Translations marketplace_translations: dict | None = None vendor_translations: dict | None = None # Timestamps created_at: str | None = None updated_at: str | None = None class RemoveProductResponse(BaseModel): """Response from product removal.""" message: str class VendorProductCreate(BaseModel): """Schema for creating a vendor product.""" vendor_id: int title: str brand: str | None = None vendor_sku: str | None = None gtin: str | None = None price: float | None = None currency: str = "EUR" availability: str | None = None is_active: bool = True is_featured: bool = False is_digital: bool = False description: str | None = None class TranslationUpdate(BaseModel): """Translation data for a single language.""" title: str | None = None description: str | None = None class VendorProductUpdate(BaseModel): """Schema for updating a vendor product.""" # Translations by language code (en, fr, de, lu) translations: dict[str, TranslationUpdate] | None = None # Product identifiers brand: str | None = None vendor_sku: str | None = None gtin: str | None = None gtin_type: str | None = None # ean13, ean8, upc, isbn, etc. # Pricing price: float | None = None # Price incl. VAT in euros sale_price: float | None = None # Optional sale price currency: str | None = None tax_rate_percent: int | None = None # 3, 8, 14, 17 # Status (is_digital is derived from marketplace product, not editable) is_active: bool | None = None is_featured: bool | None = None # Images primary_image_url: str | None = None # Optional supplier info supplier: str | None = None cost: float | None = None # Cost in euros class VendorProductCreateResponse(BaseModel): """Response from product creation.""" id: int message: str