from datetime import datetime from typing import Literal from pydantic import BaseModel, ConfigDict, EmailStr, Field, HttpUrl, field_validator CustomerStatus = Literal["lead", "active", "inactive", "blocked", "archived"] CustomerType = Literal["company", "private", "public_sector", "partner", "supplier"] AddressType = Literal["billing", "shipping", "primary", "other"] def normalize_optional_text(value: object) -> str: if value is None: return "" return str(value).strip() class CustomerAddressBase(BaseModel): type: AddressType = "primary" street: str = Field(default="", max_length=255) postal_code: str = Field(default="", max_length=30) city: str = Field(default="", max_length=120) state: str = Field(default="", max_length=120) country: str = Field(default="Deutschland", max_length=120) is_primary: bool = False @field_validator("street", "postal_code", "city", "state", "country", mode="before") @classmethod def normalize_text(cls, value: object) -> str: return normalize_optional_text(value) class CustomerAddressCreate(CustomerAddressBase): pass class CustomerAddressUpdate(CustomerAddressBase): pass class CustomerAddressResponse(CustomerAddressBase): id: int customer_id: int created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class CustomerContactBase(BaseModel): first_name: str = Field(default="", max_length=100) last_name: str = Field(default="", max_length=100) position: str = Field(default="", max_length=120) email: EmailStr | None = None phone: str = Field(default="", max_length=80) mobile: str = Field(default="", max_length=80) is_primary: bool = False notes: str = "" @field_validator("first_name", "last_name", "position", "phone", "mobile", "notes", mode="before") @classmethod def normalize_text(cls, value: object) -> str: return normalize_optional_text(value) class CustomerContactCreate(CustomerContactBase): pass class CustomerContactUpdate(CustomerContactBase): pass class CustomerContactResponse(CustomerContactBase): id: int customer_id: int email: str created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class CustomerBase(BaseModel): customer_number: str = Field(min_length=1, max_length=50) company_name: str = Field(min_length=1, max_length=255) legal_name: str = Field(default="", max_length=255) customer_type: CustomerType status: CustomerStatus industry: str = Field(default="", max_length=120) website: HttpUrl | None = None email: EmailStr | None = None phone: str = Field(default="", max_length=80) tax_number: str = Field(default="", max_length=120) vat_id: str = Field(default="", max_length=120) notes: str = "" @field_validator( "customer_number", "company_name", "legal_name", "industry", "phone", "tax_number", "vat_id", "notes", mode="before", ) @classmethod def normalize_text(cls, value: object) -> str: return normalize_optional_text(value) class CustomerCreate(CustomerBase): addresses: list[CustomerAddressCreate] = Field(default_factory=list) contacts: list[CustomerContactCreate] = Field(default_factory=list) class CustomerUpdate(CustomerBase): addresses: list[CustomerAddressUpdate] = Field(default_factory=list) class CustomerResponse(CustomerBase): id: int website: str email: str addresses: list[CustomerAddressResponse] contacts: list[CustomerContactResponse] created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True)