# models/schema/company.py """ Pydantic schemas for Company model. These schemas are used for API request/response validation and serialization. """ from datetime import datetime from typing import Any from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator class CompanyBase(BaseModel): """Base schema for company with common fields.""" name: str = Field(..., min_length=2, max_length=200, description="Company name") description: str | None = Field(None, description="Company description") contact_email: EmailStr = Field(..., description="Business contact email") contact_phone: str | None = Field(None, description="Business phone number") website: str | None = Field(None, description="Company website URL") business_address: str | None = Field(None, description="Physical business address") tax_number: str | None = Field(None, description="Tax/VAT registration number") @field_validator("contact_email") @classmethod def normalize_email(cls, v): """Normalize email to lowercase.""" return v.lower() if v else v class CompanyCreate(CompanyBase): """ Schema for creating a new company. Requires owner_email to create the associated owner user account. """ owner_email: EmailStr = Field( ..., description="Email for the company owner account" ) @field_validator("owner_email") @classmethod def normalize_owner_email(cls, v): """Normalize owner email to lowercase.""" return v.lower() if v else v model_config = ConfigDict(from_attributes=True) class CompanyUpdate(BaseModel): """ Schema for updating company information. All fields are optional to support partial updates. """ name: str | None = Field(None, min_length=2, max_length=200) description: str | None = None contact_email: EmailStr | None = None contact_phone: str | None = None website: str | None = None business_address: str | None = None tax_number: str | None = None # Status (Admin only) is_active: bool | None = None is_verified: bool | None = None @field_validator("contact_email") @classmethod def normalize_email(cls, v): """Normalize email to lowercase.""" return v.lower() if v else v model_config = ConfigDict(from_attributes=True) class CompanyResponse(BaseModel): """Standard schema for company response data.""" model_config = ConfigDict(from_attributes=True) id: int name: str description: str | None # Owner information owner_user_id: int # Contact Information contact_email: str contact_phone: str | None website: str | None # Business Information business_address: str | None tax_number: str | None # Status Flags is_active: bool is_verified: bool # Timestamps created_at: str updated_at: str class CompanyDetailResponse(CompanyResponse): """ Detailed company response including vendor count and owner details. Used for company detail pages and admin views. """ # Owner details (from related User) owner_email: str | None = Field(None, description="Owner's email address") owner_username: str | None = Field(None, description="Owner's username") # Vendor statistics vendor_count: int = Field(0, description="Number of vendors under this company") active_vendor_count: int = Field( 0, description="Number of active vendors under this company" ) # Vendors list (optional, for detail view) vendors: list | None = Field(None, description="List of vendors under this company") class CompanyListResponse(BaseModel): """Schema for paginated company list.""" companies: list[CompanyResponse] total: int skip: int limit: int class CompanyCreateResponse(BaseModel): """ Response after creating a company with owner account. Includes temporary password for the owner (shown only once). """ company: CompanyResponse owner_user_id: int owner_username: str owner_email: str temporary_password: str = Field( ..., description="Temporary password for owner (SHOWN ONLY ONCE)" ) login_url: str | None = Field(None, description="URL for company owner to login") class CompanySummary(BaseModel): """Lightweight company summary for dropdowns and quick references.""" model_config = ConfigDict(from_attributes=True) id: int name: str is_active: bool is_verified: bool vendor_count: int = 0 class CompanyTransferOwnership(BaseModel): """ Schema for transferring company ownership to another user. This is a critical operation that requires: - Confirmation flag - Reason for audit trail (optional) """ new_owner_user_id: int = Field( ..., description="ID of the user who will become the new owner", gt=0 ) confirm_transfer: bool = Field( ..., description="Must be true to confirm ownership transfer" ) transfer_reason: str | None = Field( None, max_length=500, description="Reason for ownership transfer (for audit logs)", ) @field_validator("confirm_transfer") @classmethod def validate_confirmation(cls, v): """Ensure confirmation is explicitly true.""" if not v: raise ValueError("Ownership transfer requires explicit confirmation") return v class CompanyTransferOwnershipResponse(BaseModel): """Response after successful ownership transfer.""" message: str company_id: int company_name: str old_owner: dict[str, Any] = Field( ..., description="Information about the previous owner" ) new_owner: dict[str, Any] = Field( ..., description="Information about the new owner" ) transferred_at: datetime transfer_reason: str | None