3
This commit is contained in:
+360
-13
@@ -1,7 +1,12 @@
|
||||
"""Pydantic modely pro RAYNET endpointy.
|
||||
|
||||
Modely odpovídají RAYNET CRM API v2 (CompanyInsertDto). Slouží zároveň jako
|
||||
zdroj pro Swagger/OpenAPI dokumentaci.
|
||||
Modely odpovídají RAYNET CRM API v2 (Insert DTO jednotlivých entit) a slouží
|
||||
zároveň jako zdroj pro Swagger/OpenAPI dokumentaci – ve Swaggeru je tak vidět
|
||||
přesná struktura objektů, povinná pole i tvar odpovědí.
|
||||
|
||||
POZN.: Názvy polí jsou v ``camelCase`` (tak je očekává RAYNET JSON tělo).
|
||||
Nevyjmenovaná pole jsou povolená (``extra="allow"``), takže lze poslat i pole,
|
||||
která zde nejsou explicitně uvedená.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
@@ -10,6 +15,9 @@ from typing import Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Číselníkové enumy (company)
|
||||
# --------------------------------------------------------------------------- #
|
||||
class Rating(str, Enum):
|
||||
A = "A"
|
||||
B = "B"
|
||||
@@ -35,6 +43,9 @@ class TaxPayer(str, Enum):
|
||||
NO = "NO"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Sdílené pod-objekty
|
||||
# --------------------------------------------------------------------------- #
|
||||
class Address(BaseModel):
|
||||
name: Optional[str] = Field(default=None, examples=["Sídlo klienta"])
|
||||
street: Optional[str] = Field(default=None, examples=["Francouzská 6167/5"])
|
||||
@@ -64,21 +75,21 @@ class CompanyAddress(BaseModel):
|
||||
contactInfo: Optional[ContactInfo] = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Entitní modely (request body pro create) – CamelCase dle RAYNET API
|
||||
# --------------------------------------------------------------------------- #
|
||||
class CompanyData(BaseModel):
|
||||
"""Tělo požadavku pro vytvoření firmy (CompanyInsertDto).
|
||||
"""Firma / klient (RAYNET CompanyInsertDto). Povinná: name, rating, state, role."""
|
||||
|
||||
Povinná pole: ``name``, ``rating``, ``state``, ``role``.
|
||||
"""
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
# Povinná pole
|
||||
name: str = Field(..., examples=["ACME s.r.o."])
|
||||
rating: Rating = Field(..., examples=[Rating.A])
|
||||
state: CompanyState = Field(..., examples=[CompanyState.A_POTENTIAL])
|
||||
role: CompanyRole = Field(..., examples=[CompanyRole.A_SUBSCRIBER])
|
||||
|
||||
# Volitelná pole
|
||||
regNumber: Optional[str] = Field(default=None, examples=["12345678"])
|
||||
taxNumber: Optional[str] = Field(default=None, examples=["CZ12345678"])
|
||||
regNumber: Optional[str] = Field(default=None, examples=["12345678"], description="IČO")
|
||||
taxNumber: Optional[str] = Field(default=None, examples=["CZ12345678"], description="DIČ")
|
||||
taxNumber2: Optional[str] = None
|
||||
taxPayer: Optional[TaxPayer] = None
|
||||
bankAccount: Optional[str] = None
|
||||
@@ -95,11 +106,347 @@ class CompanyData(BaseModel):
|
||||
tags: Optional[list[str]] = None
|
||||
customFields: Optional[dict] = None
|
||||
|
||||
# Umožní i pole, která zde nejsou explicitně vyjmenovaná (RAYNET jich má víc).
|
||||
|
||||
class PersonData(BaseModel):
|
||||
"""Kontaktní osoba (RAYNET PersonInsertDto). Povinné: lastName."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
lastName: str = Field(..., description="Příjmení")
|
||||
titleBefore: Optional[str] = None
|
||||
firstName: Optional[str] = None
|
||||
titleAfter: Optional[str] = None
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
category: Optional[int] = None
|
||||
personClassification1: Optional[int] = None
|
||||
personClassification2: Optional[int] = None
|
||||
personClassification3: Optional[int] = None
|
||||
salutation: Optional[str] = None
|
||||
birthday: Optional[str] = None
|
||||
language: Optional[int] = None
|
||||
maritalStatus: Optional[int] = None
|
||||
gender: Optional[str] = None
|
||||
contactInfo: Optional[dict] = None
|
||||
socialNetworkContact: Optional[dict] = None
|
||||
privateAddress: Optional[dict] = None
|
||||
notice: Optional[str] = None
|
||||
relationship: Optional[dict] = None
|
||||
tags: Optional[list[str]] = None
|
||||
keyman: Optional[bool] = None
|
||||
originLead: Optional[int] = None
|
||||
|
||||
class CreateCompanyResponse(BaseModel):
|
||||
id: Optional[int] = Field(default=None, description="ID nově vytvořené firmy")
|
||||
|
||||
class LeadData(BaseModel):
|
||||
"""Lead / poptávka (RAYNET LeadInsertDto). Povinné: topic, priority."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
topic: str = Field(..., description="Předmět")
|
||||
priority: str = Field(..., description="Priorita (číselník)")
|
||||
companyName: Optional[str] = None
|
||||
regNumber: Optional[str] = None
|
||||
firstName: Optional[str] = None
|
||||
lastName: Optional[str] = None
|
||||
titleBefore: Optional[str] = None
|
||||
titleAfter: Optional[str] = None
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
contactSource: Optional[int] = None
|
||||
category: Optional[int] = None
|
||||
notice: Optional[str] = None
|
||||
leadPhase: Optional[int] = None
|
||||
tags: Optional[str] = None
|
||||
territory: Optional[int] = None
|
||||
leadPerson: Optional[bool] = None
|
||||
contactInfo: Optional[dict] = None
|
||||
address: Optional[dict] = None
|
||||
socialNetworkContact: Optional[dict] = None
|
||||
customFields: Optional[dict] = None
|
||||
notificationMessage: Optional[str] = None
|
||||
notificationEmailAddresses: Optional[list[str]] = None
|
||||
|
||||
|
||||
class BusinessCaseData(BaseModel):
|
||||
"""Obchodní případ (RAYNET BusinessCaseInsertDto). Povinné: name, company."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = Field(..., description="Předmět")
|
||||
company: int = Field(..., description="ID klienta")
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
project: Optional[int] = None
|
||||
totalAmount: Optional[float] = None
|
||||
estimatedValue: Optional[float] = None
|
||||
probability: Optional[int] = None
|
||||
validFrom: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
currency: Optional[int] = None
|
||||
exchangeRate: Optional[float] = None
|
||||
category: Optional[int] = None
|
||||
source: Optional[int] = None
|
||||
businessCaseClassification1: Optional[int] = None
|
||||
businessCaseClassification2: Optional[int] = None
|
||||
businessCaseClassification3: Optional[int] = None
|
||||
businessCasePhase: Optional[int] = None
|
||||
originalLead: Optional[int] = None
|
||||
tags: Optional[list[str]] = None
|
||||
customFields: Optional[dict] = None
|
||||
|
||||
|
||||
class TaskData(BaseModel):
|
||||
"""Úkol = aktivita typu task (RAYNET TaskInsertDto, endpoint /task/).
|
||||
|
||||
Povinné: title, priority, owner, resolver, deadline.
|
||||
"""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
title: str = Field(..., description="Předmět")
|
||||
priority: str = Field(..., description="Priorita")
|
||||
owner: int = Field(..., description="ID kontaktní osoby – vlastník úkolu")
|
||||
resolver: int = Field(..., description="ID kontaktní osoby – řešitel úkolu")
|
||||
deadline: str = Field(..., description="Deadline (datetime)")
|
||||
category: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
company: Optional[int] = None
|
||||
businessCase: Optional[int] = None
|
||||
offer: Optional[int] = None
|
||||
salesOrder: Optional[int] = None
|
||||
project: Optional[int] = None
|
||||
activity: Optional[int] = None
|
||||
lead: Optional[int] = None
|
||||
securityLevel: Optional[int] = None
|
||||
scheduledFrom: Optional[str] = None
|
||||
scheduledTill: Optional[str] = None
|
||||
completed: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
solution: Optional[str] = None
|
||||
tags: Optional[list[str]] = None
|
||||
|
||||
|
||||
class ProductData(BaseModel):
|
||||
"""Produkt (RAYNET ProductInsertDto). Povinné: code, name."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
code: str = Field(..., description="Kód")
|
||||
name: str = Field(..., description="Název")
|
||||
unit: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
taxRate: Optional[float] = None
|
||||
category: Optional[int] = Field(default=None, description="ID z číselníku ProductCategory")
|
||||
productLine: Optional[int] = Field(default=None, description="ID z číselníku ProductLine")
|
||||
cost: Optional[float] = None
|
||||
price: Optional[float] = None
|
||||
tags: Optional[list[str]] = None
|
||||
|
||||
|
||||
class OfferData(BaseModel):
|
||||
"""Nabídka (RAYNET OfferInsertDto). Povinné: name, company, businessCase."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = Field(..., description="Předmět")
|
||||
company: int = Field(..., description="ID klienta")
|
||||
businessCase: int = Field(..., description="ID obchodního případu")
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
totalAmount: Optional[float] = None
|
||||
estimatedValue: Optional[float] = None
|
||||
validFrom: Optional[str] = None
|
||||
validTill: Optional[str] = None
|
||||
expirationDate: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
category: Optional[int] = None
|
||||
offerStatus: Optional[int] = None
|
||||
|
||||
|
||||
class SalesOrderData(BaseModel):
|
||||
"""Objednávka (RAYNET SalesOrderInsertDto, endpoint /salesOrder/).
|
||||
|
||||
Povinné: name, company, businessCase.
|
||||
"""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = Field(..., description="Předmět")
|
||||
company: int = Field(..., description="ID klienta")
|
||||
businessCase: int = Field(..., description="ID obchodního případu")
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
offer: Optional[int] = None
|
||||
totalAmount: Optional[float] = None
|
||||
estimatedValue: Optional[float] = None
|
||||
validFrom: Optional[str] = None
|
||||
validTill: Optional[str] = None
|
||||
expirationDate: Optional[str] = None
|
||||
requestDeliveryDate: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
category: Optional[int] = None
|
||||
salesOrderStatus: Optional[int] = None
|
||||
deliveryAddress: Optional[dict] = None
|
||||
|
||||
|
||||
class InvoiceData(BaseModel):
|
||||
"""Faktura (RAYNET InvoiceInsertDto, endpoint /invoice/).
|
||||
|
||||
Povinné: company, currency, dueDate, issueDate, invoiceType, paymentType,
|
||||
taxableSupplyDate.
|
||||
"""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
company: int = Field(..., description="ID klienta, kterému se fakturuje")
|
||||
currency: int = Field(..., description="ID měny (číselník Currency)")
|
||||
dueDate: str = Field(..., description="Datum splatnosti")
|
||||
issueDate: str = Field(..., description="Datum vystavení")
|
||||
invoiceType: str = Field(..., description="Typ faktury")
|
||||
paymentType: str = Field(..., description="Způsob úhrady")
|
||||
taxableSupplyDate: str = Field(..., description="Datum zdanitelného plnění")
|
||||
securityLevel: Optional[int] = None
|
||||
title: Optional[str] = None
|
||||
constantSymbol: Optional[str] = None
|
||||
specificSymbol: Optional[str] = None
|
||||
paymentTermDays: Optional[int] = None
|
||||
businessCase: Optional[int] = None
|
||||
note: Optional[str] = None
|
||||
deliveryNote: Optional[str] = None
|
||||
privateNote: Optional[str] = None
|
||||
|
||||
|
||||
class ProjectData(BaseModel):
|
||||
"""Projekt (RAYNET ProjectInsertDto). Povinné: name, company."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = Field(..., description="Předmět")
|
||||
company: int = Field(..., description="ID klienta")
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
totalAmount: Optional[int] = None
|
||||
avgValueTotalAmount: Optional[float] = None
|
||||
minValueTotalAmount: Optional[float] = None
|
||||
maxValueTotalAmount: Optional[float] = None
|
||||
validFrom: Optional[str] = None
|
||||
validTill: Optional[str] = None
|
||||
scheduledEnd: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
category: Optional[int] = None
|
||||
projectStatus: Optional[int] = None
|
||||
tags: Optional[list[str]] = None
|
||||
customFields: Optional[dict] = None
|
||||
|
||||
|
||||
class PriceListData(BaseModel):
|
||||
"""Ceník (RAYNET PriceListInsertDto). Povinné: name, code, currency, validFrom."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
name: str = Field(..., description="Název ceníku")
|
||||
code: str = Field(..., description="Kód ceníku")
|
||||
currency: int = Field(..., description="ID měny (číselník Currency)")
|
||||
validFrom: str = Field(..., description="Platnost od")
|
||||
securityLevel: Optional[int] = None
|
||||
owner: Optional[int] = None
|
||||
category: Optional[int] = None
|
||||
validTill: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
# --- Aktivity (sdílí strukturu: title, priority, owner povinné) ----------- #
|
||||
class _ActivityBase(BaseModel):
|
||||
"""Společná pole aktivit RAYNET (task/email/event/meeting/phoneCall/letter)."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
title: str = Field(..., description="Předmět")
|
||||
priority: str = Field(..., description="Priorita")
|
||||
owner: int = Field(..., description="ID kontaktní osoby – vlastník")
|
||||
category: Optional[int] = None
|
||||
person: Optional[int] = None
|
||||
company: Optional[int] = None
|
||||
businessCase: Optional[int] = None
|
||||
offer: Optional[int] = None
|
||||
salesOrder: Optional[int] = None
|
||||
project: Optional[int] = None
|
||||
activity: Optional[int] = None
|
||||
lead: Optional[int] = None
|
||||
securityLevel: Optional[int] = None
|
||||
scheduledFrom: Optional[str] = None
|
||||
scheduledTill: Optional[str] = None
|
||||
completed: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
tags: Optional[list[str]] = None
|
||||
|
||||
|
||||
class EmailData(_ActivityBase):
|
||||
"""E-mailová aktivita (RAYNET EmailInsertDto)."""
|
||||
|
||||
|
||||
class EventData(_ActivityBase):
|
||||
"""Událost (RAYNET EventInsertDto)."""
|
||||
|
||||
|
||||
class MeetingData(_ActivityBase):
|
||||
"""Schůzka (RAYNET MeetingInsertDto)."""
|
||||
|
||||
solution: Optional[str] = None
|
||||
|
||||
|
||||
class PhoneCallData(_ActivityBase):
|
||||
"""Telefonát (RAYNET PhonecallInsertDto)."""
|
||||
|
||||
solution: Optional[str] = None
|
||||
|
||||
|
||||
class LetterData(_ActivityBase):
|
||||
"""Dopis (RAYNET LetterInsertDto)."""
|
||||
|
||||
|
||||
class WebhookData(BaseModel):
|
||||
"""Webhook (RAYNET WebhookInsertDto). Povinné: url, events."""
|
||||
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
url: str = Field(..., description="Cílová adresa (http/https)")
|
||||
events: list[str] = Field(
|
||||
...,
|
||||
description="Typy událostí: record.created, record.updated, record.deleted",
|
||||
)
|
||||
secretToken: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Token zaslaný v hlavičce X-RAYNETCRM-Token",
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Obálky odpovědí (RAYNET vrací data zabalená do success/data/totalCount)
|
||||
# --------------------------------------------------------------------------- #
|
||||
class CreateResponse(BaseModel):
|
||||
success: bool = True
|
||||
id: Optional[int] = Field(default=None, description="ID nově vytvořeného záznamu")
|
||||
data: Optional[dict] = Field(default=None, description="Surová data z RAYNET, pokud byla vrácena")
|
||||
|
||||
|
||||
class DetailResponse(BaseModel):
|
||||
success: bool = True
|
||||
data: Optional[dict] = Field(
|
||||
default=None,
|
||||
description="Objekt záznamu vč. serverových polí (id, rowInfo, ...)",
|
||||
)
|
||||
|
||||
|
||||
class ListResponse(BaseModel):
|
||||
success: bool = True
|
||||
totalCount: Optional[int] = Field(default=None, description="Celkový počet záznamů")
|
||||
data: list[dict] = Field(default_factory=list, description="Pole záznamů")
|
||||
|
||||
|
||||
class SimpleResponse(BaseModel):
|
||||
success: bool = True
|
||||
raw: Optional[dict] = Field(default=None, description="Surová odpověď RAYNET API")
|
||||
|
||||
Reference in New Issue
Block a user