Skip to content

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/export

saveCustomerFollowRecord(CustomerFollowRecordDto) 的业务意义:记录本次沟通,并通过截止时间规则更新对应产品跟进。

客户创建流程中也会调用它的同类逻辑:

text
按客户 + 产品找到 CustomerProductFollow
  -> 保存 customer_follow_record
  -> 保存附件 sys_file
  -> 构造 DeadlineRuleDto
  -> CustomerProductFollowService.applyDeadlineRule

因此“保存跟进记录”可能改变 customer_product_follow.recent_follow_timefollow_deadlinefollow_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_record

Demo 状态可以先简化为:

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 的“客户生命周期”为什么由客户产品跟进驱动。

Lucking