"""CRM 模块数据模型(产品分类、产品主表、统一附件表、客户管理、公海池、线索管理)""" from datetime import datetime from decimal import Decimal from sqlalchemy import ( BigInteger, Column, DECIMAL, Date, DateTime, Integer, SmallInteger, String, Text, CHAR, ) from app.core.database import Base class CrmProductCategory(Base): """CRM 产品分类表(树形结构)""" __tablename__ = "crm_product_category" id = Column(String(64), primary_key=True, comment="主键ID") parent_id = Column(String(64), nullable=False, default="0", comment="父级分类ID(0为顶级)") category_name = Column(String(128), nullable=False, comment="分类名称") category_code = Column(String(64), nullable=True, comment="分类编码") level = Column(SmallInteger, nullable=False, default=1, comment="层级") status = Column(CHAR(1), nullable=False, default="1", comment="状态 1启用 0停用") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人id") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人id") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmProduct(Base): """CRM 产品主表""" __tablename__ = "crm_product" id = Column(String(64), primary_key=True, comment="主键ID") product_no = Column(String(50), nullable=False, comment="产品编号") product_name = Column(String(200), nullable=False, comment="产品名称") name_pinyin_abbr = Column(String(100), nullable=True, comment="产品名称拼音首字母(小写)") category_id = Column(String(64), nullable=True, comment="分类ID") category_name = Column(String(100), nullable=True, comment="分类名称(冗余)") model = Column(String(100), nullable=True, comment="规格型号") unit = Column(String(20), nullable=True, default=None, comment="单位") barcode = Column(String(100), nullable=True, comment="条码") price = Column(DECIMAL(15, 2), nullable=True, default=None, comment="标准单价") cost_price = Column(DECIMAL(15, 2), nullable=True, default=None, comment="成本价") stock = Column(Integer, nullable=False, default=0, comment="库存数量") low_stock = Column(Integer, nullable=False, default=10, comment="库存预警值") tax_rate = Column(DECIMAL(5, 2), nullable=False, default=13.00, comment="税率(百分比)") is_toxic = Column(SmallInteger, nullable=False, default=0, comment="是否易制毒 0-否 1-是") is_explosive = Column(SmallInteger, nullable=False, default=0, comment="是否易制爆 0-否 1-是") status = Column(String(3), nullable=False, default="on", comment="状态 on 上架 off 下架") description = Column(Text, nullable=True, comment="产品描述") images = Column(String(1000), nullable=True, comment="产品图片(多个用逗号分隔)") sale_count = Column(Integer, nullable=False, default=0, comment="销售次数") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人id") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人id") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmProductBrand(Base): """CRM-产品品牌(按产品独立维护)""" __tablename__ = "crm_product_brand" id = Column(String(64), primary_key=True, comment="主键ID") product_id = Column(String(64), nullable=False, comment="产品ID") brand_name = Column(String(100), nullable=False, comment="品牌名称") status = Column(String(3), nullable=False, default="on", comment="状态 on/off") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人id") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人id") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmProductAlias(Base): """CRM-产品别名""" __tablename__ = "crm_product_alias" id = Column(String(64), primary_key=True, comment="主键ID") product_id = Column(String(64), nullable=False, comment="产品ID") alias_name = Column(String(200), nullable=False, comment="别名") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人id") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人id") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class SysOss(Base): """统一附件表(全系统共用 sys_oss)""" __tablename__ = "sys_oss" id = Column(String(64), primary_key=True, comment="主键ID") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") biz_type = Column(String(50), nullable=True, comment="业务类型") biz_id = Column(String(64), nullable=True, comment="业务主键ID") file_name = Column(String(255), nullable=False, default="", comment="文件名") original_name = Column(String(255), nullable=False, default="", comment="原始文件名") file_suffix = Column(String(10), nullable=False, default="", comment="文件后缀名") url = Column(String(500), nullable=False, comment="文件URL地址") file_size = Column(BigInteger, nullable=True, comment="文件大小(字节)") file_type = Column(String(200), nullable=True, comment="MIME类型") attach_type = Column(String(32), nullable=True, default="attachment", comment="附件类型") sort_order = Column(Integer, nullable=False, default=0, comment="排序号") service = Column(String(20), nullable=False, default="minio", comment="存储服务商") ext1 = Column(Text, nullable=True, comment="扩展字段") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人id") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人id") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") # ── 客户管理模块 ────────────────────────────────────────────── class CrmCustomer(Base): """CRM-客户主表""" __tablename__ = "crm_customer" # 主键 id = Column(String(64), primary_key=True, comment="主键ID(UUID)") # 业务字段 customer_no = Column(String(50), nullable=False, comment="客户编号(唯一)") customer_name = Column(String(200), nullable=False, comment="客户名称") name_pinyin_abbr = Column(String(100), nullable=True, comment="客户名称拼音首字母(小写)") short_name = Column(String(100), nullable=True, comment="客户简称") customer_type = Column(String(20), nullable=True, default="company", comment="客户类型(字典 crm_customer_type)") mobile = Column(String(20), nullable=True, comment="手机号") telephone = Column(String(30), nullable=True, comment="固定电话") email = Column(String(100), nullable=True, comment="邮箱") website = Column(String(500), nullable=True, comment="客户网站") level = Column( String(20), nullable=True, default="normal", comment="客户级别(字典 crm_customer_level: key/normal/potential)" ) source = Column(String(20), nullable=True, comment="客户来源(字典 crm_clue_source)") industry = Column(String(50), nullable=True, comment="所属行业(字典 crm_customer_industry)") park_area = Column(String(100), nullable=True, comment="所在园区(字典 crm_customer_park)") payment_terms = Column(String(500), nullable=True, comment="收付款条件") scale = Column(String(20), nullable=True, comment="企业规模") province = Column(String(50), nullable=True, comment="省") city = Column(String(50), nullable=True, comment="市") district = Column(String(50), nullable=True, comment="区") address = Column(String(255), nullable=True, comment="详细地址") # 状态与归属 status = Column( String(20), nullable=True, default="normal", comment="客户状态(字典 crm_customer_status: normal/pool/invalid)" ) deal_status = Column( String(20), nullable=True, default="not_deal", comment="成交状态(字典 crm_deal_status: not_deal/dealed/lost)" ) owner_user_id = Column(String(64), nullable=True, comment="负责人ID") owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)") # 跟进统计 last_time = Column(DateTime, nullable=True, comment="最后跟进时间") next_time = Column(DateTime, nullable=True, comment="下次联系时间") follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数") # 成交统计 deal_time = Column(DateTime, nullable=True, comment="成交时间") deal_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="累计成交金额") # 关联统计 contact_count = Column(Integer, nullable=True, default=0, comment="联系人数量") opportunity_count = Column(Integer, nullable=True, default=0, comment="商机数量") contract_count = Column(Integer, nullable=True, default=0, comment="合同数量") # 公海池相关 into_pool_time = Column(DateTime, nullable=True, comment="进入公海时间") into_pool_by = Column(String(64), nullable=True, comment="进入公海操作人ID") into_pool_reason = Column(String(500), nullable=True, comment="进入公海原因") claim_time = Column(DateTime, nullable=True, comment="领取时间") assign_time = Column(DateTime, nullable=True, comment="分配时间") assign_by = Column(String(64), nullable=True, comment="分配人ID") protect_time = Column(DateTime, nullable=True, comment="保护到期时间") # 证照附件 business_license_img = Column(String(1000), nullable=True, comment="营业执照图片(附件URL,逗号分隔)") business_permit_images = Column(String(1000), nullable=True, comment="经营许可证图片(附件URL,逗号分隔)") other_cert_images = Column(String(1000), nullable=True, comment="其他证件图片(附件URL,逗号分隔)") # 线索关联 clue_id = Column(String(64), nullable=True, comment="关联线索ID(从线索转化)") # 公共字段 tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContact(Base): """CRM-联系人表""" __tablename__ = "crm_contact" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") contact_name = Column(String(100), nullable=False, comment="联系人姓名") gender = Column(String(10), nullable=True, comment="性别(male/female/unknown)") mobile = Column(String(20), nullable=True, comment="手机号") telephone = Column(String(30), nullable=True, comment="固定电话") email = Column(String(100), nullable=True, comment="邮箱") wechat = Column(String(100), nullable=True, comment="微信号") qq = Column(String(20), nullable=True, comment="QQ号") department = Column(String(100), nullable=True, comment="部门") position = Column(String(50), nullable=True, comment="职位") role = Column(String(20), nullable=True, comment="角色(decision/manager/user/other)") birthday = Column(Date, nullable=True, comment="生日") address = Column(String(255), nullable=True, comment="住址") is_key = Column(SmallInteger, nullable=True, default=0, comment="是否关键决策人(0-否 1-是)") is_primary = Column(SmallInteger, nullable=True, default=0, comment="是否主要联系人(0-否 1-是)") status = Column(String(20), nullable=True, default="active", comment="状态(active-在职/leave-离职)") # 公共字段 tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmInvoiceInfo(Base): """CRM-客户开票信息表""" __tablename__ = "crm_invoice_info" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") customer_id = Column(String(64), nullable=False, comment="客户ID") company_name = Column(String(200), nullable=False, comment="单位名称") tax_no = Column(String(50), nullable=True, comment="税号") company_address = Column(String(500), nullable=True, comment="单位地址") legal_representative = Column(String(100), nullable=True, comment="法定代表人") agent = Column(String(100), nullable=True, comment="代理人") phone_fax = Column(String(100), nullable=True, comment="电话/传真") bank_name = Column(String(200), nullable=True, comment="开户银行") bank_account = Column(String(100), nullable=True, comment="银行账号") is_default = Column(String(1), nullable=False, default="0", comment="是否默认(0否 1是)") # 公共字段 tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmCustomerFollow(Base): """CRM-客户跟进记录表""" __tablename__ = "crm_customer_follow" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") contact_id = Column(String(64), nullable=True, comment="联系人ID") contact_name = Column(String(100), nullable=True, comment="联系人姓名(冗余)") follow_type = Column( String(20), nullable=False, comment="跟进方式(字典 crm_follow_type: phone/wechat/visit/email/other)" ) follow_content = Column(Text, nullable=False, comment="跟进内容") follow_time = Column(DateTime, nullable=True, comment="跟进时间") next_time = Column(DateTime, nullable=True, comment="下次联系时间") attachment = Column(String(1000), nullable=True, comment="附件URL(多个用逗号分隔)") owner_user_id = Column(String(64), nullable=True, comment="跟进人ID") owner_user_name = Column(String(50), nullable=True, comment="跟进人姓名(冗余)") # 公共字段 tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmCustomerPool(Base): """CRM-客户公海池记录表""" __tablename__ = "crm_customer_pool" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") operation_type = Column(String(20), nullable=False, comment="操作类型(into-进入公海/claim-领取/assign-分配/recycle-回收)") from_user_id = Column(String(64), nullable=True, comment="原负责人ID") from_user_name = Column(String(50), nullable=True, comment="原负责人姓名(冗余)") to_user_id = Column(String(64), nullable=True, comment="新负责人ID") to_user_name = Column(String(50), nullable=True, comment="新负责人姓名(冗余)") reason = Column(String(500), nullable=True, comment="操作原因") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者(操作人)") create_by_name = Column(String(50), nullable=True, comment="操作人姓名(冗余)") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间(操作时间)") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmCustomerPoolRule(Base): """CRM-客户公海池规则表""" __tablename__ = "crm_customer_pool_rule" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") pool_name = Column(String(100), nullable=False, comment="规则名称") rule_type = Column(String(20), nullable=False, comment="规则类型(no_follow-未跟进/no_deal-未成交)") timeout_days = Column(Integer, nullable=False, comment="超时天数(多少天未跟进/未成交)") protect_days = Column(Integer, nullable=False, default=0, comment="保护期天数(领取后保护多少天)") status = Column(String(20), nullable=True, default="enable", comment="状态(enable-启用/disable-禁用)") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmOpportunity(Base): """CRM-商机主表""" __tablename__ = "crm_opportunity" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") opportunity_no = Column(String(50), nullable=False, comment="商机编号") opportunity_name = Column(String(200), nullable=False, comment="商机名称") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") contact_id = Column(String(64), nullable=True, comment="联系人ID") contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)") stage = Column(String(20), nullable=False, default="initial", comment="商机阶段") stage_percent = Column(Integer, nullable=True, default=10, comment="阶段进度百分比") status = Column(String(20), nullable=False, default="following", comment="商机状态") win_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("50.00"), comment="赢单率(百分比)") amount = Column(DECIMAL(15, 2), nullable=False, default=0, comment="商机金额") expect_deal_date = Column(Date, nullable=True, comment="预计成交日期") actual_deal_date = Column(Date, nullable=True, comment="实际成交日期") lost_reason = Column(String(500), nullable=True, comment="输单原因") owner_user_id = Column(String(64), nullable=True, comment="负责人ID") owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)") product_count = Column(Integer, nullable=True, default=0, comment="产品数量(冗余)") last_time = Column(DateTime, nullable=True, comment="最后跟进时间") next_time = Column(DateTime, nullable=True, comment="下次联系时间") follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数(冗余)") contract_id = Column(String(64), nullable=True, comment="关联合同ID") source = Column(String(20), nullable=True, comment="商机来源") type = Column(String(20), nullable=True, comment="商机类型") description = Column(Text, nullable=True, comment="商机描述") competitors = Column(String(500), nullable=True, comment="竞争对手") key_factors = Column(String(500), nullable=True, comment="关键决策因素") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmOpportunityFollow(Base): """CRM-商机跟进记录表""" __tablename__ = "crm_opportunity_follow" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") opportunity_id = Column(String(64), nullable=False, comment="商机ID") follow_type = Column(String(20), nullable=False, comment="跟进方式") follow_content = Column(Text, nullable=False, comment="跟进内容") follow_time = Column(DateTime, nullable=True, comment="跟进时间") stage = Column(String(20), nullable=True, comment="当前商机阶段") stage_percent = Column(Integer, nullable=True, comment="阶段进度百分比") next_time = Column(DateTime, nullable=True, comment="下次联系时间") next_content = Column(String(500), nullable=True, comment="下次联系计划") attachments = Column(String(1000), nullable=True, comment="附件(逗号分隔)") contact_id = Column(String(64), nullable=True, comment="联系人ID") contact_name = Column(String(50), nullable=True, comment="联系人姓名") location = Column(String(200), nullable=True, comment="跟进地点") duration = Column(Integer, nullable=True, comment="跟进时长(分钟)") follow_by = Column(String(64), nullable=True, comment="跟进人ID") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmOpportunityProduct(Base): """CRM-商机产品关联表""" __tablename__ = "crm_opportunity_product" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") opportunity_id = Column(String(64), nullable=False, comment="商机ID") product_id = Column(String(64), nullable=False, comment="产品ID") product_name = Column(String(200), nullable=True, comment="产品名称(冗余)") product_no = Column(String(50), nullable=True, comment="产品编号(冗余)") category_id = Column(String(64), nullable=True, comment="产品分类ID") category_name = Column(String(100), nullable=True, comment="产品分类名称(冗余)") model = Column(String(100), nullable=True, comment="规格型号") unit = Column(String(20), nullable=True, default="件", comment="单位") quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量") price = Column(DECIMAL(15, 2), nullable=False, default=0, comment="单价") discount = Column(DECIMAL(5, 2), nullable=True, default=0, comment="折扣(百分比)") subtotal = Column(DECIMAL(15, 2), nullable=False, default=0, comment="小计金额") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmOpportunityStageLog(Base): """CRM-商机阶段变更日志表""" __tablename__ = "crm_opportunity_stage_log" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") opportunity_id = Column(String(64), nullable=False, comment="商机ID") from_stage = Column(String(20), nullable=True, comment="原阶段") from_stage_name = Column(String(50), nullable=True, comment="原阶段名称") from_percent = Column(Integer, nullable=True, comment="原进度百分比") to_stage = Column(String(20), nullable=False, comment="新阶段") to_stage_name = Column(String(50), nullable=True, comment="新阶段名称") to_percent = Column(Integer, nullable=True, comment="新进度百分比") change_type = Column(String(20), nullable=True, default="forward", comment="变更类型") change_reason = Column(String(500), nullable=True, comment="变更原因") change_amount = Column(DECIMAL(15, 2), nullable=True, comment="变更时商机金额") lost_detail = Column(String(2000), nullable=True, comment="输单详细说明") competitor_info = Column(String(1000), nullable=True, comment="竞争对手信息") improvement = Column(String(1000), nullable=True, comment="改进建议") won_remark = Column(String(2000), nullable=True, comment="赢单说明") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContract(Base): """CRM-合同主表""" __tablename__ = "crm_contract" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") contract_no = Column(String(50), nullable=False, comment="合同编号") contract_name = Column(String(200), nullable=False, comment="合同名称") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") opportunity_id = Column(String(64), nullable=True, comment="商机ID") quote_id = Column(String(64), nullable=True, comment="报价单ID") parent_contract_id = Column(String(64), nullable=True, comment="原合同ID(续签)") renewal_count = Column(Integer, nullable=True, default=0, comment="续签次数") template_id = Column(String(64), nullable=True, comment="合同模板ID") contract_template = Column(String(50), nullable=True, default="shanxia", comment="合同模版") contact_id = Column(String(64), nullable=True, comment="联系人ID") contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)") contact_mobile = Column(String(20), nullable=True, comment="联系人手机(冗余)") contract_type = Column(String(20), nullable=False, default="sale", comment="合同类型") contract_nature = Column(String(20), nullable=True, default="new", comment="合同性质") amount = Column(DECIMAL(15, 2), nullable=False, default=0, comment="合同金额") currency = Column(String(10), nullable=True, default="CNY", comment="币种") tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="税率(%)") amount_with_tax = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="含税金额") freight = Column(DECIMAL(18, 2), nullable=False, default=Decimal("0.00"), comment="运费") barrel_deposit = Column(DECIMAL(18, 2), nullable=False, default=Decimal("0.00"), comment="桶押金") status = Column(String(20), nullable=False, default="draft", comment="合同状态") approval_status = Column(String(20), nullable=True, comment="审批状态") sign_date = Column(Date, nullable=True, comment="签订日期") actual_sign_date = Column(Date, nullable=True, comment="实际签订日期") start_date = Column(Date, nullable=True, comment="开始日期") end_date = Column(Date, nullable=True, comment="结束日期") contract_period = Column(Integer, nullable=True, comment="合同期限(月)") performance_status = Column(String(20), nullable=True, default="normal", comment="履约状态") performance_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="履约完成度(%)") customer_satisfaction = Column(Integer, nullable=True, comment="客户满意度") approval_flow_id = Column(String(64), nullable=True, comment="审批流程ID") contract_file = Column(String(500), nullable=True, comment="合同文件路径") attachment_files = Column(String(2000), nullable=True, comment="附件文件") owner_user_id = Column(String(64), nullable=True, comment="负责人ID") owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)") received_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="已回款金额") unreceived_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="未回款金额") invoice_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="已开票金额") uninvoice_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="未开票金额") payment_terms = Column(Text, nullable=True, comment="付款条款") delivery_terms = Column(Text, nullable=True, comment="交付条款") contract_terms = Column(Text, nullable=True, comment="合同条款") settlement_method = Column(String(50), nullable=True, comment="结算方式") template_content = Column(Text, nullable=True, comment="合同模板内容") settlement_clause_drafts = Column(Text, nullable=True, comment="结算方式草稿JSON") invalid_reason = Column(String(500), nullable=True, comment="作废原因") invalid_time = Column(DateTime, nullable=True, comment="作废时间") version_no = Column(Integer, nullable=True, default=0, comment="乐观锁版本号") party_a = Column(String(200), nullable=True, comment="甲方") party_a_address = Column(String(255), nullable=True, comment="甲方地址") party_a_contact = Column(String(50), nullable=True, comment="甲方联系人") party_a_mobile = Column(String(20), nullable=True, comment="甲方联系电话") party_a_legal_person = Column(String(50), nullable=True, comment="甲方法定代表人") party_a_agent = Column(String(50), nullable=True, comment="甲方代理人") party_a_phone_fax = Column(String(50), nullable=True, comment="甲方电话/传真") party_a_bank = Column(String(100), nullable=True, comment="甲方开户银行") party_a_account = Column(String(50), nullable=True, comment="甲方银行账号") party_b = Column(String(200), nullable=True, comment="乙方") party_b_address = Column(String(255), nullable=True, comment="乙方地址") party_b_contact = Column(String(50), nullable=True, comment="乙方联系人") party_b_mobile = Column(String(20), nullable=True, comment="乙方联系电话") party_b_legal_person = Column(String(100), nullable=True, comment="乙方法定代表人") party_b_agent = Column(String(100), nullable=True, comment="乙方代理人") party_b_phone_fax = Column(String(100), nullable=True, comment="乙方电话/传真") party_b_bank = Column(String(200), nullable=True, comment="乙方开户银行") party_b_account = Column(String(100), nullable=True, comment="乙方银行账号") supplier_id = Column(String(64), nullable=True, comment="供方主体ID") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractApproverSetting(Base): """CRM-合同审批人设置(租户级)""" __tablename__ = "crm_contract_approver_setting" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") approver_ids = Column(String(1000), nullable=False, default="", comment="有序审批人用户ID,逗号分隔") status = Column(String(1), nullable=False, default="0", comment="0启用 1停用") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractApproval(Base): """CRM-合同审批记录表""" __tablename__ = "crm_contract_approval" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") contract_id = Column(String(64), nullable=False, comment="合同ID") flow_id = Column(String(64), nullable=True, comment="审批流程ID") step = Column(Integer, nullable=False, default=1, comment="审批步骤") step_name = Column(String(100), nullable=True, comment="步骤名称") approver_id = Column(String(64), nullable=False, comment="审批人ID") approver_name = Column(String(50), nullable=True, comment="审批人姓名(冗余)") approver_dept = Column(String(100), nullable=True, comment="审批人部门") approval_result = Column(String(20), nullable=True, default="pending", comment="审批结果") approval_opinion = Column(Text, nullable=True, comment="审批意见") approval_time = Column(DateTime, nullable=True, comment="审批时间") approval_duration = Column(Integer, nullable=True, comment="审批耗时(小时)") attachments = Column(String(1000), nullable=True, comment="附件") is_current = Column(SmallInteger, nullable=True, default=1, comment="是否当前步骤") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractChange(Base): """CRM-合同变更记录表""" __tablename__ = "crm_contract_change" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") contract_id = Column(String(64), nullable=False, comment="合同ID") contract_no = Column(String(50), nullable=True, comment="合同编号(冗余)") change_type = Column(String(50), nullable=False, comment="变更类型") change_reason = Column(String(500), nullable=False, comment="变更原因") change_content = Column(Text, nullable=True, comment="变更内容描述") old_value = Column(Text, nullable=True, comment="变更前值(JSON)") new_value = Column(Text, nullable=True, comment="变更后值(JSON)") change_amount = Column(DECIMAL(15, 2), nullable=True, comment="变更金额") approval_status = Column(String(20), nullable=True, default="pending", comment="审批状态") approver_id = Column(String(64), nullable=True, comment="审批人ID") approver_name = Column(String(50), nullable=True, comment="审批人姓名") approval_time = Column(DateTime, nullable=True, comment="审批时间") approval_opinion = Column(String(500), nullable=True, comment="审批意见") attachment_files = Column(String(1000), nullable=True, comment="附件文件") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractTemplate(Base): """CRM-合同模板表""" __tablename__ = "crm_contract_template" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") template_no = Column(String(50), nullable=False, comment="模板编号") template_name = Column(String(200), nullable=False, comment="模板名称") contract_type = Column(String(20), nullable=True, comment="适用合同类型") template_content = Column(Text, nullable=True, comment="模板内容") payment_terms = Column(Text, nullable=True, comment="付款条款模板") delivery_terms = Column(Text, nullable=True, comment="交付条款模板") contract_terms = Column(Text, nullable=True, comment="合同条款模板") party_b = Column(String(200), nullable=True, comment="乙方名称") party_b_address = Column(String(255), nullable=True, comment="乙方地址") party_b_contact = Column(String(50), nullable=True, comment="乙方联系人") party_b_mobile = Column(String(20), nullable=True, comment="乙方联系电话") default_currency = Column(String(10), nullable=True, default="CNY", comment="默认币种") default_tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="默认税率(%)") default_period = Column(Integer, nullable=True, default=12, comment="默认合同期限(月)") is_active = Column(SmallInteger, nullable=True, default=1, comment="是否启用") usage_count = Column(Integer, nullable=True, default=0, comment="使用次数") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractProduct(Base): """CRM-合同产品明细表""" __tablename__ = "crm_contract_product" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") contract_id = Column(String(64), nullable=False, comment="合同ID") product_id = Column(String(64), nullable=False, comment="产品ID") product_name = Column(String(200), nullable=False, comment="产品名称") brand_mode = Column(String(20), nullable=True, comment="required/any") brand_id = Column(String(64), nullable=True, comment="指定品牌ID") brand_name = Column(String(100), nullable=True, comment="品牌名快照") product_no = Column(String(50), nullable=True, comment="产品编号") category_id = Column(String(64), nullable=True, comment="产品分类ID") category_name = Column(String(100), nullable=True, comment="产品分类名称") model = Column(String(100), nullable=True, comment="规格型号") unit = Column(String(20), nullable=True, default="件", comment="单位") quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量") quantity_mode = Column(String(20), nullable=True, default="fixed", comment="数量模式: customer_demand/fixed") price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="单价") discount = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="折扣(%)") tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="税率(%)") tax_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="税费金额") subtotal = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="小计金额") price_mode = Column(String(20), nullable=True, default="fixed", comment="价格模式: market/fixed") delivery_date = Column(Date, nullable=True, comment="交付日期") delivery_status = Column(String(20), nullable=True, default="pending", comment="交付状态") delivered_quantity = Column(DECIMAL(20, 4), nullable=True, default=Decimal("0.0000"), comment="已交付数量") description = Column(String(1000), nullable=True, comment="产品描述") package_spec = Column(String(200), nullable=True, comment="包装规格") delivery_method = Column(String(100), nullable=True, comment="送货方式") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号(公共)") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmContractProductPriceTier(Base): """CRM-框架合同产品调价区间""" __tablename__ = "crm_contract_product_price_tier" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") contract_id = Column(String(64), nullable=False, comment="合同ID") contract_product_id = Column(String(64), nullable=False, comment="合同产品明细ID") start_date = Column(Date, nullable=False, comment="区间开始日期") end_date = Column(Date, nullable=False, comment="区间结束日期") price = Column(DECIMAL(15, 2), nullable=False, comment="含税单价") letter_oss_ids = Column(String(4000), nullable=True, comment="调价函OSS ID列表(JSON数组)") letter_oss_id = Column(String(64), nullable=True, comment="调价函单附件(废弃)") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号(公共)") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmQuote(Base): """CRM-报价单主表""" __tablename__ = "crm_quote" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") quote_no = Column(String(50), nullable=False, comment="报价单编号") quote_title = Column(String(200), nullable=False, comment="报价单标题") quote_type = Column(String(20), nullable=False, default="sales", comment="报价单类型") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") opportunity_id = Column(String(64), nullable=True, comment="商机ID") contact_id = Column(String(64), nullable=True, comment="联系人ID") contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)") contact_mobile = Column(String(20), nullable=True, comment="联系人手机(冗余)") contact_email = Column(String(100), nullable=True, comment="联系人邮箱(冗余)") version = Column(String(20), nullable=True, default="V1.0", comment="版本号") parent_id = Column(String(64), nullable=True, default="0", comment="父版本ID") is_latest = Column(SmallInteger, nullable=True, default=1, comment="是否最新版本") total_amount = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="总金额") discount_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="整单折扣率") discount_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="折扣金额") final_amount = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="最终金额") validity_days = Column(Integer, nullable=True, default=30, comment="有效期(天数)") quote_date = Column(Date, nullable=True, comment="报价日期") expire_date = Column(Date, nullable=True, comment="到期日期") status = Column(String(20), nullable=False, default="draft", comment="状态") reject_reason = Column(String(500), nullable=True, comment="拒绝原因") pdf_url = Column(String(500), nullable=True, comment="PDF文件路径") pdf_generated = Column(SmallInteger, nullable=True, default=0, comment="PDF是否已生成") share_link = Column(String(500), nullable=True, comment="分享链接") share_code = Column(String(50), nullable=True, comment="分享码") share_password = Column(String(100), nullable=True, comment="分享密码") share_expire_time = Column(DateTime, nullable=True, comment="分享链接过期时间") view_count = Column(Integer, nullable=True, default=0, comment="查看次数") last_view_time = Column(DateTime, nullable=True, comment="最后查看时间") owner_user_id = Column(String(64), nullable=False, comment="负责人ID") owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)") supplier_id = Column(String(64), nullable=True, comment="报价主体ID") supplier_name = Column(String(200), nullable=True, comment="报价主体名称(冗余)") contract_id = Column(String(64), nullable=True, comment="关联合同ID") payment_terms = Column(String(500), nullable=True, comment="付款条款") delivery_terms = Column(String(500), nullable=True, comment="交付条款") freight = Column(DECIMAL(18, 2), nullable=False, default=Decimal("0.00"), comment="运费") barrel_deposit = Column(DECIMAL(18, 2), nullable=False, default=Decimal("0.00"), comment="桶押金") attachments = Column(String(1000), nullable=True, comment="附件") template_content = Column(Text, nullable=True, comment="报价单模板内容") version_no = Column(Integer, nullable=True, default=0, comment="乐观锁版本号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmQuoteProduct(Base): """CRM-报价单产品明细表""" __tablename__ = "crm_quote_product" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") quote_id = Column(String(64), nullable=False, comment="报价单ID") product_id = Column(String(64), nullable=False, comment="产品ID") product_name = Column(String(200), nullable=False, comment="产品名称") brand_mode = Column(String(20), nullable=True, comment="required/any") brand_id = Column(String(64), nullable=True, comment="指定品牌ID") brand_name = Column(String(100), nullable=True, comment="品牌名快照") product_no = Column(String(50), nullable=True, comment="产品编号") category_id = Column(String(64), nullable=True, comment="产品分类ID") category_name = Column(String(100), nullable=True, comment="产品分类名称") model = Column(String(100), nullable=True, comment="规格型号") unit = Column(String(20), nullable=True, default="件", comment="单位") quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量") price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="含税单价") discount = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="折扣(%)") subtotal = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="含税总价") tax_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="税费") tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("13.00"), comment="税率(%)") package_spec = Column(String(200), nullable=True, comment="包装规格") delivery_method = Column(String(200), nullable=True, comment="送货方式") description = Column(String(1000), nullable=True, comment="产品描述") sort = Column(Integer, nullable=True, default=0, comment="排序号") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmQuoteApproverSetting(Base): """CRM-报价单审批人设置(租户级)""" __tablename__ = "crm_quote_approver_setting" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") approver_ids = Column(String(1000), nullable=False, default="", comment="有序审批人用户ID,逗号分隔") status = Column(String(1), nullable=False, default="0", comment="0启用 1停用") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmQuoteApproval(Base): """CRM-报价单审批记录表""" __tablename__ = "crm_quote_approval" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") quote_id = Column(String(64), nullable=False, comment="报价单ID") quote_no = Column(String(50), nullable=True, comment="报价单编号(冗余)") step = Column(Integer, nullable=False, comment="审批步骤") approver_id = Column(String(64), nullable=False, comment="审批人ID") approver_name = Column(String(50), nullable=True, comment="审批人姓名(冗余)") approval_result = Column(String(20), nullable=True, default="pending", comment="审批结果") approval_opinion = Column(Text, nullable=True, comment="审批意见") approval_time = Column(DateTime, nullable=True, comment="审批时间") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmQuoteShareLog(Base): """CRM-报价单分享访问日志表""" __tablename__ = "crm_quote_share_log" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") quote_id = Column(String(64), nullable=False, comment="报价单ID") share_code = Column(String(50), nullable=False, comment="分享码") visit_time = Column(DateTime, nullable=False, default=datetime.now, comment="访问时间") ip_address = Column(String(50), nullable=True, comment="IP地址") location = Column(String(200), nullable=True, comment="地理位置") device_type = Column(String(50), nullable=True, comment="设备类型") browser = Column(String(100), nullable=True, comment="浏览器信息") stay_duration = Column(Integer, nullable=True, default=0, comment="停留时长(秒)") page_views = Column(Integer, nullable=True, default=1, comment="浏览页数") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建者") create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新者") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmClue(Base): """CRM-线索主表""" __tablename__ = "crm_clue" id = Column(String(64), primary_key=True, comment="主键ID") clue_name = Column(String(100), nullable=False, comment="线索姓名") mobile = Column(String(20), nullable=False, comment="手机号") company = Column(String(200), nullable=True, comment="公司名称") customer_type = Column(String(20), nullable=True, comment="客户类型(company-企业/person-个人)") telephone = Column(String(30), nullable=True, comment="固定电话") email = Column(String(100), nullable=True, comment="邮箱") title = Column(String(10), nullable=True, comment="称呼(先生/女士/其他)") position = Column(String(50), nullable=True, comment="职位") source = Column(String(20), nullable=False, comment="线索来源") level = Column(String(10), nullable=True, default="unrated", comment="线索等级(A/B/C/unrated)") industry = Column(String(50), nullable=True, comment="所属行业(字典 crm_customer_industry)") park_area = Column(String(100), nullable=True, comment="所在园区") province = Column(String(50), nullable=True, comment="省") city = Column(String(50), nullable=True, comment="市") district = Column(String(50), nullable=True, comment="区") address = Column(String(255), nullable=True, comment="详细地址") website = Column(String(500), nullable=True, comment="客户网站") intent_products = Column(String(500), nullable=True, comment="意向产品(多个用逗号分隔)") expect_time = Column(Date, nullable=True, comment="预计购买时间") budget = Column(String(20), nullable=True, comment="预算范围") requirement = Column(Text, nullable=True, comment="需求描述") status = Column(String(20), nullable=True, default="new", comment="线索状态(new/follow/invalid/converted)") owner_user_id = Column(String(64), nullable=True, comment="负责人ID") owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)") last_time = Column(DateTime, nullable=True, comment="最后跟进时间") next_time = Column(DateTime, nullable=True, comment="下次联系时间") follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数") is_converted = Column(SmallInteger, nullable=True, default=0, comment="是否已转化(0-否 1-是)") converted_time = Column(DateTime, nullable=True, comment="转化时间") customer_id = Column(String(64), nullable=True, comment="转化的客户ID") converted_by = Column(String(64), nullable=True, comment="转化操作人") assign_time = Column(DateTime, nullable=True, comment="分配时间") assign_by = Column(String(64), nullable=True, comment="分配人") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmClueFollow(Base): """CRM-线索跟进记录表""" __tablename__ = "crm_clue_follow" id = Column(String(64), primary_key=True, comment="主键ID") clue_id = Column(String(64), nullable=False, comment="线索ID") clue_name = Column(String(100), nullable=True, comment="线索姓名(冗余)") follow_type = Column(String(20), nullable=False, comment="跟进方式(电话/微信/邮件/拜访/其他)") follow_content = Column(Text, nullable=False, comment="跟进内容") next_time = Column(DateTime, nullable=True, comment="下次联系时间") attachments = Column(String(1000), nullable=True, comment="附件(多个用逗号分隔)") create_by_name = Column(String(50), nullable=True, comment="跟进人姓名(冗余)") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmPriceLetter(Base): """CRM-调价函档案(独立,不关联合同/报价单)""" __tablename__ = "crm_price_letter" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") letter_type = Column(String(20), nullable=False, comment="类型 receive接受/send发出") adjust_date = Column(Date, nullable=False, comment="调价日期") customer_id = Column(String(64), nullable=False, comment="客户ID") customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)") product_id = Column(String(64), nullable=False, comment="产品ID") product_name = Column(String(200), nullable=True, comment="产品名称(冗余)") price = Column(DECIMAL(15, 2), nullable=False, comment="调整后现金价格(元)") bill_price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="调整后汇票价格(元)") content = Column(Text, nullable=True, comment="发出类富文本HTML") attachment_urls = Column(String(4000), nullable=True, comment="附件URL(逗号分隔)") status = Column(String(20), nullable=False, default="normal", comment="状态 normal/invalid") invalid_reason = Column(String(200), nullable=True, comment="作废原因") invalid_time = Column(DateTime, nullable=True, comment="作废时间") invalid_by = Column(String(64), nullable=True, comment="作废人ID") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(512), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记") class CrmSupplierInfo(Base): """CRM-供方信息表""" __tablename__ = "crm_supplier_info" id = Column(String(64), primary_key=True, comment="主键ID(UUID)") supplier_name = Column(String(200), nullable=False, comment="供方名称(章)") short_name = Column(String(100), nullable=True, comment="简称") supplier_code = Column(String(50), nullable=True, comment="编码") supplier_address = Column(String(500), nullable=True, comment="单位地址") legal_person = Column(String(100), nullable=True, comment="法定代表人") agent = Column(String(100), nullable=True, comment="代理人") phone_fax = Column(String(100), nullable=True, comment="电话/传真") bank_name = Column(String(200), nullable=True, comment="开户银行") bank_account = Column(String(100), nullable=True, comment="账号") allow_toxic = Column(SmallInteger, nullable=False, default=0, comment="是否允许易制毒产品(0否1是)") allow_explosive = Column(SmallInteger, nullable=False, default=0, comment="是否允许易制爆产品(0否1是)") status = Column(String(1), nullable=True, default="0", comment="状态(0正常 1停用)") tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号") order_num = Column(Integer, nullable=True, comment="排序号") remark = Column(String(500), nullable=True, comment="备注") create_by = Column(String(64), nullable=True, comment="创建人ID") create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID") create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间") update_by = Column(String(64), nullable=True, comment="更新人ID") update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间") del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")