Appearance
13:产品跟进与跟进记录:真实保存和截止时间规则
1. 这是当前 CRM 的业务核心
核心 Service:
text
CustomerProductFollowServiceImpl
CustomerFollowRecordServiceImpl核心表:
text
customer_product_follow
customer_contact
customer_follow_record
customer_follow_record_comment
customer_follow_deadline_log
customer_product_claim_log一个 customer_product_follow 表示:某客户的某个产品,正在由某个商务在某部门下跟进。它不是普通客户联系人,也不是客户主资料。
2. 跟进产品接口和输入
Controller:CustomerProductFollowController。
text
POST /web/client/customerProductFollow/save
POST /web/client/customerProductFollow/transfer
POST /web/client/customerProductFollow/share
POST /web/client/customerProductFollow/claim
POST /web/client/customerProductFollow/query/followPage
POST /web/client/customerProductFollow/query/publicPoolPage
GET /web/client/customerProductFollow/query/currentFollowProductList新增入口使用 CustomerProductFollowAddForm,经 CustomerProductFollowConverter 转为 CustomerProductFollowDto,最后调用:
java
saveCustomerProductFollow(CustomerProductFollowDto dto)3. 新增产品跟进的真实校验顺序
源码方法:CustomerProductFollowServiceImpl.saveCustomerProductFollow,带事务。
text
1. 收集所有选择的 productId,判断本次提交有没有重复产品
2. 读取 tenantId、当前用户 openId、当前用户主部门
3. 查询这些客户-产品是否正在公海;在公海则拒绝新增
4. 查询是否已有其他人正在跟进相同客户-产品;有则拒绝
5. 读取客户保护规则(普通或特殊配置)
6. 校验当前用户保护中的客户数量是否超过上限
7. 校验当前用户对该客户保护中的产品数量是否超过上限
8. 校验认领次数、认领冻结天数
9. 查询产品名称,准备批量写入对象
10. 对每个产品创建跟进、联系人、截止时间日志、认领日志
11. 批量保存四类记录,并写客户变更日志4. 每个产品会写哪些表
对每个 productId,当前实现至少构造:
| 表 | 写入内容 |
|---|---|
customer_product_follow | 客户、产品、跟进人/部门、阶段、状态、首次/最近时间、截止时间、公海标志 |
customer_contact | 该客户-产品下的联系人及归属人 |
customer_follow_deadline_log | 本次“新增跟进产品”导致的截止时间变更 |
customer_product_claim_log | 当前用户的初始认领记录 |
customer_info_change_log | 跟进产品创建的审计记录 |
初始化的关键状态在源码中明确设置:
text
followPhase = E_FIRST_CONTACT
protectStatus = PROTECT
followStatus = FOLLOWING
followCount = 0
firstFollowTime = now
recentFollowTime = now
followDeadline = now + newFollowDay
isPublicPool = NO
followSource = CREATE这些值不是随便选的展示字段;它们共同决定是否在保护中、是否可进入项目评估/试单/合同、何时掉入公海。
5. 跟进记录不是“备注”
Controller:CustomerFollowRecordController。
text
POST /customerFollowRecord/save
POST /customerFollowRecord/query/page
POST /customerFollowRecord/claimFollowRecord
POST /customerFollowRecord/exportsaveCustomerFollowRecord(CustomerFollowRecordDto) 的业务意义:记录本次沟通,并通过截止时间规则更新对应产品跟进。
客户创建流程中也会调用它的同类逻辑:
text
按客户 + 产品找到 CustomerProductFollow
-> 保存 customer_follow_record
-> 保存附件 sys_file
-> 构造 DeadlineRuleDto
-> CustomerProductFollowService.applyDeadlineRule因此“保存跟进记录”可能改变 customer_product_follow.recent_follow_time、follow_deadline、follow_count 等字段,而不仅是插入一行记录。
6. 截止时间规则是一个小型规则引擎
统一入口:
java
applyDeadlineRule(DeadlineRuleDto dto)它会根据来源类型和操作类型分发到不同规则:
text
合同:applyDeadlineByContract
试单:applyDeadlineByTrial
开票:applyDeadlineByInvoice
跟进记录:applyDeadlineByRecord每次规则应用都应留下 customer_follow_deadline_log,记录:
text
为什么变更(operateType / ruleType)
基准时间是什么(baseTime / baseTimeType)
前截止时间、后截止时间
加减的天数
来源业务 id 和来源类型
操作人和部门这使得“为什么这个客户产品今天掉入公海”可以被追溯。
7. 转移和分享不是同一个动作
| 动作 | 核心含义 | 关键副作用 |
|---|---|---|
transfer | 将当前跟进关系移交给另一用户/部门 | 更新归属、写 customer_transfer_log、更新审计 |
share | 在保护期内把客户产品共享给其他人 | 新建或更新共享跟进关系,保留原关系的业务语义 |
claim | 从公海认领 | 校验认领上限/冻结,更新公海和跟进状态,写认领日志 |
不要在 Demo 中先做这三种复杂操作。你应先实现“新增跟进产品 + 新增跟进记录 + 延长截止时间”。
8. Demo 的最小对应实现
建议建三张表:
text
demo_customer
demo_customer_product_follow
demo_follow_recordDemo 状态可以先简化为:
java
enum DemoFollowStatus { FOLLOWING, EXPIRED, PUBLIC_POOL }
enum DemoFollowPhase { E_FIRST_CONTACT, B_HIGH_INTENTION, VIP }实现顺序:
text
1. 新增产品跟进
- 同一 customerId + productName 不能有 FOLLOWING 记录
- 默认 FOLLOWING、E_FIRST_CONTACT、deadline = now + 30 天
2. 新增跟进记录
- 跟进记录必须属于一个存在且 FOLLOWING 的跟进产品
- 更新 recentFollowTime = now
- deadline = now + 30 天
- 写 demo_follow_deadline_log(可在第二步后再加)
3. 到期扫描
- 查询 deadline < now 且 FOLLOWING 的记录
- 更新为 EXPIRED每一步都加 @Transactional,并写接口测试证明状态正确变化。
9. 源码阅读清单
text
CustomerProductFollowController
CustomerProductFollowServiceImpl.saveCustomerProductFollow
CustomerProductFollowServiceImpl.checkProductFollowStatus
CustomerProductFollowServiceImpl.checkMaxCustomer
CustomerProductFollowServiceImpl.checkMaxCustomerProduct
CustomerProductFollowServiceImpl.checkMaxClaim
CustomerProductFollowServiceImpl.applyDeadlineRule
CustomerFollowRecordController
CustomerFollowRecordServiceImpl.saveCustomerFollowRecord
pginit.sql 中 customer_product_follow、customer_follow_record、customer_follow_deadline_log读完这组代码后,你就理解了 CRM 的“客户生命周期”为什么由客户产品跟进驱动。
