# -*- coding: utf-8 -*- """ CRM 业务数据模型 定义客户沟通日志、标签、跟进待办、销售机会四张业务表。 所有主键均为 UUID,与 User/KnowledgeChunk 保持一致的 ID 策略。 """ import uuid from datetime import datetime from sqlalchemy import ForeignKey, String, Text, Numeric, func from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from app.core.database import Base class CustomerLog(Base): """ 客户沟通日志表 记录每次与客户的沟通内容(电话/拜访/微信等), 新增日志时会触发后台 AI 任务自动提取标签和待办。 """ __tablename__ = "customer_logs" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) customer_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True, comment="关联客户 ID", ) content: Mapped[str] = mapped_column( Text, nullable=False, comment="沟通日志内容", ) created_at: Mapped[datetime] = mapped_column( server_default=func.now(), comment="记录时间", ) class CustomerTag(Base): """ 客户标签表 由 AI 从沟通日志中自动提取,也支持手动添加。 同一客户下的标签名唯一(通过业务逻辑控制去重)。 """ __tablename__ = "customer_tags" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) customer_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True, comment="关联客户 ID", ) tag_name: Mapped[str] = mapped_column( String(100), nullable=False, comment="标签名称,如'价格敏感'、'决策周期长'", ) created_at: Mapped[datetime] = mapped_column( server_default=func.now(), ) class FollowUpToDo(Base): """ 跟进待办表 由 AI 根据沟通日志自动生成下一步行动建议, 也可由用户手动创建。status 为简单的二态: pending / done。 """ __tablename__ = "follow_up_todos" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) customer_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True, comment="关联客户 ID", ) task_desc: Mapped[str] = mapped_column( Text, nullable=False, comment="待办任务描述", ) status: Mapped[str] = mapped_column( String(20), nullable=False, default="pending", comment="状态: pending(待处理) / done(已完成)", ) created_at: Mapped[datetime] = mapped_column( server_default=func.now(), ) class SalesOpportunity(Base): """ 销售机会表 跟踪每个客户的销售漏斗阶段和金额,用于经营看板和复盘报告。 stage 四阶段: 意向 → 谈判 → 成交 → 流失 """ __tablename__ = "sales_opportunities" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) customer_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True, comment="关联客户 ID", ) amount: Mapped[float] = mapped_column( Numeric(12, 2), nullable=False, default=0, comment="预估/实际金额 (元)", ) stage: Mapped[str] = mapped_column( String(20), nullable=False, default="意向", comment="漏斗阶段: 意向 / 谈判 / 成交 / 流失", ) created_at: Mapped[datetime] = mapped_column( server_default=func.now(), )