302 lines
12 KiB
Python
302 lines
12 KiB
Python
"""Unified contact schemas — create, update, read, list, contactpersons."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# ── ContactPerson ──
|
|
|
|
class ContactPersonCreate(BaseModel):
|
|
firstname: str | None = Field(None, max_length=100)
|
|
middle_name: str | None = Field(None, max_length=100)
|
|
lastname: str | None = Field(None, max_length=100)
|
|
function: str | None = Field(None, max_length=255)
|
|
phone: str | None = Field(None, max_length=50)
|
|
mobilephone: str | None = Field(None, max_length=50)
|
|
email: str | None = Field(None, max_length=255)
|
|
street: str | None = Field(None, max_length=255)
|
|
number: str | None = Field(None, max_length=20)
|
|
postalcode: str | None = Field(None, max_length=20)
|
|
city: str | None = Field(None, max_length=100)
|
|
state: str | None = Field(None, max_length=100)
|
|
country: str | None = Field(None, max_length=2)
|
|
tags: str | None = Field(None, max_length=500)
|
|
custom: dict | None = None
|
|
|
|
|
|
class ContactPersonUpdate(BaseModel):
|
|
firstname: str | None = Field(None, max_length=100)
|
|
middle_name: str | None = Field(None, max_length=100)
|
|
lastname: str | None = Field(None, max_length=100)
|
|
function: str | None = Field(None, max_length=255)
|
|
phone: str | None = Field(None, max_length=50)
|
|
mobilephone: str | None = Field(None, max_length=50)
|
|
email: str | None = Field(None, max_length=255)
|
|
street: str | None = Field(None, max_length=255)
|
|
number: str | None = Field(None, max_length=20)
|
|
postalcode: str | None = Field(None, max_length=20)
|
|
city: str | None = Field(None, max_length=100)
|
|
state: str | None = Field(None, max_length=100)
|
|
country: str | None = Field(None, max_length=2)
|
|
tags: str | None = Field(None, max_length=500)
|
|
custom: dict | None = None
|
|
|
|
|
|
class ContactPersonResponse(BaseModel):
|
|
id: str
|
|
contact_id: str
|
|
displayname: str
|
|
firstname: str | None = None
|
|
middle_name: str | None = None
|
|
lastname: str | None = None
|
|
function: str | None = None
|
|
phone: str | None = None
|
|
mobilephone: str | None = None
|
|
email: str | None = None
|
|
street: str | None = None
|
|
number: str | None = None
|
|
postalcode: str | None = None
|
|
city: str | None = None
|
|
state: str | None = None
|
|
country: str | None = None
|
|
tags: str | None = None
|
|
custom: dict | None = None
|
|
created_at: str | None = None
|
|
updated_at: str | None = None
|
|
|
|
|
|
# ── Contact ──
|
|
|
|
class ContactCreate(BaseModel):
|
|
type: str = Field("company", pattern="^(company|person)$")
|
|
name: str | None = Field(None, max_length=255)
|
|
firstname: str | None = Field(None, max_length=100)
|
|
surname: str | None = Field(None, max_length=100)
|
|
surfix: str | None = Field(None, max_length=50)
|
|
ext_name_line: str | None = Field(None, max_length=255)
|
|
gender: str | None = Field(None, max_length=20)
|
|
code: str | None = Field(None, max_length=100)
|
|
accounting_code: str | None = Field(None, max_length=100)
|
|
vendor_accounting_code: str | None = Field(None, max_length=100)
|
|
# Mailing
|
|
mailing_street: str | None = Field(None, max_length=255)
|
|
mailing_number: str | None = Field(None, max_length=20)
|
|
mailing_unit_number: str | None = Field(None, max_length=50)
|
|
mailing_district: str | None = Field(None, max_length=100)
|
|
mailing_extra_address_line: str | None = Field(None, max_length=255)
|
|
mailing_postalcode: str | None = Field(None, max_length=20)
|
|
mailing_city: str | None = Field(None, max_length=100)
|
|
mailing_state: str | None = Field(None, max_length=100)
|
|
mailing_country: str | None = Field(None, max_length=2)
|
|
# Visit
|
|
visit_street: str | None = Field(None, max_length=255)
|
|
visit_number: str | None = Field(None, max_length=20)
|
|
visit_unit_number: str | None = Field(None, max_length=50)
|
|
visit_district: str | None = Field(None, max_length=100)
|
|
visit_extra_address_line: str | None = Field(None, max_length=255)
|
|
visit_postalcode: str | None = Field(None, max_length=20)
|
|
visit_city: str | None = Field(None, max_length=100)
|
|
visit_state: str | None = Field(None, max_length=100)
|
|
# Invoice
|
|
invoice_street: str | None = Field(None, max_length=255)
|
|
invoice_number: str | None = Field(None, max_length=20)
|
|
invoice_unit_number: str | None = Field(None, max_length=50)
|
|
invoice_district: str | None = Field(None, max_length=100)
|
|
invoice_extra_address_line: str | None = Field(None, max_length=255)
|
|
invoice_postalcode: str | None = Field(None, max_length=20)
|
|
invoice_city: str | None = Field(None, max_length=100)
|
|
invoice_state: str | None = Field(None, max_length=100)
|
|
invoice_country: str | None = Field(None, max_length=2)
|
|
# General
|
|
country: str | None = Field(None, max_length=2)
|
|
# Communication
|
|
phone_1: str | None = Field(None, max_length=50)
|
|
phone_2: str | None = Field(None, max_length=50)
|
|
email_1: str | None = Field(None, max_length=255)
|
|
email_2: str | None = Field(None, max_length=255)
|
|
website: str | None = Field(None, max_length=500)
|
|
# Financial
|
|
vat_code: str | None = Field(None, max_length=50)
|
|
fiscal_code: str | None = Field(None, max_length=50)
|
|
commerce_code: str | None = Field(None, max_length=100)
|
|
purchase_number: str | None = Field(None, max_length=100)
|
|
bic: str | None = Field(None, max_length=50)
|
|
bank_account: str | None = Field(None, max_length=50)
|
|
# Discounts
|
|
discount_crew: float = 0
|
|
discount_transport: float = 0
|
|
discount_rental: float = 0
|
|
discount_sale: float = 0
|
|
discount_subrent: float = 0
|
|
discount_total: float = 0
|
|
# Geo
|
|
latitude: float | None = None
|
|
longitude: float | None = None
|
|
# Notes
|
|
projectnote: str | None = None
|
|
projectnote_title: str | None = Field(None, max_length=255)
|
|
contact_warning: str | None = None
|
|
tags: str | None = Field(None, max_length=500)
|
|
image: str | None = None
|
|
# Custom
|
|
custom: dict | None = None
|
|
# Contact persons (optional inline create)
|
|
contact_persons: list[ContactPersonCreate] | None = None
|
|
|
|
|
|
class ContactUpdate(BaseModel):
|
|
type: str | None = Field(None, pattern="^(company|person)$")
|
|
name: str | None = Field(None, max_length=255)
|
|
firstname: str | None = Field(None, max_length=100)
|
|
surname: str | None = Field(None, max_length=100)
|
|
surfix: str | None = Field(None, max_length=50)
|
|
ext_name_line: str | None = Field(None, max_length=255)
|
|
gender: str | None = Field(None, max_length=20)
|
|
code: str | None = Field(None, max_length=100)
|
|
accounting_code: str | None = Field(None, max_length=100)
|
|
vendor_accounting_code: str | None = Field(None, max_length=100)
|
|
mailing_street: str | None = Field(None, max_length=255)
|
|
mailing_number: str | None = Field(None, max_length=20)
|
|
mailing_unit_number: str | None = Field(None, max_length=50)
|
|
mailing_district: str | None = Field(None, max_length=100)
|
|
mailing_extra_address_line: str | None = Field(None, max_length=255)
|
|
mailing_postalcode: str | None = Field(None, max_length=20)
|
|
mailing_city: str | None = Field(None, max_length=100)
|
|
mailing_state: str | None = Field(None, max_length=100)
|
|
mailing_country: str | None = Field(None, max_length=2)
|
|
visit_street: str | None = Field(None, max_length=255)
|
|
visit_number: str | None = Field(None, max_length=20)
|
|
visit_unit_number: str | None = Field(None, max_length=50)
|
|
visit_district: str | None = Field(None, max_length=100)
|
|
visit_extra_address_line: str | None = Field(None, max_length=255)
|
|
visit_postalcode: str | None = Field(None, max_length=20)
|
|
visit_city: str | None = Field(None, max_length=100)
|
|
visit_state: str | None = Field(None, max_length=100)
|
|
invoice_street: str | None = Field(None, max_length=255)
|
|
invoice_number: str | None = Field(None, max_length=20)
|
|
invoice_unit_number: str | None = Field(None, max_length=50)
|
|
invoice_district: str | None = Field(None, max_length=100)
|
|
invoice_extra_address_line: str | None = Field(None, max_length=255)
|
|
invoice_postalcode: str | None = Field(None, max_length=20)
|
|
invoice_city: str | None = Field(None, max_length=100)
|
|
invoice_state: str | None = Field(None, max_length=100)
|
|
invoice_country: str | None = Field(None, max_length=2)
|
|
country: str | None = Field(None, max_length=2)
|
|
phone_1: str | None = Field(None, max_length=50)
|
|
phone_2: str | None = Field(None, max_length=50)
|
|
email_1: str | None = Field(None, max_length=255)
|
|
email_2: str | None = Field(None, max_length=255)
|
|
website: str | None = Field(None, max_length=500)
|
|
vat_code: str | None = Field(None, max_length=50)
|
|
fiscal_code: str | None = Field(None, max_length=50)
|
|
commerce_code: str | None = Field(None, max_length=100)
|
|
purchase_number: str | None = Field(None, max_length=100)
|
|
bic: str | None = Field(None, max_length=50)
|
|
bank_account: str | None = Field(None, max_length=50)
|
|
discount_crew: float | None = None
|
|
discount_transport: float | None = None
|
|
discount_rental: float | None = None
|
|
discount_sale: float | None = None
|
|
discount_subrent: float | None = None
|
|
discount_total: float | None = None
|
|
latitude: float | None = None
|
|
longitude: float | None = None
|
|
projectnote: str | None = None
|
|
projectnote_title: str | None = Field(None, max_length=255)
|
|
contact_warning: str | None = None
|
|
tags: str | None = Field(None, max_length=500)
|
|
image: str | None = None
|
|
custom: dict | None = None
|
|
default_person_id: str | None = None
|
|
admin_contactperson_id: str | None = None
|
|
|
|
|
|
class ContactResponse(BaseModel):
|
|
id: str
|
|
type: str
|
|
displayname: str
|
|
name: str | None = None
|
|
firstname: str | None = None
|
|
surname: str | None = None
|
|
surfix: str | None = None
|
|
ext_name_line: str | None = None
|
|
gender: str | None = None
|
|
code: str | None = None
|
|
accounting_code: str | None = None
|
|
vendor_accounting_code: str | None = None
|
|
# Addresses (flat)
|
|
mailing_street: str | None = None
|
|
mailing_number: str | None = None
|
|
mailing_unit_number: str | None = None
|
|
mailing_district: str | None = None
|
|
mailing_extra_address_line: str | None = None
|
|
mailing_postalcode: str | None = None
|
|
mailing_city: str | None = None
|
|
mailing_state: str | None = None
|
|
mailing_country: str | None = None
|
|
visit_street: str | None = None
|
|
visit_number: str | None = None
|
|
visit_unit_number: str | None = None
|
|
visit_district: str | None = None
|
|
visit_extra_address_line: str | None = None
|
|
visit_postalcode: str | None = None
|
|
visit_city: str | None = None
|
|
visit_state: str | None = None
|
|
invoice_street: str | None = None
|
|
invoice_number: str | None = None
|
|
invoice_unit_number: str | None = None
|
|
invoice_district: str | None = None
|
|
invoice_extra_address_line: str | None = None
|
|
invoice_postalcode: str | None = None
|
|
invoice_city: str | None = None
|
|
invoice_state: str | None = None
|
|
invoice_country: str | None = None
|
|
country: str | None = None
|
|
phone_1: str | None = None
|
|
phone_2: str | None = None
|
|
email_1: str | None = None
|
|
email_2: str | None = None
|
|
website: str | None = None
|
|
vat_code: str | None = None
|
|
fiscal_code: str | None = None
|
|
commerce_code: str | None = None
|
|
purchase_number: str | None = None
|
|
bic: str | None = None
|
|
bank_account: str | None = None
|
|
discount_crew: float = 0
|
|
discount_transport: float = 0
|
|
discount_rental: float = 0
|
|
discount_sale: float = 0
|
|
discount_subrent: float = 0
|
|
discount_total: float = 0
|
|
latitude: float | None = None
|
|
longitude: float | None = None
|
|
projectnote: str | None = None
|
|
projectnote_title: str | None = None
|
|
contact_warning: str | None = None
|
|
tags: str | None = None
|
|
image: str | None = None
|
|
custom: dict | None = None
|
|
default_person_id: str | None = None
|
|
admin_contactperson_id: str | None = None
|
|
created_at: str | None = None
|
|
updated_at: str | None = None
|
|
|
|
|
|
class ContactDetailResponse(ContactResponse):
|
|
contact_persons: list[ContactPersonResponse] = Field(default_factory=list)
|
|
|
|
|
|
class ContactListResponse(BaseModel):
|
|
items: list[ContactResponse]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
# Keep old names for compat
|
|
class CompanyLinkRequest(BaseModel):
|
|
role_at_company: str | None = Field(None, max_length=100)
|
|
is_primary: bool = False
|