- Update VendorResponse to use company_id instead of owner fields - Add VendorDetailResponse with company info (name, email, phone, website) - Update VendorCreate to require company_id - Add owner_email, owner_username, vendors list to CompanyDetailResponse - Remove obsolete VendorTransferOwnership schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
192 lines
5.7 KiB
Python
192 lines
5.7 KiB
Python
# models/schema/vendor.py
|
|
"""
|
|
Pydantic schemas for Vendor-related operations.
|
|
|
|
Schemas include:
|
|
- VendorCreate: For creating vendors under companies
|
|
- VendorUpdate: For updating vendor information (Admin only)
|
|
- VendorResponse: Standard vendor response
|
|
- VendorDetailResponse: Vendor response with company/owner details
|
|
- VendorCreateResponse: Response after vendor creation
|
|
- VendorListResponse: Paginated vendor list
|
|
- VendorSummary: Lightweight vendor info
|
|
|
|
Note: Ownership transfer is handled at the Company level.
|
|
See models/schema/company.py for CompanyTransferOwnership.
|
|
"""
|
|
|
|
import re
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
|
|
class VendorCreate(BaseModel):
|
|
"""
|
|
Schema for creating a new vendor (storefront/brand) under an existing company.
|
|
|
|
Business contact info is inherited from the parent company.
|
|
"""
|
|
|
|
# Parent company
|
|
company_id: int = Field(..., description="ID of the parent company", gt=0)
|
|
|
|
# Basic Information
|
|
vendor_code: str = Field(
|
|
...,
|
|
description="Unique vendor identifier (e.g., TECHSTORE)",
|
|
min_length=2,
|
|
max_length=50,
|
|
)
|
|
subdomain: str = Field(
|
|
..., description="Unique subdomain for the vendor", min_length=2, max_length=100
|
|
)
|
|
name: str = Field(
|
|
..., description="Display name of the vendor/brand", min_length=2, max_length=255
|
|
)
|
|
description: str | None = Field(None, description="Vendor/brand description")
|
|
|
|
# Marketplace URLs (brand-specific multi-language support)
|
|
letzshop_csv_url_fr: str | None = Field(None, description="French CSV URL")
|
|
letzshop_csv_url_en: str | None = Field(None, description="English CSV URL")
|
|
letzshop_csv_url_de: str | None = Field(None, description="German CSV URL")
|
|
|
|
@field_validator("subdomain")
|
|
@classmethod
|
|
def validate_subdomain(cls, v):
|
|
"""Validate subdomain format: lowercase alphanumeric with hyphens."""
|
|
if v and not re.match(r"^[a-z0-9][a-z0-9-]*[a-z0-9]$", v):
|
|
raise ValueError(
|
|
"Subdomain must contain only lowercase letters, numbers, and hyphens"
|
|
)
|
|
return v.lower() if v else v
|
|
|
|
@field_validator("vendor_code")
|
|
@classmethod
|
|
def validate_vendor_code(cls, v):
|
|
"""Ensure vendor code is uppercase for consistency."""
|
|
return v.upper() if v else v
|
|
|
|
|
|
class VendorUpdate(BaseModel):
|
|
"""
|
|
Schema for updating vendor information (Admin only).
|
|
|
|
Note: Business contact info (contact_email, etc.) is at the Company level.
|
|
Use company update endpoints to modify those fields.
|
|
"""
|
|
|
|
# Basic Information
|
|
name: str | None = Field(None, min_length=2, max_length=255)
|
|
description: str | None = None
|
|
subdomain: str | None = Field(None, min_length=2, max_length=100)
|
|
|
|
# Marketplace URLs (brand-specific)
|
|
letzshop_csv_url_fr: str | None = None
|
|
letzshop_csv_url_en: str | None = None
|
|
letzshop_csv_url_de: str | None = None
|
|
|
|
# Status (Admin only)
|
|
is_active: bool | None = None
|
|
is_verified: bool | None = None
|
|
|
|
@field_validator("subdomain")
|
|
@classmethod
|
|
def subdomain_lowercase(cls, v):
|
|
"""Normalize subdomain to lowercase."""
|
|
return v.lower().strip() if v else v
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class VendorResponse(BaseModel):
|
|
"""
|
|
Standard schema for vendor response data.
|
|
|
|
Note: Business contact info (contact_email, contact_phone, website,
|
|
business_address, tax_number) is now at the Company level.
|
|
Use company_id to look up company details.
|
|
"""
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
vendor_code: str
|
|
subdomain: str
|
|
name: str
|
|
description: str | None
|
|
|
|
# Company relationship
|
|
company_id: int
|
|
|
|
# Marketplace URLs (brand-specific)
|
|
letzshop_csv_url_fr: str | None
|
|
letzshop_csv_url_en: str | None
|
|
letzshop_csv_url_de: str | None
|
|
|
|
# Status Flags
|
|
is_active: bool
|
|
is_verified: bool
|
|
|
|
# Timestamps
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class VendorDetailResponse(VendorResponse):
|
|
"""
|
|
Extended vendor response including company information.
|
|
|
|
Includes company details like contact info and owner information.
|
|
"""
|
|
|
|
# Company info
|
|
company_name: str = Field(..., description="Name of the parent company")
|
|
company_contact_email: str = Field(..., description="Company business contact email")
|
|
company_contact_phone: str | None = Field(None, description="Company phone number")
|
|
company_website: str | None = Field(None, description="Company website URL")
|
|
|
|
# Owner info (at company level)
|
|
owner_email: str = Field(
|
|
..., description="Email of the company owner (for login/authentication)"
|
|
)
|
|
owner_username: str = Field(..., description="Username of the company owner")
|
|
|
|
|
|
class VendorCreateResponse(VendorDetailResponse):
|
|
"""
|
|
Response after creating vendor under an existing company.
|
|
|
|
The vendor is created under a company, so no new owner credentials are generated.
|
|
The company owner already has access to this vendor.
|
|
"""
|
|
|
|
login_url: str | None = Field(None, description="URL for vendor storefront")
|
|
|
|
|
|
class VendorListResponse(BaseModel):
|
|
"""Schema for paginated vendor list."""
|
|
|
|
vendors: list[VendorResponse]
|
|
total: int
|
|
skip: int
|
|
limit: int
|
|
|
|
|
|
class VendorSummary(BaseModel):
|
|
"""Lightweight vendor summary for dropdowns and quick references."""
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
vendor_code: str
|
|
subdomain: str
|
|
name: str
|
|
company_id: int
|
|
is_active: bool
|
|
|
|
|
|
# NOTE: Vendor ownership transfer schemas have been removed.
|
|
# Ownership transfer is now handled at the Company level.
|
|
# See models/schema/company.py for CompanyTransferOwnership and CompanyTransferOwnershipResponse.
|