"""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 # Folder assignment folder_id: str | 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 folder_id: str | 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 folder_id: str | 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