crm_models.py 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. """CRM 模块数据模型(产品分类、产品主表、统一附件表、客户管理、公海池、线索管理)"""
  2. from datetime import datetime
  3. from decimal import Decimal
  4. from sqlalchemy import (
  5. BigInteger,
  6. Column,
  7. DECIMAL,
  8. Date,
  9. DateTime,
  10. Integer,
  11. SmallInteger,
  12. String,
  13. Text,
  14. CHAR,
  15. )
  16. from app.core.database import Base
  17. class CrmProductCategory(Base):
  18. """CRM 产品分类表(树形结构)"""
  19. __tablename__ = "crm_product_category"
  20. id = Column(String(64), primary_key=True, comment="主键ID")
  21. parent_id = Column(String(64), nullable=False, default="0", comment="父级分类ID(0为顶级)")
  22. category_name = Column(String(128), nullable=False, comment="分类名称")
  23. category_code = Column(String(64), nullable=True, comment="分类编码")
  24. level = Column(SmallInteger, nullable=False, default=1, comment="层级")
  25. status = Column(CHAR(1), nullable=False, default="1", comment="状态 1启用 0停用")
  26. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  27. order_num = Column(Integer, nullable=True, comment="排序号")
  28. remark = Column(String(512), nullable=True, comment="备注")
  29. create_by = Column(String(64), nullable=True, comment="创建人id")
  30. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  31. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  32. update_by = Column(String(64), nullable=True, comment="更新人id")
  33. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  34. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  35. class CrmProduct(Base):
  36. """CRM 产品主表"""
  37. __tablename__ = "crm_product"
  38. id = Column(String(64), primary_key=True, comment="主键ID")
  39. product_no = Column(String(50), nullable=False, comment="产品编号")
  40. product_name = Column(String(200), nullable=False, comment="产品名称")
  41. category_id = Column(String(64), nullable=True, comment="分类ID")
  42. category_name = Column(String(100), nullable=True, comment="分类名称(冗余)")
  43. model = Column(String(100), nullable=True, comment="规格型号")
  44. unit = Column(String(20), nullable=True, default=None, comment="单位")
  45. barcode = Column(String(100), nullable=True, comment="条码")
  46. price = Column(DECIMAL(15, 2), nullable=True, default=None, comment="标准单价")
  47. cost_price = Column(DECIMAL(15, 2), nullable=True, default=None, comment="成本价")
  48. stock = Column(Integer, nullable=False, default=0, comment="库存数量")
  49. low_stock = Column(Integer, nullable=False, default=10, comment="库存预警值")
  50. tax_rate = Column(DECIMAL(5, 2), nullable=False, default=13.00, comment="税率(百分比)")
  51. is_toxic = Column(SmallInteger, nullable=False, default=0, comment="是否易制毒 0-否 1-是")
  52. is_explosive = Column(SmallInteger, nullable=False, default=0, comment="是否易制爆 0-否 1-是")
  53. status = Column(String(3), nullable=False, default="on", comment="状态 on 上架 off 下架")
  54. description = Column(Text, nullable=True, comment="产品描述")
  55. images = Column(String(1000), nullable=True, comment="产品图片(多个用逗号分隔)")
  56. sale_count = Column(Integer, nullable=False, default=0, comment="销售次数")
  57. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  58. order_num = Column(Integer, nullable=True, comment="排序号")
  59. remark = Column(String(512), nullable=True, comment="备注")
  60. create_by = Column(String(64), nullable=True, comment="创建人id")
  61. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  62. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  63. update_by = Column(String(64), nullable=True, comment="更新人id")
  64. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  65. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  66. class SysOss(Base):
  67. """统一附件表(全系统共用 sys_oss)"""
  68. __tablename__ = "sys_oss"
  69. id = Column(String(64), primary_key=True, comment="主键ID")
  70. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  71. biz_type = Column(String(50), nullable=True, comment="业务类型")
  72. biz_id = Column(String(64), nullable=True, comment="业务主键ID")
  73. file_name = Column(String(255), nullable=False, default="", comment="文件名")
  74. original_name = Column(String(255), nullable=False, default="", comment="原始文件名")
  75. file_suffix = Column(String(10), nullable=False, default="", comment="文件后缀名")
  76. url = Column(String(500), nullable=False, comment="文件URL地址")
  77. file_size = Column(BigInteger, nullable=True, comment="文件大小(字节)")
  78. file_type = Column(String(200), nullable=True, comment="MIME类型")
  79. attach_type = Column(String(32), nullable=True, default="attachment", comment="附件类型")
  80. sort_order = Column(Integer, nullable=False, default=0, comment="排序号")
  81. service = Column(String(20), nullable=False, default="minio", comment="存储服务商")
  82. ext1 = Column(Text, nullable=True, comment="扩展字段")
  83. order_num = Column(Integer, nullable=True, comment="排序号")
  84. remark = Column(String(512), nullable=True, comment="备注")
  85. create_by = Column(String(64), nullable=True, comment="创建人id")
  86. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  87. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  88. update_by = Column(String(64), nullable=True, comment="更新人id")
  89. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  90. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  91. # ── 客户管理模块 ──────────────────────────────────────────────
  92. class CrmCustomer(Base):
  93. """CRM-客户主表"""
  94. __tablename__ = "crm_customer"
  95. # 主键
  96. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  97. # 业务字段
  98. customer_no = Column(String(50), nullable=False, comment="客户编号(唯一)")
  99. customer_name = Column(String(200), nullable=False, comment="客户名称")
  100. short_name = Column(String(100), nullable=True, comment="客户简称")
  101. customer_type = Column(String(20), nullable=True, default="company", comment="客户类型(字典 crm_customer_type)")
  102. mobile = Column(String(20), nullable=True, comment="手机号")
  103. telephone = Column(String(30), nullable=True, comment="固定电话")
  104. email = Column(String(100), nullable=True, comment="邮箱")
  105. website = Column(String(500), nullable=True, comment="客户网站")
  106. level = Column(
  107. String(20), nullable=True, default="normal", comment="客户级别(字典 crm_customer_level: key/normal/potential)"
  108. )
  109. source = Column(String(20), nullable=True, comment="客户来源(字典 crm_clue_source)")
  110. industry = Column(String(50), nullable=True, comment="所属行业(字典 crm_customer_industry)")
  111. park_area = Column(String(100), nullable=True, comment="所在园区(字典 crm_customer_park)")
  112. payment_terms = Column(String(500), nullable=True, comment="收付款条件")
  113. scale = Column(String(20), nullable=True, comment="企业规模")
  114. province = Column(String(50), nullable=True, comment="省")
  115. city = Column(String(50), nullable=True, comment="市")
  116. district = Column(String(50), nullable=True, comment="区")
  117. address = Column(String(255), nullable=True, comment="详细地址")
  118. # 状态与归属
  119. status = Column(
  120. String(20), nullable=True, default="normal", comment="客户状态(字典 crm_customer_status: normal/pool/invalid)"
  121. )
  122. deal_status = Column(
  123. String(20), nullable=True, default="not_deal", comment="成交状态(字典 crm_deal_status: not_deal/dealed/lost)"
  124. )
  125. owner_user_id = Column(String(64), nullable=True, comment="负责人ID")
  126. owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)")
  127. # 跟进统计
  128. last_time = Column(DateTime, nullable=True, comment="最后跟进时间")
  129. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  130. follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数")
  131. # 成交统计
  132. deal_time = Column(DateTime, nullable=True, comment="成交时间")
  133. deal_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="累计成交金额")
  134. # 关联统计
  135. contact_count = Column(Integer, nullable=True, default=0, comment="联系人数量")
  136. opportunity_count = Column(Integer, nullable=True, default=0, comment="商机数量")
  137. contract_count = Column(Integer, nullable=True, default=0, comment="合同数量")
  138. # 公海池相关
  139. into_pool_time = Column(DateTime, nullable=True, comment="进入公海时间")
  140. into_pool_by = Column(String(64), nullable=True, comment="进入公海操作人ID")
  141. into_pool_reason = Column(String(500), nullable=True, comment="进入公海原因")
  142. claim_time = Column(DateTime, nullable=True, comment="领取时间")
  143. assign_time = Column(DateTime, nullable=True, comment="分配时间")
  144. assign_by = Column(String(64), nullable=True, comment="分配人ID")
  145. protect_time = Column(DateTime, nullable=True, comment="保护到期时间")
  146. # 证照附件
  147. business_license_img = Column(String(1000), nullable=True, comment="营业执照图片(附件URL,逗号分隔)")
  148. business_permit_images = Column(String(1000), nullable=True, comment="经营许可证图片(附件URL,逗号分隔)")
  149. other_cert_images = Column(String(1000), nullable=True, comment="其他证件图片(附件URL,逗号分隔)")
  150. # 线索关联
  151. clue_id = Column(String(64), nullable=True, comment="关联线索ID(从线索转化)")
  152. # 公共字段
  153. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  154. order_num = Column(Integer, nullable=True, comment="排序号")
  155. remark = Column(String(512), nullable=True, comment="备注")
  156. create_by = Column(String(64), nullable=True, comment="创建人ID")
  157. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  158. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  159. update_by = Column(String(64), nullable=True, comment="更新人ID")
  160. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  161. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  162. class CrmContact(Base):
  163. """CRM-联系人表"""
  164. __tablename__ = "crm_contact"
  165. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  166. customer_id = Column(String(64), nullable=False, comment="客户ID")
  167. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  168. contact_name = Column(String(100), nullable=False, comment="联系人姓名")
  169. gender = Column(String(10), nullable=True, comment="性别(male/female/unknown)")
  170. mobile = Column(String(20), nullable=True, comment="手机号")
  171. telephone = Column(String(30), nullable=True, comment="固定电话")
  172. email = Column(String(100), nullable=True, comment="邮箱")
  173. wechat = Column(String(100), nullable=True, comment="微信号")
  174. qq = Column(String(20), nullable=True, comment="QQ号")
  175. department = Column(String(100), nullable=True, comment="部门")
  176. position = Column(String(50), nullable=True, comment="职位")
  177. role = Column(String(20), nullable=True, comment="角色(decision/manager/user/other)")
  178. birthday = Column(Date, nullable=True, comment="生日")
  179. address = Column(String(255), nullable=True, comment="住址")
  180. is_key = Column(SmallInteger, nullable=True, default=0, comment="是否关键决策人(0-否 1-是)")
  181. is_primary = Column(SmallInteger, nullable=True, default=0, comment="是否主要联系人(0-否 1-是)")
  182. status = Column(String(20), nullable=True, default="active", comment="状态(active-在职/leave-离职)")
  183. # 公共字段
  184. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  185. order_num = Column(Integer, nullable=True, comment="排序号")
  186. remark = Column(String(512), nullable=True, comment="备注")
  187. create_by = Column(String(64), nullable=True, comment="创建人ID")
  188. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  189. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  190. update_by = Column(String(64), nullable=True, comment="更新人ID")
  191. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  192. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  193. class CrmInvoiceInfo(Base):
  194. """CRM-客户开票信息表"""
  195. __tablename__ = "crm_invoice_info"
  196. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  197. customer_id = Column(String(64), nullable=False, comment="客户ID")
  198. company_name = Column(String(200), nullable=False, comment="单位名称")
  199. tax_no = Column(String(50), nullable=True, comment="税号")
  200. company_address = Column(String(500), nullable=True, comment="单位地址")
  201. legal_representative = Column(String(100), nullable=True, comment="法定代表人")
  202. agent = Column(String(100), nullable=True, comment="代理人")
  203. phone_fax = Column(String(100), nullable=True, comment="电话/传真")
  204. bank_name = Column(String(200), nullable=True, comment="开户银行")
  205. bank_account = Column(String(100), nullable=True, comment="银行账号")
  206. is_default = Column(String(1), nullable=False, default="0", comment="是否默认(0否 1是)")
  207. # 公共字段
  208. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  209. order_num = Column(Integer, nullable=True, comment="排序号")
  210. remark = Column(String(512), nullable=True, comment="备注")
  211. create_by = Column(String(64), nullable=True, comment="创建人ID")
  212. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  213. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  214. update_by = Column(String(64), nullable=True, comment="更新人ID")
  215. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  216. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  217. class CrmCustomerFollow(Base):
  218. """CRM-客户跟进记录表"""
  219. __tablename__ = "crm_customer_follow"
  220. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  221. customer_id = Column(String(64), nullable=False, comment="客户ID")
  222. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  223. contact_id = Column(String(64), nullable=True, comment="联系人ID")
  224. contact_name = Column(String(100), nullable=True, comment="联系人姓名(冗余)")
  225. follow_type = Column(
  226. String(20), nullable=False, comment="跟进方式(字典 crm_follow_type: phone/wechat/visit/email/other)"
  227. )
  228. follow_content = Column(Text, nullable=False, comment="跟进内容")
  229. follow_time = Column(DateTime, nullable=True, comment="跟进时间")
  230. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  231. attachment = Column(String(1000), nullable=True, comment="附件URL(多个用逗号分隔)")
  232. owner_user_id = Column(String(64), nullable=True, comment="跟进人ID")
  233. owner_user_name = Column(String(50), nullable=True, comment="跟进人姓名(冗余)")
  234. # 公共字段
  235. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  236. order_num = Column(Integer, nullable=True, comment="排序号")
  237. remark = Column(String(512), nullable=True, comment="备注")
  238. create_by = Column(String(64), nullable=True, comment="创建人ID")
  239. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  240. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  241. update_by = Column(String(64), nullable=True, comment="更新人ID")
  242. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  243. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  244. class CrmCustomerPool(Base):
  245. """CRM-客户公海池记录表"""
  246. __tablename__ = "crm_customer_pool"
  247. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  248. customer_id = Column(String(64), nullable=False, comment="客户ID")
  249. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  250. operation_type = Column(String(20), nullable=False, comment="操作类型(into-进入公海/claim-领取/assign-分配/recycle-回收)")
  251. from_user_id = Column(String(64), nullable=True, comment="原负责人ID")
  252. from_user_name = Column(String(50), nullable=True, comment="原负责人姓名(冗余)")
  253. to_user_id = Column(String(64), nullable=True, comment="新负责人ID")
  254. to_user_name = Column(String(50), nullable=True, comment="新负责人姓名(冗余)")
  255. reason = Column(String(500), nullable=True, comment="操作原因")
  256. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  257. order_num = Column(Integer, nullable=True, comment="排序号")
  258. remark = Column(String(500), nullable=True, comment="备注")
  259. create_by = Column(String(64), nullable=True, comment="创建者(操作人)")
  260. create_by_name = Column(String(50), nullable=True, comment="操作人姓名(冗余)")
  261. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  262. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间(操作时间)")
  263. update_by = Column(String(64), nullable=True, comment="更新者")
  264. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  265. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  266. class CrmCustomerPoolRule(Base):
  267. """CRM-客户公海池规则表"""
  268. __tablename__ = "crm_customer_pool_rule"
  269. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  270. pool_name = Column(String(100), nullable=False, comment="规则名称")
  271. rule_type = Column(String(20), nullable=False, comment="规则类型(no_follow-未跟进/no_deal-未成交)")
  272. timeout_days = Column(Integer, nullable=False, comment="超时天数(多少天未跟进/未成交)")
  273. protect_days = Column(Integer, nullable=False, default=0, comment="保护期天数(领取后保护多少天)")
  274. status = Column(String(20), nullable=True, default="enable", comment="状态(enable-启用/disable-禁用)")
  275. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  276. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  277. order_num = Column(Integer, nullable=True, comment="排序号")
  278. remark = Column(String(500), nullable=True, comment="备注")
  279. create_by = Column(String(64), nullable=True, comment="创建者")
  280. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  281. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  282. update_by = Column(String(64), nullable=True, comment="更新者")
  283. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  284. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  285. class CrmOpportunity(Base):
  286. """CRM-商机主表"""
  287. __tablename__ = "crm_opportunity"
  288. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  289. opportunity_no = Column(String(50), nullable=False, comment="商机编号")
  290. opportunity_name = Column(String(200), nullable=False, comment="商机名称")
  291. customer_id = Column(String(64), nullable=False, comment="客户ID")
  292. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  293. contact_id = Column(String(64), nullable=True, comment="联系人ID")
  294. contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)")
  295. stage = Column(String(20), nullable=False, default="initial", comment="商机阶段")
  296. stage_percent = Column(Integer, nullable=True, default=10, comment="阶段进度百分比")
  297. status = Column(String(20), nullable=False, default="following", comment="商机状态")
  298. win_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("50.00"), comment="赢单率(百分比)")
  299. amount = Column(DECIMAL(15, 2), nullable=False, default=0, comment="商机金额")
  300. expect_deal_date = Column(Date, nullable=True, comment="预计成交日期")
  301. actual_deal_date = Column(Date, nullable=True, comment="实际成交日期")
  302. lost_reason = Column(String(500), nullable=True, comment="输单原因")
  303. owner_user_id = Column(String(64), nullable=True, comment="负责人ID")
  304. owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)")
  305. product_count = Column(Integer, nullable=True, default=0, comment="产品数量(冗余)")
  306. last_time = Column(DateTime, nullable=True, comment="最后跟进时间")
  307. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  308. follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数(冗余)")
  309. contract_id = Column(String(64), nullable=True, comment="关联合同ID")
  310. source = Column(String(20), nullable=True, comment="商机来源")
  311. type = Column(String(20), nullable=True, comment="商机类型")
  312. description = Column(Text, nullable=True, comment="商机描述")
  313. competitors = Column(String(500), nullable=True, comment="竞争对手")
  314. key_factors = Column(String(500), nullable=True, comment="关键决策因素")
  315. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  316. order_num = Column(Integer, nullable=True, comment="排序号")
  317. remark = Column(String(512), nullable=True, comment="备注")
  318. create_by = Column(String(64), nullable=True, comment="创建人ID")
  319. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  320. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  321. update_by = Column(String(64), nullable=True, comment="更新人ID")
  322. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  323. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  324. class CrmOpportunityFollow(Base):
  325. """CRM-商机跟进记录表"""
  326. __tablename__ = "crm_opportunity_follow"
  327. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  328. opportunity_id = Column(String(64), nullable=False, comment="商机ID")
  329. follow_type = Column(String(20), nullable=False, comment="跟进方式")
  330. follow_content = Column(Text, nullable=False, comment="跟进内容")
  331. follow_time = Column(DateTime, nullable=True, comment="跟进时间")
  332. stage = Column(String(20), nullable=True, comment="当前商机阶段")
  333. stage_percent = Column(Integer, nullable=True, comment="阶段进度百分比")
  334. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  335. next_content = Column(String(500), nullable=True, comment="下次联系计划")
  336. attachments = Column(String(1000), nullable=True, comment="附件(逗号分隔)")
  337. contact_id = Column(String(64), nullable=True, comment="联系人ID")
  338. contact_name = Column(String(50), nullable=True, comment="联系人姓名")
  339. location = Column(String(200), nullable=True, comment="跟进地点")
  340. duration = Column(Integer, nullable=True, comment="跟进时长(分钟)")
  341. follow_by = Column(String(64), nullable=True, comment="跟进人ID")
  342. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  343. order_num = Column(Integer, nullable=True, comment="排序号")
  344. remark = Column(String(500), nullable=True, comment="备注")
  345. create_by = Column(String(64), nullable=True, comment="创建人ID")
  346. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  347. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  348. update_by = Column(String(64), nullable=True, comment="更新人ID")
  349. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  350. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  351. class CrmOpportunityProduct(Base):
  352. """CRM-商机产品关联表"""
  353. __tablename__ = "crm_opportunity_product"
  354. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  355. opportunity_id = Column(String(64), nullable=False, comment="商机ID")
  356. product_id = Column(String(64), nullable=False, comment="产品ID")
  357. product_name = Column(String(200), nullable=True, comment="产品名称(冗余)")
  358. product_no = Column(String(50), nullable=True, comment="产品编号(冗余)")
  359. category_id = Column(String(64), nullable=True, comment="产品分类ID")
  360. category_name = Column(String(100), nullable=True, comment="产品分类名称(冗余)")
  361. model = Column(String(100), nullable=True, comment="规格型号")
  362. unit = Column(String(20), nullable=True, default="件", comment="单位")
  363. quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量")
  364. price = Column(DECIMAL(15, 2), nullable=False, default=0, comment="单价")
  365. discount = Column(DECIMAL(5, 2), nullable=True, default=0, comment="折扣(百分比)")
  366. subtotal = Column(DECIMAL(15, 2), nullable=False, default=0, comment="小计金额")
  367. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  368. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  369. order_num = Column(Integer, nullable=True, comment="排序号")
  370. remark = Column(String(500), nullable=True, comment="备注")
  371. create_by = Column(String(64), nullable=True, comment="创建人ID")
  372. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  373. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  374. update_by = Column(String(64), nullable=True, comment="更新人ID")
  375. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  376. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  377. class CrmOpportunityStageLog(Base):
  378. """CRM-商机阶段变更日志表"""
  379. __tablename__ = "crm_opportunity_stage_log"
  380. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  381. opportunity_id = Column(String(64), nullable=False, comment="商机ID")
  382. from_stage = Column(String(20), nullable=True, comment="原阶段")
  383. from_stage_name = Column(String(50), nullable=True, comment="原阶段名称")
  384. from_percent = Column(Integer, nullable=True, comment="原进度百分比")
  385. to_stage = Column(String(20), nullable=False, comment="新阶段")
  386. to_stage_name = Column(String(50), nullable=True, comment="新阶段名称")
  387. to_percent = Column(Integer, nullable=True, comment="新进度百分比")
  388. change_type = Column(String(20), nullable=True, default="forward", comment="变更类型")
  389. change_reason = Column(String(500), nullable=True, comment="变更原因")
  390. change_amount = Column(DECIMAL(15, 2), nullable=True, comment="变更时商机金额")
  391. lost_detail = Column(String(2000), nullable=True, comment="输单详细说明")
  392. competitor_info = Column(String(1000), nullable=True, comment="竞争对手信息")
  393. improvement = Column(String(1000), nullable=True, comment="改进建议")
  394. won_remark = Column(String(2000), nullable=True, comment="赢单说明")
  395. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  396. order_num = Column(Integer, nullable=True, comment="排序号")
  397. remark = Column(String(500), nullable=True, comment="备注")
  398. create_by = Column(String(64), nullable=True, comment="创建人ID")
  399. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  400. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  401. update_by = Column(String(64), nullable=True, comment="更新人ID")
  402. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  403. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  404. class CrmContract(Base):
  405. """CRM-合同主表"""
  406. __tablename__ = "crm_contract"
  407. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  408. contract_no = Column(String(50), nullable=False, comment="合同编号")
  409. contract_name = Column(String(200), nullable=False, comment="合同名称")
  410. customer_id = Column(String(64), nullable=False, comment="客户ID")
  411. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  412. opportunity_id = Column(String(64), nullable=True, comment="商机ID")
  413. quote_id = Column(String(64), nullable=True, comment="报价单ID")
  414. parent_contract_id = Column(String(64), nullable=True, comment="原合同ID(续签)")
  415. renewal_count = Column(Integer, nullable=True, default=0, comment="续签次数")
  416. template_id = Column(String(64), nullable=True, comment="合同模板ID")
  417. contract_template = Column(String(50), nullable=True, default="shanxia", comment="合同模版")
  418. contact_id = Column(String(64), nullable=True, comment="联系人ID")
  419. contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)")
  420. contact_mobile = Column(String(20), nullable=True, comment="联系人手机(冗余)")
  421. contract_type = Column(String(20), nullable=False, default="sale", comment="合同类型")
  422. contract_nature = Column(String(20), nullable=True, default="new", comment="合同性质")
  423. amount = Column(DECIMAL(15, 2), nullable=False, default=0, comment="合同金额")
  424. currency = Column(String(10), nullable=True, default="CNY", comment="币种")
  425. tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="税率(%)")
  426. amount_with_tax = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="含税金额")
  427. status = Column(String(20), nullable=False, default="draft", comment="合同状态")
  428. approval_status = Column(String(20), nullable=True, comment="审批状态")
  429. sign_date = Column(Date, nullable=True, comment="签订日期")
  430. actual_sign_date = Column(Date, nullable=True, comment="实际签订日期")
  431. start_date = Column(Date, nullable=True, comment="开始日期")
  432. end_date = Column(Date, nullable=True, comment="结束日期")
  433. contract_period = Column(Integer, nullable=True, comment="合同期限(月)")
  434. performance_status = Column(String(20), nullable=True, default="normal", comment="履约状态")
  435. performance_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="履约完成度(%)")
  436. customer_satisfaction = Column(Integer, nullable=True, comment="客户满意度")
  437. approval_flow_id = Column(String(64), nullable=True, comment="审批流程ID")
  438. contract_file = Column(String(500), nullable=True, comment="合同文件路径")
  439. attachment_files = Column(String(2000), nullable=True, comment="附件文件")
  440. owner_user_id = Column(String(64), nullable=True, comment="负责人ID")
  441. owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)")
  442. received_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="已回款金额")
  443. unreceived_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="未回款金额")
  444. invoice_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="已开票金额")
  445. uninvoice_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="未开票金额")
  446. payment_terms = Column(Text, nullable=True, comment="付款条款")
  447. delivery_terms = Column(Text, nullable=True, comment="交付条款")
  448. contract_terms = Column(Text, nullable=True, comment="合同条款")
  449. settlement_method = Column(String(50), nullable=True, comment="结算方式")
  450. template_content = Column(Text, nullable=True, comment="合同模板内容")
  451. settlement_clause_drafts = Column(Text, nullable=True, comment="结算方式草稿JSON")
  452. invalid_reason = Column(String(500), nullable=True, comment="作废原因")
  453. invalid_time = Column(DateTime, nullable=True, comment="作废时间")
  454. version_no = Column(Integer, nullable=True, default=0, comment="乐观锁版本号")
  455. party_a = Column(String(200), nullable=True, comment="甲方")
  456. party_a_address = Column(String(255), nullable=True, comment="甲方地址")
  457. party_a_contact = Column(String(50), nullable=True, comment="甲方联系人")
  458. party_a_mobile = Column(String(20), nullable=True, comment="甲方联系电话")
  459. party_a_legal_person = Column(String(50), nullable=True, comment="甲方法定代表人")
  460. party_a_agent = Column(String(50), nullable=True, comment="甲方代理人")
  461. party_a_phone_fax = Column(String(50), nullable=True, comment="甲方电话/传真")
  462. party_a_bank = Column(String(100), nullable=True, comment="甲方开户银行")
  463. party_a_account = Column(String(50), nullable=True, comment="甲方银行账号")
  464. party_b = Column(String(200), nullable=True, comment="乙方")
  465. party_b_address = Column(String(255), nullable=True, comment="乙方地址")
  466. party_b_contact = Column(String(50), nullable=True, comment="乙方联系人")
  467. party_b_mobile = Column(String(20), nullable=True, comment="乙方联系电话")
  468. party_b_legal_person = Column(String(100), nullable=True, comment="乙方法定代表人")
  469. party_b_agent = Column(String(100), nullable=True, comment="乙方代理人")
  470. party_b_phone_fax = Column(String(100), nullable=True, comment="乙方电话/传真")
  471. party_b_bank = Column(String(200), nullable=True, comment="乙方开户银行")
  472. party_b_account = Column(String(100), nullable=True, comment="乙方银行账号")
  473. supplier_id = Column(String(64), nullable=True, comment="供方主体ID")
  474. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  475. order_num = Column(Integer, nullable=True, comment="排序号")
  476. remark = Column(String(512), nullable=True, comment="备注")
  477. create_by = Column(String(64), nullable=True, comment="创建人ID")
  478. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  479. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  480. update_by = Column(String(64), nullable=True, comment="更新人ID")
  481. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  482. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  483. class CrmContractApproval(Base):
  484. """CRM-合同审批记录表"""
  485. __tablename__ = "crm_contract_approval"
  486. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  487. contract_id = Column(String(64), nullable=False, comment="合同ID")
  488. flow_id = Column(String(64), nullable=True, comment="审批流程ID")
  489. step = Column(Integer, nullable=False, default=1, comment="审批步骤")
  490. step_name = Column(String(100), nullable=True, comment="步骤名称")
  491. approver_id = Column(String(64), nullable=False, comment="审批人ID")
  492. approver_name = Column(String(50), nullable=True, comment="审批人姓名(冗余)")
  493. approver_dept = Column(String(100), nullable=True, comment="审批人部门")
  494. approval_result = Column(String(20), nullable=True, default="pending", comment="审批结果")
  495. approval_opinion = Column(Text, nullable=True, comment="审批意见")
  496. approval_time = Column(DateTime, nullable=True, comment="审批时间")
  497. approval_duration = Column(Integer, nullable=True, comment="审批耗时(小时)")
  498. attachments = Column(String(1000), nullable=True, comment="附件")
  499. is_current = Column(SmallInteger, nullable=True, default=1, comment="是否当前步骤")
  500. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  501. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  502. order_num = Column(Integer, nullable=True, comment="排序号")
  503. remark = Column(String(500), nullable=True, comment="备注")
  504. create_by = Column(String(64), nullable=True, comment="创建者")
  505. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  506. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  507. update_by = Column(String(64), nullable=True, comment="更新者")
  508. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  509. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  510. class CrmContractChange(Base):
  511. """CRM-合同变更记录表"""
  512. __tablename__ = "crm_contract_change"
  513. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  514. contract_id = Column(String(64), nullable=False, comment="合同ID")
  515. contract_no = Column(String(50), nullable=True, comment="合同编号(冗余)")
  516. change_type = Column(String(50), nullable=False, comment="变更类型")
  517. change_reason = Column(String(500), nullable=False, comment="变更原因")
  518. change_content = Column(Text, nullable=True, comment="变更内容描述")
  519. old_value = Column(Text, nullable=True, comment="变更前值(JSON)")
  520. new_value = Column(Text, nullable=True, comment="变更后值(JSON)")
  521. change_amount = Column(DECIMAL(15, 2), nullable=True, comment="变更金额")
  522. approval_status = Column(String(20), nullable=True, default="pending", comment="审批状态")
  523. approver_id = Column(String(64), nullable=True, comment="审批人ID")
  524. approver_name = Column(String(50), nullable=True, comment="审批人姓名")
  525. approval_time = Column(DateTime, nullable=True, comment="审批时间")
  526. approval_opinion = Column(String(500), nullable=True, comment="审批意见")
  527. attachment_files = Column(String(1000), nullable=True, comment="附件文件")
  528. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  529. order_num = Column(Integer, nullable=True, comment="排序号")
  530. remark = Column(String(500), nullable=True, comment="备注")
  531. create_by = Column(String(64), nullable=True, comment="创建者")
  532. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  533. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  534. update_by = Column(String(64), nullable=True, comment="更新者")
  535. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  536. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  537. class CrmContractTemplate(Base):
  538. """CRM-合同模板表"""
  539. __tablename__ = "crm_contract_template"
  540. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  541. template_no = Column(String(50), nullable=False, comment="模板编号")
  542. template_name = Column(String(200), nullable=False, comment="模板名称")
  543. contract_type = Column(String(20), nullable=True, comment="适用合同类型")
  544. template_content = Column(Text, nullable=True, comment="模板内容")
  545. payment_terms = Column(Text, nullable=True, comment="付款条款模板")
  546. delivery_terms = Column(Text, nullable=True, comment="交付条款模板")
  547. contract_terms = Column(Text, nullable=True, comment="合同条款模板")
  548. party_b = Column(String(200), nullable=True, comment="乙方名称")
  549. party_b_address = Column(String(255), nullable=True, comment="乙方地址")
  550. party_b_contact = Column(String(50), nullable=True, comment="乙方联系人")
  551. party_b_mobile = Column(String(20), nullable=True, comment="乙方联系电话")
  552. default_currency = Column(String(10), nullable=True, default="CNY", comment="默认币种")
  553. default_tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="默认税率(%)")
  554. default_period = Column(Integer, nullable=True, default=12, comment="默认合同期限(月)")
  555. is_active = Column(SmallInteger, nullable=True, default=1, comment="是否启用")
  556. usage_count = Column(Integer, nullable=True, default=0, comment="使用次数")
  557. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  558. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  559. order_num = Column(Integer, nullable=True, comment="排序号")
  560. remark = Column(String(500), nullable=True, comment="备注")
  561. create_by = Column(String(64), nullable=True, comment="创建者")
  562. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  563. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  564. update_by = Column(String(64), nullable=True, comment="更新者")
  565. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  566. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  567. class CrmContractProduct(Base):
  568. """CRM-合同产品明细表"""
  569. __tablename__ = "crm_contract_product"
  570. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  571. contract_id = Column(String(64), nullable=False, comment="合同ID")
  572. product_id = Column(String(64), nullable=False, comment="产品ID")
  573. product_name = Column(String(200), nullable=False, comment="产品名称")
  574. product_no = Column(String(50), nullable=True, comment="产品编号")
  575. category_id = Column(String(64), nullable=True, comment="产品分类ID")
  576. category_name = Column(String(100), nullable=True, comment="产品分类名称")
  577. model = Column(String(100), nullable=True, comment="规格型号")
  578. unit = Column(String(20), nullable=True, default="件", comment="单位")
  579. quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量")
  580. price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="单价")
  581. discount = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="折扣(%)")
  582. tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("6.00"), comment="税率(%)")
  583. tax_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="税费金额")
  584. subtotal = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="小计金额")
  585. delivery_date = Column(Date, nullable=True, comment="交付日期")
  586. delivery_status = Column(String(20), nullable=True, default="pending", comment="交付状态")
  587. delivered_quantity = Column(DECIMAL(20, 4), nullable=True, default=Decimal("0.0000"), comment="已交付数量")
  588. description = Column(String(1000), nullable=True, comment="产品描述")
  589. package_spec = Column(String(200), nullable=True, comment="包装规格")
  590. delivery_method = Column(String(100), nullable=True, comment="送货方式")
  591. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  592. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  593. order_num = Column(Integer, nullable=True, comment="排序号(公共)")
  594. remark = Column(String(500), nullable=True, comment="备注")
  595. create_by = Column(String(64), nullable=True, comment="创建者")
  596. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  597. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  598. update_by = Column(String(64), nullable=True, comment="更新者")
  599. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  600. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  601. class CrmContractProductPriceTier(Base):
  602. """CRM-框架合同产品调价区间"""
  603. __tablename__ = "crm_contract_product_price_tier"
  604. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  605. contract_id = Column(String(64), nullable=False, comment="合同ID")
  606. contract_product_id = Column(String(64), nullable=False, comment="合同产品明细ID")
  607. start_date = Column(Date, nullable=False, comment="区间开始日期")
  608. end_date = Column(Date, nullable=False, comment="区间结束日期")
  609. price = Column(DECIMAL(15, 2), nullable=False, comment="含税单价")
  610. letter_oss_ids = Column(String(4000), nullable=True, comment="调价函OSS ID列表(JSON数组)")
  611. letter_oss_id = Column(String(64), nullable=True, comment="调价函单附件(废弃)")
  612. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  613. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  614. order_num = Column(Integer, nullable=True, comment="排序号(公共)")
  615. remark = Column(String(500), nullable=True, comment="备注")
  616. create_by = Column(String(64), nullable=True, comment="创建者")
  617. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  618. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  619. update_by = Column(String(64), nullable=True, comment="更新者")
  620. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  621. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  622. class CrmQuote(Base):
  623. """CRM-报价单主表"""
  624. __tablename__ = "crm_quote"
  625. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  626. quote_no = Column(String(50), nullable=False, comment="报价单编号")
  627. quote_title = Column(String(200), nullable=False, comment="报价单标题")
  628. quote_type = Column(String(20), nullable=False, default="sales", comment="报价单类型")
  629. customer_id = Column(String(64), nullable=False, comment="客户ID")
  630. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  631. opportunity_id = Column(String(64), nullable=True, comment="商机ID")
  632. contact_id = Column(String(64), nullable=True, comment="联系人ID")
  633. contact_name = Column(String(50), nullable=True, comment="联系人姓名(冗余)")
  634. contact_mobile = Column(String(20), nullable=True, comment="联系人手机(冗余)")
  635. contact_email = Column(String(100), nullable=True, comment="联系人邮箱(冗余)")
  636. version = Column(String(20), nullable=True, default="V1.0", comment="版本号")
  637. parent_id = Column(String(64), nullable=True, default="0", comment="父版本ID")
  638. is_latest = Column(SmallInteger, nullable=True, default=1, comment="是否最新版本")
  639. total_amount = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="总金额")
  640. discount_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="整单折扣率")
  641. discount_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="折扣金额")
  642. final_amount = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="最终金额")
  643. validity_days = Column(Integer, nullable=True, default=30, comment="有效期(天数)")
  644. quote_date = Column(Date, nullable=True, comment="报价日期")
  645. expire_date = Column(Date, nullable=True, comment="到期日期")
  646. status = Column(String(20), nullable=False, default="draft", comment="状态")
  647. reject_reason = Column(String(500), nullable=True, comment="拒绝原因")
  648. pdf_url = Column(String(500), nullable=True, comment="PDF文件路径")
  649. pdf_generated = Column(SmallInteger, nullable=True, default=0, comment="PDF是否已生成")
  650. share_link = Column(String(500), nullable=True, comment="分享链接")
  651. share_code = Column(String(50), nullable=True, comment="分享码")
  652. share_password = Column(String(100), nullable=True, comment="分享密码")
  653. share_expire_time = Column(DateTime, nullable=True, comment="分享链接过期时间")
  654. view_count = Column(Integer, nullable=True, default=0, comment="查看次数")
  655. last_view_time = Column(DateTime, nullable=True, comment="最后查看时间")
  656. owner_user_id = Column(String(64), nullable=False, comment="负责人ID")
  657. owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)")
  658. supplier_id = Column(String(64), nullable=True, comment="报价主体ID")
  659. supplier_name = Column(String(200), nullable=True, comment="报价主体名称(冗余)")
  660. contract_id = Column(String(64), nullable=True, comment="关联合同ID")
  661. payment_terms = Column(String(500), nullable=True, comment="付款条款")
  662. delivery_terms = Column(String(500), nullable=True, comment="交付条款")
  663. freight = Column(DECIMAL(18, 2), nullable=False, default=Decimal("0.00"), comment="运费")
  664. attachments = Column(String(1000), nullable=True, comment="附件")
  665. template_content = Column(Text, nullable=True, comment="报价单模板内容")
  666. version_no = Column(Integer, nullable=True, default=0, comment="乐观锁版本号")
  667. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  668. order_num = Column(Integer, nullable=True, comment="排序号")
  669. remark = Column(String(500), nullable=True, comment="备注")
  670. create_by = Column(String(64), nullable=True, comment="创建者")
  671. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  672. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  673. update_by = Column(String(64), nullable=True, comment="更新者")
  674. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  675. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  676. class CrmQuoteProduct(Base):
  677. """CRM-报价单产品明细表"""
  678. __tablename__ = "crm_quote_product"
  679. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  680. quote_id = Column(String(64), nullable=False, comment="报价单ID")
  681. product_id = Column(String(64), nullable=False, comment="产品ID")
  682. product_name = Column(String(200), nullable=False, comment="产品名称")
  683. product_no = Column(String(50), nullable=True, comment="产品编号")
  684. category_id = Column(String(64), nullable=True, comment="产品分类ID")
  685. category_name = Column(String(100), nullable=True, comment="产品分类名称")
  686. model = Column(String(100), nullable=True, comment="规格型号")
  687. unit = Column(String(20), nullable=True, default="件", comment="单位")
  688. quantity = Column(DECIMAL(20, 4), nullable=False, comment="数量")
  689. price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="含税单价")
  690. discount = Column(DECIMAL(5, 2), nullable=True, default=Decimal("0.00"), comment="折扣(%)")
  691. subtotal = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="含税总价")
  692. tax_amount = Column(DECIMAL(15, 2), nullable=True, default=Decimal("0.00"), comment="税费")
  693. tax_rate = Column(DECIMAL(5, 2), nullable=True, default=Decimal("13.00"), comment="税率(%)")
  694. package_spec = Column(String(200), nullable=True, comment="包装规格")
  695. delivery_method = Column(String(200), nullable=True, comment="送货方式")
  696. description = Column(String(1000), nullable=True, comment="产品描述")
  697. sort = Column(Integer, nullable=True, default=0, comment="排序号")
  698. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  699. order_num = Column(Integer, nullable=True, comment="排序号")
  700. remark = Column(String(500), nullable=True, comment="备注")
  701. create_by = Column(String(64), nullable=True, comment="创建者")
  702. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  703. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  704. update_by = Column(String(64), nullable=True, comment="更新者")
  705. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  706. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  707. class CrmQuoteApproval(Base):
  708. """CRM-报价单审批记录表"""
  709. __tablename__ = "crm_quote_approval"
  710. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  711. quote_id = Column(String(64), nullable=False, comment="报价单ID")
  712. quote_no = Column(String(50), nullable=True, comment="报价单编号(冗余)")
  713. step = Column(Integer, nullable=False, comment="审批步骤")
  714. approver_id = Column(String(64), nullable=False, comment="审批人ID")
  715. approver_name = Column(String(50), nullable=True, comment="审批人姓名(冗余)")
  716. approval_result = Column(String(20), nullable=True, default="pending", comment="审批结果")
  717. approval_opinion = Column(Text, nullable=True, comment="审批意见")
  718. approval_time = Column(DateTime, nullable=True, comment="审批时间")
  719. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  720. order_num = Column(Integer, nullable=True, comment="排序号")
  721. remark = Column(String(500), nullable=True, comment="备注")
  722. create_by = Column(String(64), nullable=True, comment="创建者")
  723. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  724. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  725. update_by = Column(String(64), nullable=True, comment="更新者")
  726. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  727. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  728. class CrmQuoteShareLog(Base):
  729. """CRM-报价单分享访问日志表"""
  730. __tablename__ = "crm_quote_share_log"
  731. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  732. quote_id = Column(String(64), nullable=False, comment="报价单ID")
  733. share_code = Column(String(50), nullable=False, comment="分享码")
  734. visit_time = Column(DateTime, nullable=False, default=datetime.now, comment="访问时间")
  735. ip_address = Column(String(50), nullable=True, comment="IP地址")
  736. location = Column(String(200), nullable=True, comment="地理位置")
  737. device_type = Column(String(50), nullable=True, comment="设备类型")
  738. browser = Column(String(100), nullable=True, comment="浏览器信息")
  739. stay_duration = Column(Integer, nullable=True, default=0, comment="停留时长(秒)")
  740. page_views = Column(Integer, nullable=True, default=1, comment="浏览页数")
  741. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  742. order_num = Column(Integer, nullable=True, comment="排序号")
  743. remark = Column(String(500), nullable=True, comment="备注")
  744. create_by = Column(String(64), nullable=True, comment="创建者")
  745. create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
  746. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  747. update_by = Column(String(64), nullable=True, comment="更新者")
  748. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  749. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  750. class CrmClue(Base):
  751. """CRM-线索主表"""
  752. __tablename__ = "crm_clue"
  753. id = Column(String(64), primary_key=True, comment="主键ID")
  754. clue_name = Column(String(100), nullable=False, comment="线索姓名")
  755. mobile = Column(String(20), nullable=False, comment="手机号")
  756. company = Column(String(200), nullable=True, comment="公司名称")
  757. customer_type = Column(String(20), nullable=True, comment="客户类型(company-企业/person-个人)")
  758. telephone = Column(String(30), nullable=True, comment="固定电话")
  759. email = Column(String(100), nullable=True, comment="邮箱")
  760. title = Column(String(10), nullable=True, comment="称呼(先生/女士/其他)")
  761. position = Column(String(50), nullable=True, comment="职位")
  762. source = Column(String(20), nullable=False, comment="线索来源")
  763. level = Column(String(10), nullable=True, default="unrated", comment="线索等级(A/B/C/unrated)")
  764. industry = Column(String(50), nullable=True, comment="所属行业(字典 crm_customer_industry)")
  765. park_area = Column(String(100), nullable=True, comment="所在园区")
  766. province = Column(String(50), nullable=True, comment="省")
  767. city = Column(String(50), nullable=True, comment="市")
  768. district = Column(String(50), nullable=True, comment="区")
  769. address = Column(String(255), nullable=True, comment="详细地址")
  770. website = Column(String(500), nullable=True, comment="客户网站")
  771. intent_products = Column(String(500), nullable=True, comment="意向产品(多个用逗号分隔)")
  772. expect_time = Column(Date, nullable=True, comment="预计购买时间")
  773. budget = Column(String(20), nullable=True, comment="预算范围")
  774. requirement = Column(Text, nullable=True, comment="需求描述")
  775. status = Column(String(20), nullable=True, default="new", comment="线索状态(new/follow/invalid/converted)")
  776. owner_user_id = Column(String(64), nullable=True, comment="负责人ID")
  777. owner_user_name = Column(String(50), nullable=True, comment="负责人姓名(冗余)")
  778. last_time = Column(DateTime, nullable=True, comment="最后跟进时间")
  779. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  780. follow_count = Column(Integer, nullable=True, default=0, comment="跟进次数")
  781. is_converted = Column(SmallInteger, nullable=True, default=0, comment="是否已转化(0-否 1-是)")
  782. converted_time = Column(DateTime, nullable=True, comment="转化时间")
  783. customer_id = Column(String(64), nullable=True, comment="转化的客户ID")
  784. converted_by = Column(String(64), nullable=True, comment="转化操作人")
  785. assign_time = Column(DateTime, nullable=True, comment="分配时间")
  786. assign_by = Column(String(64), nullable=True, comment="分配人")
  787. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  788. order_num = Column(Integer, nullable=True, comment="排序号")
  789. remark = Column(String(512), nullable=True, comment="备注")
  790. create_by = Column(String(64), nullable=True, comment="创建人ID")
  791. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  792. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  793. update_by = Column(String(64), nullable=True, comment="更新人ID")
  794. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  795. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  796. class CrmClueFollow(Base):
  797. """CRM-线索跟进记录表"""
  798. __tablename__ = "crm_clue_follow"
  799. id = Column(String(64), primary_key=True, comment="主键ID")
  800. clue_id = Column(String(64), nullable=False, comment="线索ID")
  801. clue_name = Column(String(100), nullable=True, comment="线索姓名(冗余)")
  802. follow_type = Column(String(20), nullable=False, comment="跟进方式(电话/微信/邮件/拜访/其他)")
  803. follow_content = Column(Text, nullable=False, comment="跟进内容")
  804. next_time = Column(DateTime, nullable=True, comment="下次联系时间")
  805. attachments = Column(String(1000), nullable=True, comment="附件(多个用逗号分隔)")
  806. create_by_name = Column(String(50), nullable=True, comment="跟进人姓名(冗余)")
  807. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  808. order_num = Column(Integer, nullable=True, comment="排序号")
  809. remark = Column(String(512), nullable=True, comment="备注")
  810. create_by = Column(String(64), nullable=True, comment="创建人ID")
  811. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  812. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  813. update_by = Column(String(64), nullable=True, comment="更新人ID")
  814. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  815. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  816. class CrmPriceLetter(Base):
  817. """CRM-调价函档案(独立,不关联合同/报价单)"""
  818. __tablename__ = "crm_price_letter"
  819. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  820. letter_type = Column(String(20), nullable=False, comment="类型 receive接受/send发出")
  821. adjust_date = Column(Date, nullable=False, comment="调价日期")
  822. customer_id = Column(String(64), nullable=False, comment="客户ID")
  823. customer_name = Column(String(200), nullable=True, comment="客户名称(冗余)")
  824. product_id = Column(String(64), nullable=False, comment="产品ID")
  825. product_name = Column(String(200), nullable=True, comment="产品名称(冗余)")
  826. price = Column(DECIMAL(15, 2), nullable=False, comment="调整后现金价格(元)")
  827. bill_price = Column(DECIMAL(15, 2), nullable=False, default=Decimal("0.00"), comment="调整后汇票价格(元)")
  828. content = Column(Text, nullable=True, comment="发出类富文本HTML")
  829. attachment_urls = Column(String(4000), nullable=True, comment="附件URL(逗号分隔)")
  830. status = Column(String(20), nullable=False, default="normal", comment="状态 normal/invalid")
  831. invalid_reason = Column(String(200), nullable=True, comment="作废原因")
  832. invalid_time = Column(DateTime, nullable=True, comment="作废时间")
  833. invalid_by = Column(String(64), nullable=True, comment="作废人ID")
  834. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  835. order_num = Column(Integer, nullable=True, comment="排序号")
  836. remark = Column(String(512), nullable=True, comment="备注")
  837. create_by = Column(String(64), nullable=True, comment="创建人ID")
  838. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  839. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  840. update_by = Column(String(64), nullable=True, comment="更新人ID")
  841. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  842. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
  843. class CrmSupplierInfo(Base):
  844. """CRM-供方信息表"""
  845. __tablename__ = "crm_supplier_info"
  846. id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
  847. supplier_name = Column(String(200), nullable=False, comment="供方名称(章)")
  848. short_name = Column(String(100), nullable=True, comment="简称")
  849. supplier_code = Column(String(50), nullable=True, comment="编码")
  850. supplier_address = Column(String(500), nullable=True, comment="单位地址")
  851. legal_person = Column(String(100), nullable=True, comment="法定代表人")
  852. agent = Column(String(100), nullable=True, comment="代理人")
  853. phone_fax = Column(String(100), nullable=True, comment="电话/传真")
  854. bank_name = Column(String(200), nullable=True, comment="开户银行")
  855. bank_account = Column(String(100), nullable=True, comment="账号")
  856. status = Column(String(1), nullable=True, default="0", comment="状态(0正常 1停用)")
  857. tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
  858. order_num = Column(Integer, nullable=True, comment="排序号")
  859. remark = Column(String(500), nullable=True, comment="备注")
  860. create_by = Column(String(64), nullable=True, comment="创建人ID")
  861. create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
  862. create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
  863. update_by = Column(String(64), nullable=True, comment="更新人ID")
  864. update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
  865. del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")