# models/schema/inventory.py from datetime import datetime from pydantic import BaseModel, ConfigDict, Field class InventoryBase(BaseModel): product_id: int = Field(..., description="Product ID in vendor catalog") location: str = Field(..., description="Storage location") class InventoryCreate(InventoryBase): """Set exact inventory quantity (replaces existing).""" quantity: int = Field(..., description="Exact inventory quantity", ge=0) class InventoryAdjust(InventoryBase): """Add or remove inventory quantity.""" quantity: int = Field( ..., description="Quantity to add (positive) or remove (negative)" ) class InventoryUpdate(BaseModel): """Update inventory fields.""" quantity: int | None = Field(None, ge=0) reserved_quantity: int | None = Field(None, ge=0) location: str | None = None class InventoryReserve(BaseModel): """Reserve inventory for orders.""" product_id: int location: str quantity: int = Field(..., gt=0) class InventoryResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: int product_id: int vendor_id: int location: str quantity: int reserved_quantity: int gtin: str | None created_at: datetime updated_at: datetime @property def available_quantity(self): return max(0, self.quantity - self.reserved_quantity) class InventoryLocationResponse(BaseModel): location: str quantity: int reserved_quantity: int available_quantity: int class ProductInventorySummary(BaseModel): """Inventory summary for a product.""" product_id: int vendor_id: int product_sku: str | None product_title: str total_quantity: int total_reserved: int total_available: int locations: list[InventoryLocationResponse] class InventoryListResponse(BaseModel): inventories: list[InventoryResponse] total: int skip: int limit: int class InventoryMessageResponse(BaseModel): """Simple message response for inventory operations.""" message: str class InventorySummaryResponse(BaseModel): """Inventory summary response for marketplace product service.""" gtin: str total_quantity: int locations: list[InventoryLocationResponse] # ============================================================================ # Admin Inventory Schemas # ============================================================================ class AdminInventoryCreate(BaseModel): """Admin version of inventory create - requires explicit vendor_id.""" vendor_id: int = Field(..., description="Target vendor ID") product_id: int = Field(..., description="Product ID in vendor catalog") location: str = Field(..., description="Storage location") quantity: int = Field(..., description="Exact inventory quantity", ge=0) class AdminInventoryAdjust(BaseModel): """Admin version of inventory adjust - requires explicit vendor_id.""" vendor_id: int = Field(..., description="Target vendor ID") product_id: int = Field(..., description="Product ID in vendor catalog") location: str = Field(..., description="Storage location") quantity: int = Field( ..., description="Quantity to add (positive) or remove (negative)" ) reason: str | None = Field(None, description="Reason for adjustment") class AdminInventoryItem(BaseModel): """Inventory item with vendor info for admin list view.""" model_config = ConfigDict(from_attributes=True) id: int product_id: int vendor_id: int vendor_name: str | None = None vendor_code: str | None = None product_title: str | None = None product_sku: str | None = None location: str quantity: int reserved_quantity: int available_quantity: int gtin: str | None = None created_at: datetime updated_at: datetime class AdminInventoryListResponse(BaseModel): """Cross-vendor inventory list for admin.""" inventories: list[AdminInventoryItem] total: int skip: int limit: int vendor_filter: int | None = None location_filter: str | None = None class AdminInventoryStats(BaseModel): """Inventory statistics for admin dashboard.""" total_entries: int total_quantity: int total_reserved: int total_available: int low_stock_count: int vendors_with_inventory: int unique_locations: int class AdminLowStockItem(BaseModel): """Low stock item for admin alerts.""" id: int product_id: int vendor_id: int vendor_name: str | None = None product_title: str | None = None location: str quantity: int reserved_quantity: int available_quantity: int class AdminVendorWithInventory(BaseModel): """Vendor with inventory entries.""" id: int name: str vendor_code: str class AdminVendorsWithInventoryResponse(BaseModel): """Response for vendors with inventory list.""" vendors: list[AdminVendorWithInventory] class AdminInventoryLocationsResponse(BaseModel): """Response for unique inventory locations.""" locations: list[str]