Implement sales CRM workflow foundation
This commit is contained in:
@@ -38,9 +38,10 @@ SalesDocumentStatus = Literal["draft", "sent", "under_review", "confirmed", "sig
|
||||
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", "in_progress", "resolved"]
|
||||
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):
|
||||
@@ -222,7 +223,11 @@ class SalesDealUpdate(BaseModel):
|
||||
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):
|
||||
@@ -295,8 +300,16 @@ class SalesCommunicationSummaryIn(BaseModel):
|
||||
|
||||
|
||||
class SalesCommunicationSwitchChannelIn(BaseModel):
|
||||
to_channel: SalesPreferredChannel
|
||||
reason_for_channel_switch: str = Field(min_length=3)
|
||||
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):
|
||||
@@ -315,6 +328,7 @@ class SalesCommunicationOut(BaseModel):
|
||||
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
|
||||
@@ -580,7 +594,11 @@ 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"
|
||||
@@ -618,6 +636,10 @@ class SalesEscalationCreateIn(BaseModel):
|
||||
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):
|
||||
@@ -628,8 +650,35 @@ class SalesEscalationOut(BaseModel):
|
||||
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):
|
||||
@@ -640,6 +689,11 @@ class SalesAutomationTaskOut(BaseModel):
|
||||
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
|
||||
created_at: str
|
||||
updated_at: str
|
||||
@@ -662,10 +716,50 @@ 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):
|
||||
@@ -684,6 +778,8 @@ class SalesWorkspaceOut(BaseModel):
|
||||
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
|
||||
@@ -691,9 +787,11 @@ class SalesWorkspaceOut(BaseModel):
|
||||
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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user