Files
orion/models/schema/product.py
Samir Boulahtit 8a367077e1 refactor: migrate vendor APIs to token-based context and consolidate architecture
## Vendor-in-Token Architecture (Complete Migration)
- Migrate all vendor API endpoints from require_vendor_context() to token_vendor_id
- Update permission dependencies to extract vendor from JWT token
- Add vendor exceptions: VendorAccessDeniedException, VendorOwnerOnlyException,
  InsufficientVendorPermissionsException
- Shop endpoints retain require_vendor_context() for URL-based detection
- Add AUTH-004 architecture rule enforcing vendor context patterns
- Fix marketplace router missing /marketplace prefix

## Exception Pattern Fixes (API-003/API-004)
- Services raise domain exceptions, endpoints let them bubble up
- Add code_quality and content_page exception modules
- Move business logic from endpoints to services (admin, auth, content_page)
- Fix exception handling in admin, shop, and vendor endpoints

## Tailwind CSS Consolidation
- Consolidate CSS to per-area files (admin, vendor, shop, platform)
- Remove shared/cdn-fallback.html and shared/css/tailwind.min.css
- Update all templates to use area-specific Tailwind output files
- Remove Node.js config (package.json, postcss.config.js, tailwind.config.js)

## Documentation & Cleanup
- Update vendor-in-token-architecture.md with completed migration status
- Update architecture-rules.md with new rules
- Move migration docs to docs/development/migration/
- Remove duplicate/obsolete documentation files
- Merge pytest.ini settings into pyproject.toml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 22:24:45 +01:00

88 lines
2.4 KiB
Python

# models/schema/product.py
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field
from models.schema.inventory import InventoryLocationResponse
from models.schema.marketplace_product import MarketplaceProductResponse
class ProductCreate(BaseModel):
marketplace_product_id: int = Field(
..., description="MarketplaceProduct ID to add to vendor catalog"
)
product_id: str | None = Field(None, description="Vendor's internal SKU/product ID")
price: float | None = Field(None, ge=0)
sale_price: float | None = Field(None, ge=0)
currency: str | None = None
availability: str | None = None
condition: str | None = None
is_featured: bool = False
min_quantity: int = Field(1, ge=1)
max_quantity: int | None = Field(None, ge=1)
class ProductUpdate(BaseModel):
product_id: str | None = None
price: float | None = Field(None, ge=0)
sale_price: float | None = Field(None, ge=0)
currency: str | None = None
availability: str | None = None
condition: str | None = None
is_featured: bool | None = None
is_active: bool | None = None
min_quantity: int | None = Field(None, ge=1)
max_quantity: int | None = Field(None, ge=1)
class ProductResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
vendor_id: int
marketplace_product: MarketplaceProductResponse
product_id: str | None
price: float | None
sale_price: float | None
currency: str | None
availability: str | None
condition: str | None
is_featured: bool
is_active: bool
display_order: int
min_quantity: int
max_quantity: int | None
created_at: datetime
updated_at: datetime
# Include inventory summary
total_inventory: int | None = None
available_inventory: int | None = None
class ProductDetailResponse(ProductResponse):
"""Product with full inventory details."""
inventory_locations: list[InventoryLocationResponse] = []
class ProductListResponse(BaseModel):
products: list[ProductResponse]
total: int
skip: int
limit: int
class ProductDeleteResponse(BaseModel):
"""Response for product deletion."""
message: str
class ProductToggleResponse(BaseModel):
"""Response for product toggle operations (active/featured)."""
message: str
is_active: bool | None = None
is_featured: bool | None = None