Implement sales CRM workflow foundation

This commit is contained in:
Admin
2026-05-10 20:54:01 +05:00
parent dad4ab115a
commit 8577d97356
22 changed files with 5625 additions and 242 deletions
+76
View File
@@ -178,6 +178,7 @@ class SalesCommunicationSessionRow(Base):
lead_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
customer_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
channel_type: Mapped[str] = mapped_column(String(16), index=True)
channel_provider: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True)
direction: Mapped[str] = mapped_column(String(16), index=True)
agent_type: Mapped[str] = mapped_column(String(32), index=True)
started_at: Mapped[str] = mapped_column(String(64), index=True)
@@ -275,7 +276,11 @@ class SalesNoteRow(Base):
author_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
note_type: Mapped[str] = mapped_column(String(64), index=True)
content: Mapped[str] = mapped_column(Text)
source_type: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
source_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
created_at: Mapped[str] = mapped_column(String(64), index=True)
updated_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
archived_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
class SalesOfferRow(Base):
@@ -403,6 +408,15 @@ class SalesPaymentRow(Base):
__tablename__ = "sales_payments"
__table_args__ = (
Index("idx_sales_payments_deal_status", "deal_id", "status"),
Index(
"idx_sales_payments_tenant_external_payment_unique",
"tenant_id",
"payment_provider",
"external_payment_id",
unique=True,
sqlite_where=text("external_payment_id IS NOT NULL"),
postgresql_where=text("external_payment_id IS NOT NULL"),
),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
@@ -423,6 +437,41 @@ class SalesPaymentRow(Base):
updated_at: Mapped[str] = mapped_column(String(64), index=True)
class SalesPaymentWebhookEventRow(Base):
__tablename__ = "sales_payment_webhook_events"
__table_args__ = (
Index("idx_sales_payment_webhook_events_received", "tenant_id", "received_at"),
Index("idx_sales_payment_webhook_events_payment", "tenant_id", "payment_provider", "external_payment_id"),
Index(
"idx_sales_payment_webhook_events_external_event_unique",
"tenant_id",
"payment_provider",
"external_event_id",
unique=True,
sqlite_where=text("external_event_id IS NOT NULL"),
postgresql_where=text("external_event_id IS NOT NULL"),
),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
tenant_id: Mapped[str] = mapped_column(String(64), index=True)
payment_provider: Mapped[str] = mapped_column(String(64), index=True)
provider_account_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
external_event_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
external_payment_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
event_type: Mapped[str] = mapped_column(String(128), index=True)
event_status: Mapped[str] = mapped_column(String(32), index=True, default="received")
signature_status: Mapped[str] = mapped_column(String(32), index=True, default="unchecked")
raw_payload_hash: Mapped[str] = mapped_column(String(64), index=True)
normalized_payload_json: Mapped[str] = mapped_column(Text, default="{}")
headers_json: Mapped[str] = mapped_column(Text, default="{}")
received_at: Mapped[str] = mapped_column(String(64), index=True)
processed_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[str] = mapped_column(String(64), index=True)
updated_at: Mapped[str] = mapped_column(String(64), index=True)
class SalesStageHistoryRow(Base):
__tablename__ = "sales_stage_history"
__table_args__ = (
@@ -456,14 +505,25 @@ class SalesEscalationRow(Base):
severity: Mapped[str] = mapped_column(String(16), index=True)
status: Mapped[str] = mapped_column(String(32), index=True, default="open")
assigned_to_user_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
assigned_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
started_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
created_at: Mapped[str] = mapped_column(String(64), index=True)
resolved_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
canceled_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
resolution_code: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
resolution_summary: Mapped[str | None] = mapped_column(Text, nullable=True)
sla_due_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
source_channel: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True)
source_communication_session_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
source_automation_task_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
updated_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
class SalesAutomationTaskRow(Base):
__tablename__ = "sales_automation_tasks"
__table_args__ = (
Index("idx_sales_tasks_run_status", "run_at", "status"),
Index("idx_sales_tasks_lock", "status", "locked_at", "locked_by"),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
@@ -475,6 +535,11 @@ class SalesAutomationTaskRow(Base):
run_at: Mapped[str] = mapped_column(String(64), index=True)
status: Mapped[str] = mapped_column(String(32), index=True, default="pending")
retry_count: Mapped[int] = mapped_column(Integer, default=0)
max_retries: Mapped[int] = mapped_column(Integer, default=3)
locked_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
locked_by: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
completed_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
failed_at: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
last_error: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[str] = mapped_column(String(64), index=True)
updated_at: Mapped[str] = mapped_column(String(64), index=True)
@@ -491,10 +556,21 @@ class SalesChannelSwitchRow(Base):
tenant_id: Mapped[str] = mapped_column(String(64), index=True)
deal_id: Mapped[str] = mapped_column(String(64), index=True)
communication_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
communication_session_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
previous_communication_session_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
new_communication_session_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
from_channel: Mapped[str] = mapped_column(String(32), index=True)
to_channel: Mapped[str] = mapped_column(String(32), index=True)
reason_code: Mapped[str] = mapped_column(String(64), default="human_decision", index=True)
reason_text: Mapped[str | None] = mapped_column(Text, nullable=True)
reason_for_channel_switch: Mapped[str] = mapped_column(Text)
initiated_by_type: Mapped[str] = mapped_column(String(32), default="human", index=True)
initiated_by_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
source_type: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
source_id: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
recommended_by_task_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
switched_at: Mapped[str] = mapped_column(String(64), index=True)
created_at: Mapped[str] = mapped_column(String(64), index=True)
class SalesExternalLinkRow(Base):