886 lines
27 KiB
Python
886 lines
27 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
SalesLeadTemperature = Literal["warm", "hot"]
|
|
SalesChannelType = Literal["text", "voice"]
|
|
SalesPreferredChannel = Literal["telegram", "whatsapp", "webchat", "email", "voice"]
|
|
SalesDirection = Literal["inbound", "outbound"]
|
|
SalesAgentType = Literal["text_ai", "voice_ai", "human"]
|
|
SalesLeadStatus = Literal["new_qualified_lead", "warm_lead", "hot_lead", "enrichment_required", "converted", "lost"]
|
|
SalesDealStatus = Literal["active", "won", "lost", "postponed", "closed"]
|
|
SalesScenarioType = Literal[
|
|
"quick_sale",
|
|
"consultative_sale",
|
|
"quotation_based_sale",
|
|
"booking_based_sale",
|
|
"subscription_sale",
|
|
"custom_human_escalation",
|
|
]
|
|
SalesOfferType = Literal["offer", "quotation", "estimate", "order", "booking", "appointment", "subscription_plan"]
|
|
SalesOfferStatus = Literal["draft", "sent", "viewed", "accepted", "rejected"]
|
|
SalesTranscriptStatus = Literal["pending", "ready"]
|
|
SalesDocumentType = Literal[
|
|
"contract",
|
|
"offer_acceptance",
|
|
"appendix",
|
|
"specification",
|
|
"invoice_basis_doc",
|
|
"order_confirmation",
|
|
"booking_confirmation",
|
|
"appointment_confirmation",
|
|
"additional_agreement",
|
|
]
|
|
SalesDocumentStatus = Literal["draft", "sent", "under_review", "confirmed", "signed"]
|
|
SalesInvoiceStatus = Literal["draft", "issued", "sent", "partially_paid", "paid", "overdue", "canceled"]
|
|
SalesPaymentStatus = Literal["pending", "success", "failed", "canceled", "partial"]
|
|
SalesEscalationSeverity = Literal["low", "medium", "high", "critical"]
|
|
SalesEscalationStatus = Literal["open", "assigned", "in_progress", "resolved", "canceled"]
|
|
SalesAutomationStatus = Literal["pending", "running", "completed", "failed", "canceled"]
|
|
SalesPipelineStageCategory = Literal["entry", "communication", "commercial", "paperwork", "finance", "closing"]
|
|
SalesSwitchChannel = Literal["text", "voice"]
|
|
|
|
|
|
class SalesStageRefOut(BaseModel):
|
|
id: str
|
|
code: str
|
|
name: str
|
|
category: SalesPipelineStageCategory
|
|
sort_order: int
|
|
|
|
|
|
class SalesPipelineOut(BaseModel):
|
|
pipeline_id: str
|
|
tenant_id: str
|
|
code: str
|
|
name: str
|
|
description: str | None = None
|
|
is_default: bool
|
|
is_active: bool
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesPipelineCreate(BaseModel):
|
|
code: str = Field(default="default_sales", min_length=2)
|
|
name: str = Field(min_length=2)
|
|
description: str | None = None
|
|
is_default: bool = False
|
|
is_active: bool = True
|
|
|
|
|
|
class SalesPipelineUpdate(BaseModel):
|
|
name: str | None = Field(default=None, min_length=2)
|
|
description: str | None = None
|
|
is_default: bool | None = None
|
|
is_active: bool | None = None
|
|
|
|
|
|
class SalesPipelineStageOut(BaseModel):
|
|
stage_id: str
|
|
tenant_id: str
|
|
pipeline_id: str
|
|
code: str
|
|
name: str
|
|
category: SalesPipelineStageCategory
|
|
sort_order: int
|
|
is_terminal: bool
|
|
is_system: bool
|
|
is_active: bool
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesPipelineStageCreate(BaseModel):
|
|
code: str = Field(min_length=2)
|
|
name: str = Field(min_length=2)
|
|
category: SalesPipelineStageCategory
|
|
sort_order: int = 0
|
|
is_terminal: bool = False
|
|
is_system: bool = False
|
|
is_active: bool = True
|
|
|
|
|
|
class SalesPipelineStageUpdate(BaseModel):
|
|
name: str | None = Field(default=None, min_length=2)
|
|
category: SalesPipelineStageCategory | None = None
|
|
sort_order: int | None = None
|
|
is_active: bool | None = None
|
|
|
|
|
|
class SalesLeadCreate(BaseModel):
|
|
source_type: str = Field(default="crm")
|
|
source_channel: str = Field(default="webchat")
|
|
source_campaign_id: str | None = None
|
|
full_name: str = Field(min_length=2)
|
|
company_name: str | None = None
|
|
phone: str | None = None
|
|
email: str | None = None
|
|
messenger_handles: dict = Field(default_factory=dict)
|
|
lead_temperature: SalesLeadTemperature = "warm"
|
|
lead_score: float = Field(default=50.0, ge=0, le=100)
|
|
customer_type: str | None = None
|
|
segment_type: str | None = None
|
|
initial_need_summary: str | None = None
|
|
preferred_channel: SalesPreferredChannel = "telegram"
|
|
assigned_agent_type: SalesAgentType = "text_ai"
|
|
status: SalesLeadStatus = "new_qualified_lead"
|
|
priority: int = Field(default=3, ge=1, le=5)
|
|
title: str | None = None
|
|
estimated_amount: float | None = Field(default=None, ge=0)
|
|
currency: str = "KZT"
|
|
|
|
|
|
class SalesLeadUpdate(BaseModel):
|
|
full_name: str | None = Field(default=None, min_length=2)
|
|
company_name: str | None = None
|
|
phone: str | None = None
|
|
email: str | None = None
|
|
messenger_handles: dict | None = None
|
|
lead_temperature: SalesLeadTemperature | None = None
|
|
lead_score: float | None = Field(default=None, ge=0, le=100)
|
|
customer_type: str | None = None
|
|
segment_type: str | None = None
|
|
initial_need_summary: str | None = None
|
|
preferred_channel: SalesPreferredChannel | None = None
|
|
assigned_agent_type: SalesAgentType | None = None
|
|
status: SalesLeadStatus | None = None
|
|
|
|
|
|
class SalesLeadEnrichIn(BaseModel):
|
|
need_summary: str | None = None
|
|
product_context: dict = Field(default_factory=dict)
|
|
customer_type: str | None = None
|
|
preferred_channel: SalesPreferredChannel | None = None
|
|
scenario_type: SalesScenarioType | None = None
|
|
required_fields: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesLeadOut(BaseModel):
|
|
lead_id: str
|
|
tenant_id: str
|
|
deal_id: str | None = None
|
|
source_type: str
|
|
source_channel: str
|
|
source_campaign_id: str | None = None
|
|
full_name: str
|
|
company_name: str | None = None
|
|
phone: str | None = None
|
|
email: str | None = None
|
|
messenger_handles: dict = Field(default_factory=dict)
|
|
lead_temperature: SalesLeadTemperature
|
|
lead_score: float
|
|
customer_type: str | None = None
|
|
segment_type: str | None = None
|
|
initial_need_summary: str | None = None
|
|
preferred_channel: SalesPreferredChannel
|
|
assigned_agent_type: SalesAgentType
|
|
status: SalesLeadStatus
|
|
crm_customer_id: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesCustomerOut(BaseModel):
|
|
customer_id: str
|
|
display_name: str
|
|
phones: list = Field(default_factory=list)
|
|
preferred_phone: str | None = None
|
|
tags: list = Field(default_factory=list)
|
|
deal_count: int = 0
|
|
created_at: str
|
|
|
|
|
|
class SalesCustomerUpdate(BaseModel):
|
|
display_name: str | None = Field(default=None, min_length=2)
|
|
phones: list | None = None
|
|
preferred_phone: str | None = None
|
|
tags: list | None = None
|
|
|
|
|
|
class SalesDealCreate(BaseModel):
|
|
lead_id: str | None = None
|
|
customer_id: str | None = None
|
|
stage_id: str | None = Field(default=None, min_length=2)
|
|
stage_code: str | None = Field(default=None, min_length=2)
|
|
scenario_type: SalesScenarioType = "quick_sale"
|
|
priority: int = Field(default=3, ge=1, le=5)
|
|
title: str = Field(min_length=3)
|
|
need_summary: str | None = None
|
|
product_context: dict = Field(default_factory=dict)
|
|
estimated_amount: float | None = Field(default=None, ge=0)
|
|
final_amount: float | None = Field(default=None, ge=0)
|
|
currency: str = "KZT"
|
|
payment_model: str | None = None
|
|
document_required: bool = True
|
|
payment_required: bool = True
|
|
preferred_channel: SalesPreferredChannel = "telegram"
|
|
current_channel: SalesPreferredChannel = "telegram"
|
|
|
|
|
|
class SalesDealUpdate(BaseModel):
|
|
title: str | None = Field(default=None, min_length=3)
|
|
need_summary: str | None = None
|
|
product_context: dict | None = None
|
|
estimated_amount: float | None = Field(default=None, ge=0)
|
|
final_amount: float | None = Field(default=None, ge=0)
|
|
currency: str | None = None
|
|
payment_model: str | None = None
|
|
document_required: bool | None = None
|
|
payment_required: bool | None = None
|
|
preferred_channel: SalesPreferredChannel | None = None
|
|
current_channel: SalesPreferredChannel | None = None
|
|
assigned_human_user_id: str | None = None
|
|
next_action_type: str | None = None
|
|
next_action_at: str | None = None
|
|
|
|
|
|
class SalesDealStageChangeIn(BaseModel):
|
|
stage_id: str | None = Field(default=None, min_length=2)
|
|
stage_code: str | None = Field(default=None, min_length=2)
|
|
target_stage_id: str | None = Field(default=None, min_length=2)
|
|
target_stage_code: str | None = Field(default=None, min_length=2)
|
|
reason: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
force: bool = False
|
|
|
|
|
|
class SalesDealScenarioIn(BaseModel):
|
|
scenario_type: SalesScenarioType
|
|
|
|
|
|
class SalesDealNextActionIn(BaseModel):
|
|
next_action_type: str = Field(min_length=2)
|
|
next_action_at: str | None = None
|
|
payload: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesDealCloseIn(BaseModel):
|
|
status: Literal["won", "lost", "postponed"]
|
|
reason: str | None = None
|
|
|
|
|
|
class SalesDealOut(BaseModel):
|
|
deal_id: str
|
|
tenant_id: str
|
|
lead_id: str | None = None
|
|
customer_id: str | None = None
|
|
pipeline_id: str
|
|
stage_id: str
|
|
pipeline: SalesPipelineOut | None = None
|
|
stage: SalesStageRefOut | None = None
|
|
scenario_type: SalesScenarioType
|
|
priority: int
|
|
title: str
|
|
need_summary: str | None = None
|
|
product_context: dict = Field(default_factory=dict)
|
|
estimated_amount: float | None = None
|
|
final_amount: float | None = None
|
|
currency: str
|
|
payment_model: str | None = None
|
|
document_required: bool = True
|
|
payment_required: bool = True
|
|
assigned_human_user_id: str | None = None
|
|
assigned_ai_orchestrator_id: str | None = None
|
|
preferred_channel: str
|
|
current_channel: str
|
|
status: SalesDealStatus
|
|
won_reason: str | None = None
|
|
lost_reason: str | None = None
|
|
close_reason: str | None = None
|
|
next_action_type: str | None = None
|
|
next_action_at: str | None = None
|
|
last_contact_at: str | None = None
|
|
closed_at: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesCommunicationStartIn(BaseModel):
|
|
channel_type: SalesChannelType
|
|
direction: SalesDirection = "outbound"
|
|
agent_type: SalesAgentType | None = None
|
|
subject: str | None = None
|
|
summary: str | None = None
|
|
next_action_type: str | None = None
|
|
next_action_at: str | None = None
|
|
|
|
|
|
class SalesCommunicationSummaryIn(BaseModel):
|
|
summary: str = Field(min_length=2)
|
|
result_code: str | None = None
|
|
sentiment: str | None = None
|
|
next_action_type: str | None = None
|
|
next_action_at: str | None = None
|
|
|
|
|
|
class SalesCommunicationSwitchChannelIn(BaseModel):
|
|
to_channel: SalesSwitchChannel
|
|
reason_code: str = "human_decision"
|
|
reason_text: str | None = None
|
|
reason_for_channel_switch: str | None = None
|
|
create_session: bool = False
|
|
scheduled_at: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
source_type: str | None = None
|
|
source_id: str | None = None
|
|
recommended_by_task_id: str | None = None
|
|
|
|
|
|
class SalesCommunicationBindExternalIn(BaseModel):
|
|
channel_provider: str | None = None
|
|
telegram_thread_id: str | None = None
|
|
telegram_chat_id: str | None = None
|
|
voice_session_id: str | None = None
|
|
external_call_id: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesCommunicationOut(BaseModel):
|
|
communication_id: str
|
|
tenant_id: str
|
|
deal_id: str
|
|
lead_id: str | None = None
|
|
customer_id: str | None = None
|
|
channel_type: SalesChannelType
|
|
channel_provider: str | None = None
|
|
direction: SalesDirection
|
|
agent_type: SalesAgentType
|
|
started_at: str
|
|
ended_at: str | None = None
|
|
duration_sec: int | None = None
|
|
subject: str | None = None
|
|
status: str
|
|
summary: str | None = None
|
|
transcript_id: str | None = None
|
|
next_action_type: str | None = None
|
|
next_action_at: str | None = None
|
|
sentiment: str | None = None
|
|
result_code: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesMessageWebhookIn(BaseModel):
|
|
deal_id: str | None = None
|
|
lead_id: str | None = None
|
|
phone: str | None = None
|
|
channel_provider: str = "telegram"
|
|
external_message_id: str | None = None
|
|
sender_id: str | None = None
|
|
body: str = Field(min_length=1)
|
|
attachments: list[dict] = Field(default_factory=list)
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesMessageSendIn(BaseModel):
|
|
deal_id: str
|
|
communication_id: str | None = None
|
|
channel_provider: str = "telegram"
|
|
sender_type: Literal["text_ai", "human"] = "text_ai"
|
|
sender_id: str | None = None
|
|
body: str = Field(min_length=1)
|
|
attachments: list[dict] = Field(default_factory=list)
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesMessageOut(BaseModel):
|
|
message_id: str
|
|
deal_id: str
|
|
communication_id: str
|
|
sender_type: str
|
|
sender_id: str | None = None
|
|
channel_provider: str
|
|
external_message_id: str | None = None
|
|
body: str
|
|
attachments: list[dict] = Field(default_factory=list)
|
|
delivery_status: str | None = None
|
|
read_status: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
sent_at: str
|
|
created_at: str
|
|
|
|
|
|
class SalesCallWebhookIn(BaseModel):
|
|
deal_id: str | None = None
|
|
lead_id: str | None = None
|
|
phone_number: str
|
|
provider: str = "asterisk"
|
|
external_call_id: str | None = None
|
|
subject: str | None = None
|
|
|
|
|
|
class SalesCallCompleteIn(BaseModel):
|
|
summary: str | None = None
|
|
recording_url: str | None = None
|
|
result_code: str | None = None
|
|
|
|
|
|
class SalesTranscriptIn(BaseModel):
|
|
language: str = "ru"
|
|
transcript_text: str = Field(min_length=1)
|
|
diarization: dict = Field(default_factory=dict)
|
|
extracted_entities: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesTranscriptOut(BaseModel):
|
|
transcript_id: str
|
|
call_id: str
|
|
language: str
|
|
transcript_text: str
|
|
diarization: dict = Field(default_factory=dict)
|
|
extracted_entities: dict = Field(default_factory=dict)
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesCallOut(BaseModel):
|
|
call_id: str
|
|
deal_id: str
|
|
communication_id: str
|
|
phone_number: str
|
|
direction: SalesDirection
|
|
provider: str
|
|
external_call_id: str | None = None
|
|
recording_url: str | None = None
|
|
transcript_status: SalesTranscriptStatus
|
|
transcript_id: str | None = None
|
|
call_status: str
|
|
started_at: str
|
|
ended_at: str | None = None
|
|
duration_sec: int | None = None
|
|
summary: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesOfferCreate(BaseModel):
|
|
offer_type: SalesOfferType = "offer"
|
|
title: str = Field(min_length=3)
|
|
description: str | None = None
|
|
line_items: list[dict] = Field(default_factory=list)
|
|
pricing: dict = Field(default_factory=dict)
|
|
total_amount: float = Field(ge=0)
|
|
currency: str = "KZT"
|
|
validity_until: str | None = None
|
|
rendered_document_url: str | None = None
|
|
|
|
|
|
class SalesOfferOut(BaseModel):
|
|
offer_id: str
|
|
deal_id: str
|
|
offer_type: SalesOfferType
|
|
title: str
|
|
description: str | None = None
|
|
line_items: list[dict] = Field(default_factory=list)
|
|
pricing: dict = Field(default_factory=dict)
|
|
total_amount: float
|
|
currency: str
|
|
validity_until: str | None = None
|
|
status: SalesOfferStatus
|
|
rendered_document_url: str | None = None
|
|
created_by_type: str
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesConditionUpsertIn(BaseModel):
|
|
product_name: str | None = None
|
|
service_name: str | None = None
|
|
quantity: float | None = Field(default=None, ge=0)
|
|
unit: str | None = None
|
|
delivery_mode: str | None = None
|
|
execution_date: str | None = None
|
|
start_date: str | None = None
|
|
end_date: str | None = None
|
|
payment_terms: str | None = None
|
|
custom_terms: dict = Field(default_factory=dict)
|
|
agreed_price: float | None = Field(default=None, ge=0)
|
|
currency: str = "KZT"
|
|
|
|
|
|
class SalesConditionOut(BaseModel):
|
|
condition_id: str
|
|
deal_id: str
|
|
product_name: str | None = None
|
|
service_name: str | None = None
|
|
quantity: float | None = None
|
|
unit: str | None = None
|
|
delivery_mode: str | None = None
|
|
execution_date: str | None = None
|
|
start_date: str | None = None
|
|
end_date: str | None = None
|
|
payment_terms: str | None = None
|
|
custom_terms: dict = Field(default_factory=dict)
|
|
agreed_price: float | None = None
|
|
currency: str
|
|
confirmed_at: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesCounterpartyUpsertIn(BaseModel):
|
|
company_name: str | None = None
|
|
full_name: str | None = None
|
|
bin_iin: str | None = None
|
|
address: str | None = None
|
|
bank_details: dict = Field(default_factory=dict)
|
|
signer_name: str | None = None
|
|
signer_role: str | None = None
|
|
signer_basis: str | None = None
|
|
email_for_docs: str | None = None
|
|
phone_for_docs: str | None = None
|
|
|
|
|
|
class SalesCounterpartyOut(BaseModel):
|
|
counterparty_id: str
|
|
deal_id: str
|
|
customer_id: str | None = None
|
|
company_name: str | None = None
|
|
full_name: str | None = None
|
|
bin_iin: str | None = None
|
|
address: str | None = None
|
|
bank_details: dict = Field(default_factory=dict)
|
|
signer_name: str | None = None
|
|
signer_role: str | None = None
|
|
signer_basis: str | None = None
|
|
email_for_docs: str | None = None
|
|
phone_for_docs: str | None = None
|
|
completeness_status: str
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesDocumentCreate(BaseModel):
|
|
document_type: SalesDocumentType
|
|
template_id: str | None = None
|
|
version: int = Field(default=1, ge=1)
|
|
rendered_payload: dict = Field(default_factory=dict)
|
|
file_url: str | None = None
|
|
|
|
|
|
class SalesDocumentOut(BaseModel):
|
|
document_id: str
|
|
deal_id: str
|
|
customer_id: str | None = None
|
|
document_type: SalesDocumentType
|
|
template_id: str | None = None
|
|
version: int
|
|
status: SalesDocumentStatus
|
|
file_url: str | None = None
|
|
rendered_payload: dict = Field(default_factory=dict)
|
|
external_sign_provider_id: str | None = None
|
|
signed_at: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesInvoiceCreate(BaseModel):
|
|
basis_document_id: str | None = None
|
|
amount: float = Field(ge=0)
|
|
currency: str = "KZT"
|
|
due_date: str | None = None
|
|
payment_link: str | None = None
|
|
line_items: list[dict] = Field(default_factory=list)
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesInvoiceOut(BaseModel):
|
|
invoice_id: str
|
|
deal_id: str
|
|
customer_id: str | None = None
|
|
invoice_number: str
|
|
basis_document_id: str | None = None
|
|
amount: float
|
|
currency: str
|
|
due_date: str | None = None
|
|
status: SalesInvoiceStatus
|
|
payment_link: str | None = None
|
|
line_items: list[dict] = Field(default_factory=list)
|
|
metadata: dict = Field(default_factory=dict)
|
|
issued_at: str | None = None
|
|
paid_at: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesPaymentWebhookIn(BaseModel):
|
|
deal_id: str
|
|
invoice_id: str | None = None
|
|
payment_provider: str = "manual"
|
|
provider_account_id: str | None = None
|
|
external_event_id: str | None = None
|
|
external_payment_id: str | None = None
|
|
event_type: str | None = None
|
|
provider_status: str | None = None
|
|
amount: float = Field(ge=0)
|
|
currency: str = "KZT"
|
|
status: SalesPaymentStatus = "success"
|
|
paid_at: str | None = None
|
|
payment_method: str | None = None
|
|
failure_reason: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesPaymentReconcileIn(BaseModel):
|
|
status: SalesPaymentStatus
|
|
failure_reason: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesPaymentOut(BaseModel):
|
|
payment_id: str
|
|
deal_id: str
|
|
invoice_id: str | None = None
|
|
payment_provider: str | None = None
|
|
external_payment_id: str | None = None
|
|
amount: float
|
|
currency: str
|
|
status: SalesPaymentStatus
|
|
paid_at: str | None = None
|
|
payment_method: str | None = None
|
|
failure_reason: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesEscalationCreateIn(BaseModel):
|
|
escalation_type: str = Field(min_length=2)
|
|
reason: str = Field(min_length=3)
|
|
severity: SalesEscalationSeverity = "medium"
|
|
assigned_to_user_id: str | None = None
|
|
source_channel: str | None = None
|
|
source_communication_session_id: str | None = None
|
|
source_automation_task_id: str | None = None
|
|
sla_due_at: str | None = None
|
|
|
|
|
|
class SalesEscalationOut(BaseModel):
|
|
escalation_id: str
|
|
deal_id: str
|
|
escalation_type: str
|
|
reason: str
|
|
severity: SalesEscalationSeverity
|
|
status: SalesEscalationStatus
|
|
assigned_to_user_id: str | None = None
|
|
assigned_at: str | None = None
|
|
started_at: str | None = None
|
|
created_at: str
|
|
resolved_at: str | None = None
|
|
canceled_at: str | None = None
|
|
resolution_code: str | None = None
|
|
resolution_summary: str | None = None
|
|
sla_due_at: str | None = None
|
|
source_channel: str | None = None
|
|
source_communication_session_id: str | None = None
|
|
source_automation_task_id: str | None = None
|
|
updated_at: str | None = None
|
|
|
|
|
|
class SalesEscalationAssignIn(BaseModel):
|
|
assigned_to_user_id: str = Field(min_length=1)
|
|
|
|
|
|
class SalesEscalationResolveIn(BaseModel):
|
|
resolution_code: str = Field(min_length=2)
|
|
resolution_summary: str | None = None
|
|
target_stage_code: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesEscalationCancelIn(BaseModel):
|
|
resolution_code: str = "canceled"
|
|
resolution_summary: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesAutomationTaskOut(BaseModel):
|
|
task_id: str
|
|
deal_id: str
|
|
deal_title: str | None = None
|
|
deal_status: SalesDealStatus | None = None
|
|
deal_stage_id: str | None = None
|
|
deal_stage_code: str | None = None
|
|
deal_pipeline_id: str | None = None
|
|
task_type: str
|
|
payload: dict = Field(default_factory=dict)
|
|
run_at: str
|
|
status: SalesAutomationStatus
|
|
retry_count: int = 0
|
|
max_retries: int = 3
|
|
locked_at: str | None = None
|
|
locked_by: str | None = None
|
|
completed_at: str | None = None
|
|
failed_at: str | None = None
|
|
last_error: str | None = None
|
|
recommended_to_channel: SalesSwitchChannel | str | None = None
|
|
reason_code: str | None = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
class SalesStageHistoryOut(BaseModel):
|
|
history_id: str
|
|
deal_id: str
|
|
from_stage_id: str | None = None
|
|
to_stage_id: str
|
|
from_stage: SalesStageRefOut | None = None
|
|
to_stage: SalesStageRefOut | None = None
|
|
changed_by_type: str
|
|
changed_by_id: str | None = None
|
|
reason: str | None = None
|
|
changed_at: str
|
|
|
|
|
|
class SalesChannelSwitchOut(BaseModel):
|
|
switch_id: str
|
|
deal_id: str
|
|
communication_id: str | None = None
|
|
communication_session_id: str | None = None
|
|
previous_communication_session_id: str | None = None
|
|
new_communication_session_id: str | None = None
|
|
from_channel: str
|
|
to_channel: str
|
|
reason_code: str
|
|
reason_text: str | None = None
|
|
reason_for_channel_switch: str
|
|
initiated_by_type: str
|
|
initiated_by_id: str | None = None
|
|
source_type: str | None = None
|
|
source_id: str | None = None
|
|
recommended_by_task_id: str | None = None
|
|
switched_at: str
|
|
created_at: str
|
|
new_communication: SalesCommunicationOut | None = None
|
|
|
|
|
|
class SalesNoteCreateIn(BaseModel):
|
|
note_type: str = "general"
|
|
content: str = Field(min_length=1)
|
|
source_type: str | None = None
|
|
source_id: str | None = None
|
|
|
|
|
|
class SalesNoteUpdateIn(BaseModel):
|
|
note_type: str | None = None
|
|
content: str | None = Field(default=None, min_length=1)
|
|
source_type: str | None = None
|
|
source_id: str | None = None
|
|
|
|
|
|
class SalesNoteOut(BaseModel):
|
|
note_id: str
|
|
deal_id: str
|
|
author_type: str
|
|
author_id: str | None = None
|
|
note_type: str
|
|
content: str
|
|
source_type: str | None = None
|
|
source_id: str | None = None
|
|
created_at: str
|
|
updated_at: str | None = None
|
|
archived_at: str | None = None
|
|
|
|
|
|
class SalesTimelineEventOut(BaseModel):
|
|
ts: str
|
|
kind: str
|
|
title: str
|
|
body: str
|
|
meta: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesWorkspaceOut(BaseModel):
|
|
lead: SalesLeadOut | None = None
|
|
deal: SalesDealOut
|
|
pipeline: SalesPipelineOut | None = None
|
|
stage: SalesStageRefOut | None = None
|
|
communications: list[SalesCommunicationOut] = Field(default_factory=list)
|
|
messages: list[SalesMessageOut] = Field(default_factory=list)
|
|
calls: list[SalesCallOut] = Field(default_factory=list)
|
|
transcripts: list[SalesTranscriptOut] = Field(default_factory=list)
|
|
notes: list[SalesNoteOut] = Field(default_factory=list)
|
|
offers: list[SalesOfferOut] = Field(default_factory=list)
|
|
conditions: list[SalesConditionOut] = Field(default_factory=list)
|
|
counterparty: SalesCounterpartyOut | None = None
|
|
documents: list[SalesDocumentOut] = Field(default_factory=list)
|
|
invoices: list[SalesInvoiceOut] = Field(default_factory=list)
|
|
payments: list[SalesPaymentOut] = Field(default_factory=list)
|
|
escalations: list[SalesEscalationOut] = Field(default_factory=list)
|
|
active_escalation: SalesEscalationOut | None = None
|
|
tasks: list[SalesAutomationTaskOut] = Field(default_factory=list)
|
|
stage_history: list[SalesStageHistoryOut] = Field(default_factory=list)
|
|
channel_switches: list[SalesChannelSwitchOut] = Field(default_factory=list)
|
|
recommended_channel_switch: dict | None = None
|
|
timeline: list[SalesTimelineEventOut] = Field(default_factory=list)
|
|
|
|
|
|
class SalesDashboardStageOut(BaseModel):
|
|
stage_id: str
|
|
label: str
|
|
stage: SalesStageRefOut | None = None
|
|
count: int = 0
|
|
amount: float = 0.0
|
|
|
|
|
|
class SalesDashboardSummaryOut(BaseModel):
|
|
leads_total: int = 0
|
|
deals_active: int = 0
|
|
deals_won: int = 0
|
|
deals_lost: int = 0
|
|
overdue_invoices: int = 0
|
|
payment_expected: float = 0.0
|
|
payment_received: float = 0.0
|
|
voice_sessions: int = 0
|
|
text_sessions: int = 0
|
|
channel_switches: int = 0
|
|
human_escalations: int = 0
|
|
stage_counts: list[SalesDashboardStageOut] = Field(default_factory=list)
|
|
hottest_deals: list[SalesDealOut] = Field(default_factory=list)
|
|
|
|
|
|
class SalesTelegramSyncIn(BaseModel):
|
|
thread_id: str = Field(min_length=1)
|
|
chat_id: str = Field(min_length=1)
|
|
interaction_id: str | None = None
|
|
customer_id: str | None = None
|
|
phone_number: str | None = None
|
|
display_name: str | None = None
|
|
queue_id: str | None = None
|
|
status: str | None = None
|
|
ai_state: str | None = None
|
|
ai_handoff_reason: str | None = None
|
|
message_id: str | None = None
|
|
external_message_id: str | None = None
|
|
text: str | None = None
|
|
direction: str = "inbound"
|
|
author_type: str | None = None
|
|
author_id: str | None = None
|
|
happened_at: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|
|
|
|
|
|
class SalesVoiceSyncIn(BaseModel):
|
|
call_id: str = Field(min_length=1)
|
|
interaction_id: str | None = None
|
|
queue_id: str | None = None
|
|
queue_code: str | None = None
|
|
caller_number: str | None = None
|
|
caller_name: str | None = None
|
|
voice_session_id: str | None = None
|
|
ai_session_id: str | None = None
|
|
ai_state: str | None = None
|
|
handoff_reason: str | None = None
|
|
telephony_status: str | None = None
|
|
call_status: str | None = None
|
|
started_at: str | None = None
|
|
ended_at: str | None = None
|
|
summary: str | None = None
|
|
transcript_text: str | None = None
|
|
metadata: dict = Field(default_factory=dict)
|