发票、收款、提成与订单状态数据流
基于当前代码实现梳理 CRM 发票、收款、财务状态、订单状态和提成状态的触发操作、流转规则与业务影响
发票、收款、提成与订单状态数据流
本文基于 2026 年 8 月 24 日 当前代码实现,说明 CRM 中以下状态如何变化:
- 发票申请状态
- 回款审批状态
- 商机的订单状态
- 商机的财务状态
- 商机提成状态
本文描述的是系统当前实际执行逻辑,不把页面按钮、流程名称或历史设计当作已经生效的业务能力。
一、核心结论
- 商机是主聚合对象:发票和回款都通过
orderId关联商机,最终回写商机的financialStatus。 - 发票只有进入“已开票”才计入开票金额:待申请、待审核、已驳回、待上传都不参与财务状态计算。
- 回款只有“审核通过”才计入已收款金额:草稿、审批中、审核不通过、已取消都不计入。
- 财务状态只对“赢单”商机自动重算:非赢单商机触发重算时会直接跳过。
- 订单状态与财务状态都为“完成”时才生成待提成记录:以后完成的那个状态决定
qualifiedSource。 - 提成记录生成后不会因订单或财务状态回退而自动撤销。
- 订单状态和财务状态都保留人工直接修改入口:人工修改为完成也可能直接触发提成资格。
二、总体数据流图
三、关键数据对象
| 业务对象 | 表 | 关键关联 | 状态字段 |
|---|---|---|---|
| 商机 / 交易单 | crm_business | 主键 id | end_status、order_status、financial_status |
| 发票申请 | crm_order_invoice | order_id -> crm_business.id | status |
| 回款 | crm_receivable | order_id -> crm_business.id | audit_status |
| 回款计划 | crm_receivable_plan | order_id -> crm_business.id | 通过计划日期和 receivable_id 判断逾期 |
| 商机提成 | crm_business_commission | business_id -> crm_business.id | status |
系统中另有
crm_sales_commission“销售提成记录”模块,它是人工维护的收入、底薪等统计记录,没有提成状态,也不参与本文的自动资格链路。本文的“提成状态”指crm_business_commission。
四、发票状态流转
4.1 状态定义
| 状态值 | 状态名称 | 是否计入开票金额 |
|---|---|---|
10 | 待申请 | 否 |
20 | 待审核 | 否 |
30 | 已驳回 | 否 |
40 | 待上传 | 否 |
50 | 已开票 | 是 |
4.2 状态流转图
4.3 操作与业务影响
| 操作 | 前置状态 | 新状态 | 其他业务动作 |
|---|---|---|---|
| 创建发票申请 | 商机存在,当前用户是商机负责人 | 待申请 | 写入申请人;发送创建通知 |
| 修改发票申请 | 待申请、已驳回 | 不变 | 可修改备注和申请金额 |
| 提交审核 | 待申请、已驳回 | 待审核 | 清空驳回原因;记录提交人和提交时间;为所有发票审核权限人员创建待办并发送通知 |
| 审核驳回 | 待审核 | 已驳回 | 记录驳回原因、审核人和审核时间;完成当前发票待办;通知销售 |
| 审核通过,不附正式发票 | 待审核 | 待上传 | 为所有上传权限人员创建待办;通知上传人员和申请人;不重算财务状态 |
| 审核通过,同时附正式发票 | 待审核 | 已开票 | 记录审核和上传信息;完成待办;重算财务状态;通知销售 |
| 上传正式发票 | 待上传 | 已开票 | 保存文件、名称、金额和上传人;完成待办;重算财务状态;通知销售 |
| 删除 | 待申请、已驳回 | 删除记录 | 不允许删除待审核、待上传、已开票记录 |
4.4 发票金额口径
商机已开票金额为:
SUM(crm_order_invoice.amount),查询条件是同一 order_id 且发票状态为 50-已开票。
因此:
- 申请金额不代表已开票金额。
- 审核通过但仍待上传时,不计入已开票金额。
- 审核时附文件,或者后续上传正式发票,才会触发财务状态重算。
- 发票可以在商机尚未赢单时创建并开具,但自动财务重算会因商机不是赢单状态而跳过。
五、回款状态流转
5.1 状态定义
| 状态值 | 状态名称 | 是否计入已收款金额 |
|---|---|---|
0 | 未提交 / 草稿 | 否 |
10 | 审批中 | 否 |
20 | 审核通过 | 是 |
30 | 审核不通过 | 否 |
40 | 已取消 | 否 |
5.2 当前实际流转图
5.3 当前操作与业务影响
| 操作 | 当前实际行为 | 对财务状态的影响 |
|---|---|---|
| 创建回款 | 新记录直接写为 10-审批中 | 立即触发重算,但审批中金额不计入已收款金额 |
| 修改回款 | 仅草稿或审批中允许编辑 | 立即触发重算;审批中金额仍不计入 |
| 更新审批状态 | 接口直接写入传入的 auditStatus | 立即重算;只有写成 20 后金额才计入 |
| 提交审批 | 仅允许草稿调用,但 BPM 创建和状态更新代码已停用 | 当前不会创建审批流程,也不会把草稿改成审批中 |
| 删除回款 | 审核通过不可删除;有关联回款计划且计划仍存在时不可删除 | 删除成功后重算 |
5.4 回款金额口径
商机已收款金额为:
SUM(crm_receivable.price),查询条件是同一 order_id 且审批状态为 20-审核通过。
5.5 回款计划对逾期的影响
存在以下回款计划时,商机可能被计算为“付款逾期”:
- 计划属于当前商机;
receivable_id为空,表示尚未绑定回款;- 计划回款时间早于当天开始时间。
创建回款并绑定某个回款计划后,系统会立即把回款编号写入计划。即使回款仍处于审批中,该计划也不再满足“未绑定回款”的逾期条件。
六、商机财务状态
6.1 状态定义
| 状态值 | 状态名称 |
|---|---|
11 | 未开票,未收款 |
1 | 已开票,未收款 |
22 | 未开票,已收款 |
23 | 部分款票 |
10 | 款票完成 |
20 | 付款逾期 |
6.2 自动重算触发源
| 触发操作 | 触发时点 |
|---|---|
| 发票审核通过并同时上传正式发票 | 发票改为已开票后 |
| 上传正式发票 | 发票改为已开票后 |
| 创建回款 | 回款保存后 |
| 修改回款 | 回款保存后 |
| 更新回款审批状态 | 审批状态保存后 |
| 删除回款 | 回款删除后 |
| 财务状态批量重算任务 | 任务执行时遍历全部赢单商机 |
项目中存在
CrmBusinessFinancialStatusJob处理器,但仓库内没有发现固定的 Quartz 初始化记录。是否按计划周期执行,取决于运行环境中是否另行配置了定时任务。
6.3 自动重算前置条件
只有同时满足以下条件才会计算:
- 商机存在;
- 商机总金额不为空;
- 商机结束状态为“赢单”。
如果不满足,系统保留当前 financialStatus,不会自动修改。
6.4 当前计算顺序
6.5 计算示例
假设商机总金额为 100 元:
| 已开票 | 审核通过回款 | 是否有逾期计划 | 当前计算结果 | 原因 |
|---|---|---|---|---|
| 0 | 0 | 否 | 未开票,未收款 | 没有有效款票 |
| 0 | 0 | 是 | 付款逾期 | 逾期优先于默认状态 |
| 30 | 0 | 否 | 部分款票 | 部分开票优先进入“部分款票” |
| 100 | 0 | 否 | 已开票,未收款 | 开票已达到商机总金额且无回款 |
| 0 | 30 | 否 | 部分款票 | 部分回款优先进入“部分款票” |
| 0 | 100 | 否 | 未开票,已收款 | 回款已达到商机总金额且无发票 |
| 30 | 30 | 否 | 款票完成 | 当前规则只要求回款金额不小于开票金额 |
| 100 | 50 | 否 | 部分款票 | 回款小于开票金额 |
| 50 | 100 | 是 | 款票完成 | 款票完成的判断优先于逾期 |
重要口径:当前“款票完成”并不要求开票金额或回款金额达到商机总金额,只要求二者都大于 0,且回款金额不小于开票金额。因此“开票 30、回款 30、商机金额 100”也会被判定为款票完成。
6.6 人工修改财务状态
商机详情页提供财务状态下拉框。有 crm:business:financial 权限并具备商机写权限的人员,可以把财务状态直接改为任意合法枚举值。
人工修改:
- 不校验实际发票金额、回款金额和逾期计划;
- 修改为“款票完成”时,也会执行提成资格判断;
- 后续再次触发自动重算或执行批量重算任务时,可能被实际数据覆盖。
七、订单状态
7.1 状态定义
| 状态值 | 状态名称 | 自动触发来源 |
|---|---|---|
1 | 立项 | 关联 TVP 项目创建时,原状态必须是“未成单” |
2 | 未成单 | 新建商机默认值 |
10 | 测试中 | 当前没有项目事件自动写入,仅可人工修改或由其他外部调用写入 |
11 | 测试完成 | TVP 项目交付阶段变为“已完成” |
12 | 交付中 | TVP 项目交付阶段进入招募中、执行中、报告中、验收中 |
20 | 完成 | 同一商机关联的全部 TVP 项目都进入“已结束” |
7.2 订单状态数据流图
7.3 自动同步限制
- 创建项目只有在商机订单状态仍为“未成单”时,才自动改为“立项”。
- 项目“开始报名”和“开始进行”事件目前只写日志,不直接改变订单状态。
- 商机订单状态一旦为“完成”,后续项目交付阶段事件不会再把它改回其他状态。
- 项目交付阶段只会自动写入“交付中”或“测试完成”,不会自动写入“测试中”。
- 人工修改接口没有固定的前后状态迁移限制,可以跨级或回退到任意合法状态。
7.4 人工修改订单状态
商机详情页提供订单状态下拉框。有 crm:business:status 权限并具备商机写权限的人员,可以直接选择任意合法状态。
当人工把订单状态改为“完成”时,系统同样会检查财务状态;如果财务状态已经是“款票完成”,会生成待提成记录。
八、提成状态
8.1 状态定义
| 状态值 | 状态名称 |
|---|---|
10 | 待提成 |
20 | 已提成 |
8.2 提成资格生成规则
8.3 最后完成条件
提成记录的 qualifiedSource 表示哪个条件最后完成:
| 值 | 含义 |
|---|---|
ORDER_STATUS | 财务状态已经完成,本次订单状态变为完成 |
FINANCIAL_STATUS | 订单状态已经完成,本次财务状态变为完成 |
HISTORY_WIN_TIME | 上线迁移时,历史商机已同时满足两个完成条件,使用历史赢单时间补建 |
8.4 提成确认
| 操作 | 前置条件 | 状态变化 | 记录内容 |
|---|---|---|---|
| 单条确认提成 | 记录存在且为待提成 | 待提成 → 已提成 | 记录确认人和确认时间 |
| 批量确认提成 | 所有传入 ID 都存在 | 所有待提成记录 → 已提成 | 已提成记录保持不变;统一记录本次确认人和时间 |
8.5 当前不可逆行为
- 没有“取消提成”或“退回待提成”接口。
- 订单状态或财务状态从完成回退后,已经生成的提成记录不会删除。
- 已提成记录不会因订单退款、发票调整、回款状态回退而自动撤销。
- 每个租户的每个商机最多只有一条提成记录,数据库唯一键为
(tenant_id, business_id)。 - 修改赢单时间不会触发新的提成资格判断。
九、端到端业务场景
场景 A:先完成订单,后完成款票
- TVP 全部关联项目结束,订单状态变为“完成”。
- 此时财务状态未完成,不生成提成。
- 正式发票上传,或者回款审批通过,触发财务状态重算。
- 财务状态变为“款票完成”。
- 系统发现订单已完成,创建“待提成”,
qualifiedSource = FINANCIAL_STATUS。 - 有确认权限的人员点击“确认提成”,状态变为“已提成”。
场景 B:先完成款票,后完成订单
- 财务状态先变为“款票完成”。
- 此时订单未完成,不生成提成。
- 后续全部 TVP 项目结束,或人工把订单状态改为“完成”。
- 系统发现财务已经完成,创建“待提成”,
qualifiedSource = ORDER_STATUS。
场景 C:人工直接完成
- 有权限的人员人工把财务状态改为“款票完成”,无需真实发票或审核通过回款。
- 再人工把订单状态改为“完成”。
- 系统会生成待提成记录。
这说明当前提成资格依赖的是两个状态字段,不会再次校验款票原始数据和项目实际完成数据。
场景 D:完成后回退
- 订单和财务都完成,系统生成待提成记录。
- 后续人工把订单改回“交付中”,或者把回款审批状态改回非通过导致财务状态重算回退。
- 已生成的待提成或已提成记录仍然保留。
十、当前实现与业务确认项
以下内容是代码当前行为,建议业务负责人明确是否符合管理规则:
| 编号 | 当前行为 | 需要确认的问题 |
|---|---|---|
| 1 | 回款创建后直接是“审批中”,但 BPM 发起和审批结果监听已停用 | 回款审批是否计划走人工改状态,还是需要恢复正式工作流? |
| 2 | “提交回款审批”目前不会创建流程或改变状态 | 页面是否应隐藏该操作,或恢复提交逻辑? |
| 3 | 更新回款审批状态接口没有前置状态限制,也没有枚举校验 | 是否允许从任意状态直接改为审核通过、驳回、取消或回退? |
| 4 | 款票完成只要求回款金额不小于开票金额,不要求达到商机总金额 | 提成资格应按已开票部分收齐,还是必须整单金额全部开票并收齐? |
| 5 | 商机变为赢单时不会立即重算财务状态 | 是否需要赢单动作立即根据已有发票、回款和逾期计划重算? |
| 6 | 订单状态和财务状态允许人工跨级修改 | 是否需要状态机约束、审批或操作原因? |
| 7 | 提成记录生成后不会随订单、财务回退而撤销 | 是否需要“资格失效”“冻结”“撤销提成”等状态? |
| 8 | TVP 项目事件不会自动产生“测试中”状态 | “测试中”应由哪个项目动作触发? |
| 9 | 财务批量重算只有任务处理器,代码仓库内未发现固定调度初始化 | 生产环境是否已配置执行周期和告警? |
十一、业务操作速查
| 业务动作 | 直接改变的状态 | 可能间接改变的状态 |
|---|---|---|
| 新建商机 | 订单状态 = 未成单;财务状态 = 未开票未收款 | 无 |
| 商机改为赢单 | 商机结束状态 = 赢单;写入赢单时间 | 不会立即重算财务状态 |
| 创建 TVP 项目 | 订单状态可能变为立项 | 若不是未成单则不变 |
| 更新项目交付阶段 | 订单状态可能变为交付中或测试完成 | 订单变为完成时才可能生成提成 |
| 所有关联项目结束 | 订单状态 = 完成 | 财务已完成时生成待提成 |
| 人工修改订单状态 | 订单状态 = 选定值 | 改为完成时可能生成待提成 |
| 创建发票申请 | 发票状态 = 待申请 | 无 |
| 提交发票申请 | 发票状态 = 待审核 | 创建审核待办和通知 |
| 驳回发票 | 发票状态 = 已驳回 | 无 |
| 审核通过但不上传 | 发票状态 = 待上传 | 创建上传待办,不重算财务 |
| 审核通过并上传 / 上传正式发票 | 发票状态 = 已开票 | 重算财务;财务完成且订单完成时生成待提成 |
| 创建回款 | 回款状态 = 审批中 | 重算财务,但该金额尚不计入 |
| 回款改为审核通过 | 回款状态 = 审核通过 | 金额计入已收款并重算财务;可能生成待提成 |
| 回款改为非通过状态 | 回款状态 = 指定状态 | 已收款金额减少并重算财务,但不会撤销已有提成 |
| 人工修改财务状态 | 财务状态 = 选定值 | 改为款票完成且订单完成时生成待提成 |
| 确认提成 | 提成状态 = 已提成 | 记录确认人、确认时间 |
十二、代码实现位置
| 规则 | 主要实现 |
|---|---|
| 发票状态机 | CrmOrderInvoiceServiceImpl、CrmOrderInvoiceStatusEnum |
| 回款状态与审批入口 | CrmReceivableServiceImpl、CrmReceivableController、CrmAuditStatusEnum |
| 已开票金额汇总 | CrmOrderInvoiceMapper.selectInvoicedAmountByOrderId |
| 审核通过回款汇总 | CrmReceivableMapper.selectApprovedAmountByOrderId |
| 财务状态重算 | CrmBusinessServiceImpl.recalculateFinancialStatus、calculateFinancialStatus |
| 订单状态人工修改 | CrmBusinessController.updateOrderStatus、CrmBusinessServiceImpl.changeOrderStatus |
| TVP 项目同步订单状态 | CrmProjectStatusConsumer |
| 提成资格与确认 | CrmBusinessCommissionServiceImpl、CrmBusinessCommissionMapper |
| 财务状态批量重算 | CrmBusinessFinancialStatusJob |