11 KiB
Answer
Status: resolved
A. 客户主表 customer(crm-customer)
A1. 字段清单
系统字段(BaseEntity 继承)
| Java 字段 | 列名 | 类型 | 说明 |
|---|---|---|---|
| id | id | bigint PK | 自增主键 |
| createTime | create_time | datetime | 创建时间 |
| updateTime | update_time | datetime | 最后修改时间 |
| createBy | create_by | bigint | 创建人 user_id |
| updateBy | update_by | bigint | 最后修改人 user_id |
| deleted | deleted | tinyint(1) default 0 | 逻辑删除(一期:仅系统在合并时置 1,不开放手动删除/无前端删除入口——§5.3 拍板 A) |
业务字段 — 系统生成
| Java 字段 | 列名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| customerNo | customer_no | varchar(32) | 系统生成 | 唯一编号,格式 KH+yyyyMMdd+4位序;只读不可改 |
业务字段 — 基本信息
| Java 字段 | 列名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| customerName | customer_name | varchar(100) | ✅ | 客户名称;停输防抖触发相似查重 |
| customerType | customer_type | varchar(50) | ✅ | 客户类型字典 customer_type;见 A3 字典节 |
| provinceCode | province_code | varchar(20) | ✅ | 省(三级地区,与商机对称) |
| cityCode | city_code | varchar(20) | ✅ | 市 |
| districtCode | district_code | varchar(20) | 区/县(客户有三级,商机只二级) | |
| industryCode | industry_code | varchar(50) | ✅ | 行业一级 code(复用 crm-dict industry 两级树;客户选到二级,见商机图 D1「行业字典口径」决策:商机选一级、客户选二级) |
| industryChildCode | industry_child_code | varchar(50) | 行业二级 code(客户额外存二级;商机无此列) | |
| customerStarLevel | customer_star_level | tinyint | ✅ | 客户星级 1~5(枚举,非字典;字典值「一星/二星/…/五星」=前端展示用,存数字) |
| relationStarLevel | relation_star_level | tinyint | ✅ | 关系星级 1~5(同上) |
| networkUnits | network_units | text | 人脉关系单位,JSON 数组存标签名(单个≤50字;非关联 CRM 客户;选填) |
⚠ JPA/Hibernate 孤立单大写字母规则(AGENTS.md):
districtCode/industryCode/industryChildCode/provinceCode/cityCode/customerNo/customerStarLevel/relationStarLevel— 均为「完整词+Code/Level/No」,非孤立单大写,不需加@Column(name=...)。
业务字段 — 归属(轴1)
| Java 字段 | 列名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| ownerUserId | owner_user_id | bigint | ✅(新增时) | 销售负责人 user_id;公海时为 NULL |
| ownerUserNameSnapshot | owner_user_name_snapshot | varchar(64) | 负责人姓名快照(列表免 join) | |
| ownerDeptId | owner_dept_id | bigint | ✅(新增时) | 销售部门 dept_id 快照;公海时保留最后部门(供公海可见性锚点,对称商机) |
| ownerDeptNameSnapshot | owner_dept_name_snapshot | varchar(64) | 部门名快照 |
协同人(团队成员)= 独立子表
customer_team_member(不在主表)。
业务字段 — 轴2 阶段 + 档案状态
| Java 字段 | 列名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| customerStage | customer_stage | tinyint default 1 | 客户阶段:潜在1/重潜2/已成交3;只增不减;不可手动改 | |
| archiveStatus | archive_status | tinyint default 1 | 档案状态:有效1/已归档2(D19 拍板去掉「已被合并」,合并 Out-of-scope);正交于归属;已归档即删除语义(软删),列表加 archive_status 筛选默认排除 |
业务字段 — 快照/冗余(列表免 join)
| Java 字段 | 列名 | 类型 | 说明 |
|---|---|---|---|
| lastValidFollowTime | last_valid_follow_time | datetime | 最近有效跟进时间(新建时=create_time;每写一条跟进记录刷新;超期提醒计时锚点) |
| strategicAgreementLevel | strategic_agreement_level | tinyint | 战略协议等级快照(1~3级;战略协议子域划出但主表留此冗余供列表展示;NULL=未签);由战略协议子系统写入,本图只读 |
| vipCustomerLevel | vip_customer_level | tinyint | 已成交VIP客户等级快照(1~5级;NULL=无;由 A5 项目模块写入,本图只读/留 seam) |
⚠
strategicAgreementLevel→ Hibernate 命名策略孤立单大写字母:Level前面的l是小写 →strategicAgreement+Level整段。实测SpringPhysicalNamingStrategy对strategicAgreementLevel生成strategic_agreement_level✅(Level是完整词,无问题)。但vipCustomerLevel→vip首字母v是小写,C是孤立大写?→ 不是,vip是小写词,Customer是完整词,Level是完整词,不踩坑。
业务字段 — 关联信息
| Java 字段 | 列名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| companyDecisionMaker | company_decision_maker | varchar(100) | 公司决策人(文本) | |
| isBizNegotiated | is_biz_negotiated | tinyint | ✅ | 是否商机勾兑(是1/否0) |
| directorVisitTime | director_visit_time | datetime | 总监近期拜访时间(人工维护,日期时间) | |
| isChild | is_child | tinyint default 0 | ✅ | 是否子客户(是1/否0);=1时 parent_customer_id 必填 |
| parentCustomerId | parent_customer_id | bigint | 条件必填 | 父客户 id;服务端防环校验;isChild=0时为 NULL |
| parentCustomerNameSnapshot | parent_customer_name_snapshot | varchar(100) | 父客户名称快照 | |
| cooperationSystem | cooperation_system | varchar(200) | 合作系统(文本,选填) | |
| nonCoopReason | non_coop_reason | varchar(200) | 不合作原因(文本,选填) | |
| joinedPresidentClass | joined_president_class | tinyint | 是否参加总裁班(是1/否0/NULL=未选) | |
| presidentClassPerson | president_class_person | varchar(100) | 条件必填 | 总裁班参加人(joinedPresidentClass=1时必填) |
| presidentClassPhone | president_class_phone | varchar(20) | 条件必填 | 总裁班参加人电话 |
| joinedProductClass | joined_product_class | tinyint | 是否参加产品经理班 | |
| productClassPerson | product_class_person | varchar(100) | 条件必填 | 产品班参加人 |
| productClassPhone | product_class_phone | varchar(20) | 条件必填 | 产品班参加人电话 |
业务字段 — 工商信息(企查查回填)
| Java 字段 | 列名 | 类型 | 说明 |
|---|---|---|---|
| unifiedCreditCode | unified_credit_code | varchar(18) | 统一社会信用代码;UNIQUE(NULL 除外,未填时不唯一约束);18 位格式校验 |
| legalRepresentative | legal_representative | varchar(100) | 法定代表人 |
| establishedDate | established_date | date | 成立时间(不得晚于当前日期) |
| registeredCapital | registered_capital | varchar(100) | 注册资本(文本,含单位,如「1000万元」) |
| businessScope | business_scope | text | 经营范围(不套 50 字限制) |
| staffSize | staff_size | varchar(50) | 人员规模 |
| annualRevenue | annual_revenue | varchar(50) | 年产值 |
| businessAddress | business_address | varchar(500) | 工商注册地址(不套 50 字限制) |
| bizNameFromLookup | biz_name_from_lookup | varchar(200) | 企查查确认的工商名称(可与 customer_name 不同;只存不覆盖 customer_name,除非用户确认) |
业务字段 — 补充资料
| Java 字段 | 列名 | 类型 | 说明 |
|---|---|---|---|
| remark | remark | varchar(500) | 备注(≤500字) |
附件 = 独立子表
customer_attachment(复用 crm-file,biz_type=CUSTOMER;不在主表)。
A2. 需要显式 @Column(name=...) 的孤立单大写字母字段
检查全部字段——结论:本表无需加 @Column(name=...)。所有字段均为「完整词 + 完整词」组合,无孤立单大写字母触发 Hibernate 命名策略陷阱。
A3. 字典清单(新增/复用)
| 字典分组 code | 含义 | 状态 | 参考值 |
|---|---|---|---|
customer_type |
客户类型 | 🆕 需新增 | (grill Q8/D18 定稿,18 值) 运营商 / 土建总包 / 机电总包 / 装修总包 / 教育局 / 投资(代建)公司 / 设计院 / 集成商 / 集成商(子客户) / 咨询造价公司 / 甲方(企业用户) / 甲方(普教) / 甲方(中高职) / 甲方(政府机关) / 竞争同行 / 个人用户 / 操手 / 招标代理 |
industry |
行业(两级树) | ✅ 已有(商机图票09已建;9一级+51二级) | 复用 |
customer_star_level |
客户星级 | 硬编码枚举 1~5(D4-rev1 定稿,不走字典) | 1~5 星 |
relation_star_level |
关系星级 | 硬编码枚举 1~5(D4-rev1 定稿,不走字典) | 一星~五星 |
✅ 已定(grill Q8/D18):
customer_type= crm-dict 字典分组,18 值(见上表)。含 4 甲方值 + 14 非甲方角色值,是通用角色字典。
A4. DataScope 注解
@DataScope(module = "customer", ownerColumn = "owner_user_id", deptColumn = "owner_dept_id")
复用 crm-auth DataScopeEnum(SELF/DEPT/DEPT_AND_CHILD/ALL),不新建可见性机制。
A5. 索引
| 索引名 | 列 | 说明 |
|---|---|---|
uk_unified_credit_code |
unified_credit_code |
信用代码全局唯一(NULL 不参与唯一约束,MySQL 默认行为) |
idx_owner_stage |
owner_user_id, customer_stage, deleted |
我的客户视图常用过滤 |
idx_dept_stage |
owner_dept_id, archive_status, deleted |
公海/总览部门维度 |
idx_name |
customer_name |
相似查重防抖查询 |
idx_parent |
parent_customer_id |
父子客户查询/防环 |
idx_last_follow |
last_valid_follow_time, owner_user_id |
超期未跟进提醒扫表 |
A6. 产品确认项(⚠ P0)— 已随 grill 全部销号
| # | 问题 | 影响 |
|---|---|---|
| P0-1 | customer_type 完整枚举值 |
字典种子数据 |
| P0-2 | industry_code + industry_child_code 两列;与商机图 D1 一致) |
两列 |
| P0-3 | 存储类型 | |
| P1-1 | vip_customer_level 等级范围(原型列表列有「已成交VIP客户等级」但详情字段写「1~5级」,待确认范围及触发条件,本图只留 seam) |
— |
| P1-2 | strategic_agreement_level 战略协议等级范围(原型见「一级/二级/三级」=1~3;战略协议子域划出,主表只存冗余快照,待战略协议 effort 回填写逻辑) |
— |
A7. 回填 ticket 02 的下游影响
- 票 03(三视图):
archiveStatus过滤(有效1/已归档2,无已被合并——D19),ownerUserId IS NULL= 公海视图;last_valid_follow_time排序。 - 票 04(查重):
unified_credit_codeUNIQUE 索引 +customer_nameidx 是查重的存储底座。 - 票 05(阶段):
customer_stage默认1,只能 UPDATE SET customer_stage=? WHERE id=? AND customer_stage < ?(只前进)。 - 票 07(oplog):
last_valid_follow_time新建时初始化为create_time。 - 票 08(交割):
ownerUserId+ownerDeptId是交割换主的操作列。 - 票 10(超期提醒):
last_valid_follow_time是计时锚点;新建时初始化为create_time(grill 挂号确认,见 map.md)。