# 费用审批动态路由概念文档 ## 功能一句话 让费用申请和报账在直属领导审批后,按预算风险、规则风险和员工历史风险动态决定是否进入预算管理者复核。 ## 背景与问题 当前申请单默认进入预算管理者审批,报账单默认进入财务审批,审批路径偏固定。业务上更合理的方式是:预算充足、当前无风险、历史画像正常的单据减少审批层级;存在超预算、规则命中、超标或历史风险异常的单据交给预算管理者做二次确认。 ## 目标与非目标 目标: - 申请环节:低风险且预算充足时,直属领导审批后直接完成申请并生成报销草稿。 - 申请环节:超预算、预算预警、当前风险或历史风险异常时,进入预算管理者审批。 - 报账环节:低风险且预算充足时,直属领导审批后进入财务审批。 - 报账环节:超预算、超标、当前风险或历史风险异常时,先进入预算管理者审批,再进入财务审批。 - 审批记录中保留路由决策依据,便于追溯。 非目标: - 不改预算占用、释放、核销的资金动作语义。 - 不引入新的审批流配置页面。 - 不让大模型参与最终审批路由裁判。 ## 用户与场景 - 普通员工:提交费用申请或报账。 - 直属领导:确认业务必要性。 - 预算管理者:只复核有预算或风险关注项的单据。 - 财务人员:处理报账财务终审和付款前流程。 ## 功能能力 路由决策输入: - 单据基本信息:金额、费用类型、发生时间、部门、项目、申请人。 - 预算测算:预算池匹配、可用余额、预算使用率、预警阈值、超预算金额。 - 当前风险:预算标记、规则中心风险、提交预审风险、票据/附件风险、超标风险。 - 历史风险:同一员工近一段时间内的实质风险记录。 路由决策输出: - `requires_budget_review`:是否需要预算管理者复核。 - `route`:下一环节建议。 - `reasons`:触发预算复核或跳过的原因。 - `budget_result`:预算模型摘要。 - `current_risk_count`、`historical_risk_count`:当前和历史风险计数。 ## 方案设计 后端新增独立审批路由决策模块,避免在审批主流程中堆条件。 直属领导审批时: 1. 调用预算服务计算当前单据预算影响。 2. 读取当前单据风险标记,过滤审批记录等非风险事件。 3. 查询同一员工近期历史单据,统计实质风险记录。 4. 生成路由决策标记并写入 `risk_flags_json`。 5. 根据结果决定下一环节: - 申请单:预算复核或审批完成。 - 报账单:预算复核或财务审批。 预算管理者审批时: - 申请单进入审批完成,并生成报销草稿。 - 报账单进入财务审批。 ## 算法与公式 路由决策不是单一分数,而是规则化闸口: $$ requires\_budget\_review = budget\_risk \lor current\_risk \lor historical\_risk $$ 其中: - `budget_risk = rating in {block, review, caution} or risk_level in {medium, high, critical}` - `current_risk = 当前单据存在 medium/high/critical 实质风险标记` - `historical_risk = 同一员工近期存在实质风险记录` 实质风险标记排除审批通过、退回、付款、路由说明等流程记录,只保留预算、规则、AI 预审、附件、政策超标等风险来源。 ## 测试方案 - 单元测试:低风险申请跳过预算管理者并生成报销草稿。 - 单元测试:高风险报账进入预算管理者审批,预算审批后进入财务审批。 - 回归测试:原有风险规则生成、申请提交、阶段化风险规则执行继续通过。 - 容器验证:在 `x-financial-main:/app/server` 内运行定向 pytest。 ## 指标与验收 - 低风险申请不会固定进入预算管理者审批。 - 风险报账会进入预算管理者审批。 - 报账经过预算管理者审批后仍需进入财务终审。 - 每次动态路由都有可追溯的 `approval_routing` 标记。 - 预算资金动作仍由原有提交、退回、财务终审链路处理。 ## 风险与开放问题 - 历史风险的口径会影响预算管理者工作量,当前一期采用“存在实质风险即复核”的严格口径。 - 缺失预算池时是否全部进入预算复核,当前按预算风险处理。 - 后续如要支持可配置路由阈值,应新增配置表或策略服务,而不是继续改审批流分支。