Skip to content

17:试单申请:产品关联、审批与截止时间联动

1. 试单是什么

试单是客户尚未正式成交、但已经进入实际合作验证阶段的申请单。它关联的是客户产品跟进,而不是直接关联一个孤立的客户。

text
customer_product_follow(正在跟进)
  -> trial_order_application(试单主表)
  -> trial_order_product(关联的跟进产品)
  -> BPM 审批
  -> 截止时间规则联动

2. 当前代码和表

内容代码
ControllerTrialOrderApplicationController-
主 ServiceTrialOrderApplicationServiceImpltrial_order_application
产品关联 ServiceTrialOrderProductServiceImpltrial_order_product
输入/输出TrialOrderApplication*Form、Dto、Vo-
规则联动CustomerProductFollowService.applyDeadlineRulecustomer_follow_deadline_log

关键方法:

text
saveTrialOrderApplication(TrialOrderApplicationDto)
updateTrialOrderApplication(TrialOrderApplicationDto)
findById(Long)
updateFlowProgress(String flowId, String status)
validExistsTrialOrderApplication(TrialOrderApplicationDto)
applyDeadlineRule(TrialOrderApplication, DeadLineLogOperateTypeEnum)

3. 保存试单申请的真实逻辑

saveTrialOrderApplication 的工作不是只写主表:

text
1. 调 validExistsTrialOrderApplication 校验是否存在冲突/重复试单
2. 从当前用户上下文获得部门和人员信息
3. 保存 trial_order_application 主表
4. TrialOrderProductService 批量保存 productFollowId 列表
5. 发起 BPM 流程,回写 flowId、流程状态和开始时间
6. 后续审批状态变化时应用截止时间规则

实际的试单产品表保存前还会:

text
按 productFollowId 查询 CustomerProductFollow
  -> 必须存在
  -> 必须处于 FOLLOWING
  -> 从跟进记录复制 customerId、productId、跟进人、跟进部门等上下文

因此前端不应该直接传任意 customerId/productId 组合来创建试单;系统以已经建立的产品跟进作为事实来源。

4. 编辑、详情和审批回调

编辑:

text
1. 主单必须存在
2. 替换或更新 trial_order_product 关联产品
3. 更新主表字段
4. 保持业务状态与流程状态的一致性

详情:

text
trial_order_application
  + trial_order_product
  + 关联客户、产品、跟进人展示信息
  + 流程字段

回调:

text
updateFlowProgress(flowId, status)
  -> 更新试单流程状态
  -> 识别审批通过、驳回、撤销等状态
  -> 调 applyDeadlineRule
  -> 更新相关客户产品的保护截止时间与日志

5. 与项目评估、合同的关系

三类单据都从产品跟进出发:

单据前置审批后影响
项目评估跟进状态为 FOLLOWING,当前用户是跟进人流程状态、评估资料
试单申请关联跟进产品存在且 FOLLOWING跟进截止时间规则
合同符合合同创建条件的跟进产品截止时间、成交阶段、客户首单日期

不要把这些单据理解为彼此独立的“表单模块”;它们共同驱动客户产品跟进生命周期。

6. Demo 的最小实现

表:

text
demo_trial_order
  id, customer_id, status, flow_id, created_at

demo_trial_order_product
  id, trial_order_id, product_follow_id

步骤:

text
1. 请求传 productFollowIds
2. 循环查询每个跟进必须为 FOLLOWING
3. 保存试单主表 + 产品关联,放在同一事务
4. status 初始 PENDING
5. 写一个模拟审批接口:PENDING -> APPROVED / REJECTED
6. APPROVED 时把这些跟进的 deadline 延长 15 天,并写日志

完成后,你会理解正式 TrialOrderProductServiceImpl 为什么需要复制跟进人和部门:试单审批和后续规则需要保存当时的业务上下文。

7. 必测用例

  • productFollowId 不存在,创建失败;
  • productFollowStatus 不是 FOLLOWING,创建失败;
  • 多个产品中有一个非法,主单和所有关联表都回滚;
  • 审批通过后截止时间更新,驳回按对应规则处理;
  • 重复试单按 validExistsTrialOrderApplication 的业务规则被拦截;
  • 详情返回主单和全部产品关联。

8. 源码阅读顺序

text
TrialOrderApplicationController
TrialOrderApplicationServiceImpl.saveTrialOrderApplication
TrialOrderApplicationServiceImpl.validExistsTrialOrderApplication
TrialOrderApplicationServiceImpl.updateFlowProgress
TrialOrderApplicationServiceImpl.applyDeadlineRule
TrialOrderProductServiceImpl.batchInsertProducts
TrialOrderProductServiceImpl.batchUpdateProducts
pginit.sql 中 trial_order_application / trial_order_product

Lucking