Appearance
17:试单申请:产品关联、审批与截止时间联动
1. 试单是什么
试单是客户尚未正式成交、但已经进入实际合作验证阶段的申请单。它关联的是客户产品跟进,而不是直接关联一个孤立的客户。
text
customer_product_follow(正在跟进)
-> trial_order_application(试单主表)
-> trial_order_product(关联的跟进产品)
-> BPM 审批
-> 截止时间规则联动2. 当前代码和表
| 内容 | 代码 | 表 |
|---|---|---|
| Controller | TrialOrderApplicationController | - |
| 主 Service | TrialOrderApplicationServiceImpl | trial_order_application |
| 产品关联 Service | TrialOrderProductServiceImpl | trial_order_product |
| 输入/输出 | TrialOrderApplication*Form、Dto、Vo | - |
| 规则联动 | CustomerProductFollowService.applyDeadlineRule | customer_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