|
|
|
|
# 02 — 客户主表字段清单
|
|
|
|
|
|
|
|
|
|
Type: research
|
|
|
|
|
Status: resolved
|
|
|
|
|
> **⚠ 20260902 复核注记**:本文件 `archiveStatus` 仍写三值(有效1/已归档2/已被合并3)。**D19 已拍板去掉「已被合并」**(合并 Out-of-scope),收敛为**有效1/已归档2**。**以 `02-answer.md` 为准。**
|
|
|
|
|
Blocked by:
|
|
|
|
|
|
|
|
|
|
## 问题
|
|
|
|
|
|
|
|
|
|
定客户主表 `customer` 的完整字段清单 + 索引 + DataScope 注解。这是扇出最广的票,其他票(三视图/查重/交割/阶段)回填它。
|
|
|
|
|
|
|
|
|
|
## 一手证据(蓝湖缓存 txt)
|
|
|
|
|
|
|
|
|
|
- `a4-3-3-1_新增客户信息.txt` — 新增页字段(基本信息/工商信息/跟进人员/关联信息/补充资料五区)
|
|
|
|
|
- `a4-4-1_客户详情_客户信息_.txt` — 详情页字段分区(基本信息/关联信息/补充资料/工商信息/系统信息)
|
|
|
|
|
- `a4-2-1_客户总览列表_列表视图_.txt` — 列表列 + 字段设置项
|
|
|
|
|
|
|
|
|
|
## 已知字段线索(待核实归类)
|
|
|
|
|
|
|
|
|
|
- **系统生成**:客户编号 `customer_no`(KH+日期+序,只读)、创建人/时间、修改人/时间。
|
|
|
|
|
- **基本信息**:客户名称*、客户类型*(字典)、所属地区*(省市区)、行业*(两级树,复用 crm-dict `industry`)、客户星级*(一~五星)、关系星级*(一~五星)、人脉关系单位(标签集)、公司决策人。
|
|
|
|
|
- **归属(轴1)**:`owner_user_id`(销售负责人*)+`owner_dept_id`(销售部门*快照)+协同人(团队子表)。
|
|
|
|
|
- **阶段(轴2)**:`customer_stage`(潜在/重潜/已成交)。
|
|
|
|
|
- **档案状态**:`archive_status`(有效/已归档/已被合并)。
|
|
|
|
|
- **战略协议**(划出):`战略协议等级` 列在列表出现——但战略协议子域划出,主表是否冗余一个等级快照列供列表展示?→ 本票决定(建议:留 `strategic_agreement_level` 快照列供列表,实体本身划出)。
|
|
|
|
|
- **已成交VIP客户等级**:列表有列 → 主表字段还是 A5 驱动?待定(疑似阶段=已成交后的细分,可能留 seam)。
|
|
|
|
|
- **工商信息**(企查查回填):统一社会信用代码(唯一)、法定代表人、成立时间、注册资本、经营范围、人员规模、年产值、公司地址、工商名称。
|
|
|
|
|
- **关联信息**:是否商机勾兑*、总监近期拜访时间、是否子客户*(是→父客户关联必填)、父客户关联(禁自身及下级/防环)、合作系统、不合作原因、是否参加总裁班/产品经理班(+参加人/电话,条件必填)。
|
|
|
|
|
- **补充资料**:备注(≤500)、附件(crm-file)。
|
|
|
|
|
|
|
|
|
|
## 待拍板点(research 中逐一给推荐 + grill)
|
|
|
|
|
|
|
|
|
|
1. 战略协议等级 / 已成交VIP等级 是否主表冗余快照列(战略协议实体划出)?
|
|
|
|
|
2. 父子客户:自关联 `parent_customer_id` + 防环校验口径。
|
|
|
|
|
3. 客户类型字典分组(`customer_type`)取值:甲方(企业/政府/普教/中高职/高校)… 需列全。
|
|
|
|
|
4. 客户星级/关系星级:字典 or 定长枚举(一~五星)?
|
|
|
|
|
5. 冗余快照列(列表免 join):最近跟进时间、关联业务计数(商机/项目)、owner 名快照。
|
|
|
|
|
6. DataScope:`@DataScope(module="customer", ownerColumn="owner_user_id", deptColumn="owner_dept_id")`。
|
|
|
|
|
7. 索引:UNIQUE 统一社会信用代码 / owner+stage / owner_dept+archive_status(公海视图)。
|
|
|
|
|
|
|
|
|
|
## Answer
|
|
|
|
|
|
|
|
|
|
**Status: resolved**(P0 已全部销号:customer_type=18值字典/D18、行业二级、星级硬编码/D4-rev1;含 grill Q8/Q15 回填)
|
|
|
|
|
|
|
|
|
|
**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 | 逻辑删除 |
|
|
|
|
|
|
|
|
|
|
**业务字段 — 系统生成**
|
|
|
|
|
|
|
|
|
|
| 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/已被合并3;正交于归属 |
|
|
|
|
|
|
|
|
|
|
**业务字段 — 快照/冗余(列表免 join)**
|
|
|
|
|
|
|
|
|
|
| Java 字段 | 列名 | 类型 | 说明 |
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
| lastValidFollowTime | last_valid_follow_time | datetime | 最近有效跟进时间;**超期提醒计时锚点 = 成为「有主」的时刻**(新建即指派=create_time;公海领取时=领取时刻;每写一条跟进记录刷新);公海无负责人=NULL不提醒 |
|
|
|
|
|
| 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 注解
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
@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)
|
|
|
|
|
|
|
|
|
|
| # | 问题 | 影响 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| P0-1 | ~~`customer_type` 完整枚举值~~ **已拍板(grill Q8/D18)**:crm-dict 字典,18 值 | 字典种子数据 |
|
|
|
|
|
| P0-2 | ~~客户选行业到几级~~ **定稿:二级**(`industry_code` + `industry_child_code` 两列;与商机图 D1「商机选一级、客户选二级」一致) | 两列 |
|
|
|
|
|
| P0-3 | ~~星级枚举 vs 字典~~ **已拍板(D4-rev1)**:硬编码枚举 1~5,不走字典 | 存储类型 |
|
|
|
|
|
| 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_code` UNIQUE 索引 + `customer_name` idx 是查重的存储底座。
|
|
|
|
|
- **票 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` 是计时锚点 = **成为有主时刻**(grill Q15 拍板 A):新建即指派=create_time;公海领取=领取时刻;跟进刷新。公海(NULL)不计时。
|