feat(customers): add dashboard and customer management
This commit is contained in:
parent
694b7bd09a
commit
92cb8d1286
28 changed files with 2521 additions and 13 deletions
131
backend/hermes/app/schemas/customer.py
Normal file
131
backend/hermes/app/schemas/customer.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue