feat: 报销审批流重构与管家计划全链路贯通

- 重构报销状态注册表、审批流路由与平台风险标记
- 完善管家意图规划器与模型计划构建器全链路
- 新增 OCR Worker 脚本、数据库会话管理与通知状态
- 优化文档中心、日志视图、预算中心与员工管理交互
- 增强工作台摘要、图标资源与全局主题样式
- 补充审批路由、状态注册、OCR 服务与管家规划器测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-06 17:19:07 +08:00
parent f60cebadb8
commit e124e4bbcb
162 changed files with 9161 additions and 1941 deletions

View File

@@ -1,5 +1,11 @@
# 财务规则表补齐开发记录
## 2026-06-05 口径调整
用户明确要求业务招待费超过 500 元、大额办公用品以及金额超过 2000 元的费用申请审批要求进入财务规则中心。因此新增《公司费用申请审批规则》作为申请前置和审批阈值的财务规则依据;风险规则负责引用该财务规则并执行命中判断。
本次调整不恢复旧的单项《业务招待费报销规则》或《办公用品费报销规则》,而是使用统一规则表维护申请审批阈值,避免规则中心再次出现多个口径型规则表。
## 目标
财务规则中心只维护真正具备制度标准、且需要按职级/职务或明确人均标准执行的规则表。没有实际金额分档的费用类型,不在财务规则中心单独生成 Excel 表;其额度控制进入预算中心,申请前置和材料完整性进入风险规则。

View File

@@ -1,5 +1,9 @@
# 风险规则补齐开发记录
## 2026-06-05 口径调整
业务招待费超过 500 元、办公用品超过 2000 元、通用费用超过 2000 元的申请前置要求,制度依据统一改为财务规则《公司费用申请审批规则》。风险规则继续承担执行判断,但 `finance_rule_code` 统一指向 `expense.preapproval.policy`
## 目标
补齐预算、申请前置、报销偏差、费用标准、材料完整性类风险规则,让后续 demo 数据可以形成“预算-申请-报销-风控”的闭环。

View File

@@ -150,6 +150,27 @@
- 申请任务完成后,再把剩余报销任务作为后续任务引导到报销助手。
- 附件归集不作为第一屏主动作抢占申请流程;当进入报销任务时,相关附件随报销上下文带入。
小财管家必须维护运行时任务上下文,而不是把每次用户输入都当成新的独立意图。上下文至少包含:
- 当前任务:正在处理的申请或报销任务。
- 剩余任务:已拆解但尚未处理的任务队列。
- 已完成任务:已经形成申请单、报销草稿、附件归集或提交动作的任务。
- 等待动作:当前正在等待用户补字段、确认核对表、确认提交审批或继续下一项。
- 最近结构化结果:当前申请核对表、报销核对结果、附件归集建议等。
用户输入“确认”“无误”“可以提交”等文本时,小财管家必须先匹配当前等待动作;如果当前等待的是申请单提交确认,就提交当前申请单;如果当前等待的是继续下一项,就进入剩余任务队列中的下一项;如果当前核对表仍有缺字段,则提示补字段。只有没有可匹配上下文时,才重新进入任务规划。
上述匹配不应主要依赖前端关键词规则。第一版应新增“小财管家运行时决策智能体”,由后端 function calling 接收 `runtime_state` 和用户当前输入,返回结构化 `next_action`
- `submit_current_application`:确认当前申请核对表并提交至审批。
- `continue_next_task`:当前任务已完成,继续剩余任务队列中的下一项。
- `fill_current_slot`:用户补充了当前等待字段。
- `ask_user`:当前信息不足,需要继续追问。
- `plan_new_tasks`:当前没有可匹配上下文,重新进入任务规划。
- `cancel_current_action` / `no_op`:取消或不执行当前动作。
前端只执行模型返回的结构化动作,并做安全校验:例如申请核对表必须 `readyToSubmit` 才能提交,已提交消息必须标记避免重复提交,缺字段时必须追问。本地规则只允许作为模型失败后的保守兜底,不作为主判断来源。
可以自动执行的动作:
- 任务拆解。
@@ -161,7 +182,7 @@
### 4. 流式过程摘要
前端展示的是“意图识别智能体”的过程摘要,不是模型内部推理链;过程摘要必须独立于最终回复正文展示。
前端展示的是“意图识别智能体”的过程摘要,不是模型内部推理链;过程摘要必须独立于最终回复正文展示。过程摘要必须围绕业务理解展开,例如用户说了什么、被拆成哪些申请/报销任务、已识别哪些业务要素、还缺少哪些关键条件、为什么需要向用户追问。不能只展示“接收确认、协调能力、准备输出”等系统执行日志。
示例:
@@ -188,7 +209,7 @@
计划完成后的最终正文也必须流式输出。前端不能把完整正文一次性替换到消息气泡里,而应进入 `typing` 状态按字符逐步追加正文;正文输出完成后,再把状态改为“等待用户确认”并展示确认按钮。
用户确认当前步骤后,小财管家隐式委派给申请能力或报销能力时,也必须保持同一套流式体验:先在系统气泡上方的小财管家思考折叠气泡中逐字展示“接收确认、协调能力、等待结果”等过程摘要;拿到申请核对表或报销核对结果后,再逐字输出正文。结构化表格、核对卡片、确认按钮可以在正文输出完成后一次性展示,但正文不能一次性替换进消息气泡。
用户确认当前步骤后,小财管家隐式委派给申请能力或报销能力时,也必须保持同一套流式体验:先在系统气泡上方的小财管家思考折叠气泡中逐字展示当前业务任务、已识别信息、待补充条件和下一步动作;拿到申请核对表或报销核对结果后,再逐字输出正文。结构化表格、核对卡片、确认按钮可以在正文输出完成后一次性展示,但正文不能一次性替换进消息气泡。
小财管家委派期间不得打开右侧单助手执行流程面板,也不得把“申请助手 / 报销助手”的执行步骤显示成独立助手思考框。用户可见身份保持“小财管家”,具体调用哪个能力只作为小财管家自己的过程摘要,不切换为“财务助手”或单独助手会话。
@@ -208,6 +229,12 @@
后续步骤如果需要展示“还需要补充”,必须是结构化列表,每个待补充项独立成行,包含字段业务名称和填写说明;不得把多个待补充项拼接成一行连续文本。
当后续步骤发现关键条件缺失时,小财管家不能只展示“模型复核不稳定”或“下方表格待补充”。它必须把缺口转成下一轮对话问题,并优先给出可直接选择的业务选项。例如差旅申请缺少 `transport_mode` 时,用户界面展示为“请问你打算怎么出行?火车、飞机或轮船”,不得先展示申请核对表,也不得默认补成火车;用户选择后再生成申请核对表、写回出行方式、重新测算费用,并继续判断是否可以提交申请。这是“思考 -> 行动 -> 再思考 -> 再行动”循环的一部分。
用户补齐关键字段也不是终态动作。以“出行方式”为例,用户选择火车后,小财管家必须先进入下一轮业务思考,基于已识别的时间、地点、事由和出行方式模拟查询交通票据或票价口径,完成系统预估金额测算,再流式输出正文并展示申请核对表;不能在用户点击选项后直接把旧核对表补字段后闪现出来。
费用申请核对表阶段不得把系统档案字段或非阻塞归档字段当作用户待补充项。`employee_no``employee_name``department_name` 应从当前登录用户档案和组织上下文读取;`attachments` 在差旅申请阶段不阻塞核对表生成,可在后续报销、归档或审批材料补充阶段处理;`amount` 在申请阶段由系统规则估算。字段决策模型即使返回这些字段为缺失,服务端也必须过滤,不能向用户展示“附件/凭证和员工编号为合规必需字段”这类错误追问。
任务卡片和正文不得直接暴露本体字段名,例如 `transport_mode``amount``attachments`。本体字段只允许作为内部结构化数据进入后端、助手委派和持久化链路;用户界面必须翻译为业务中文,并提供可理解的填写说明:
- `transport_mode` 展示为“出行方式”,说明可填写高铁、飞机、自驾、出租车等。
@@ -311,6 +338,13 @@
规则置信度评分仅用于模型不可用或模型返回结构不可用时的兜底路径。
任务拆解之后还需要第二层“任务字段决策智能体”。这一步不能由前端关键词或固定 required 字段直接决定而要把当前任务类型、用户原话、上游任务拆解结果、canonical ontology fields、已抽取字段、缺失字段、附件和申请/报销上下文交给模型,通过 function calling 返回下一步动作:
- `ask_user`:当前信息不足,必须先把缺口转成业务问题和可选项。
- `render_preview`:当前信息足够生成可核对结果,但提交、入库、绑定附件前仍需用户确认。
字段决策规则只能作为模型不可用或结构化结果非法时的兜底,兜底结果必须标记为 `rule_fallback`,不能伪装成智能体判断。字段名必须来自 ontology registryUI 只展示中文业务名称,不展示 canonical 字段名。
任务置信度:
$$

View File

@@ -44,6 +44,14 @@
- [x] 支持小财管家隐藏委派申请/报销能力,执行后保留小财管家会话并继续引导剩余任务。[CONCEPT: 执行流] 证据:`sessionTypeOverride``stewardContinuation` 已接入前端提交流程。
- [x] 支持小财管家确认后的隐式委派继续流式输出,正文完成后再展示申请核对表、报销核对卡片和确认按钮。[CONCEPT: 流式过程摘要] 证据:`useTravelReimbursementSubmitComposer.js` 新增 `typeStewardDelegatedMessage`,申请预览与 orchestrator 结果均先流式思考、再逐字正文、最后挂载结构化 payload`npm.cmd --prefix web run build` 成功。
- [x] 小财管家委派申请/报销能力期间不打开右侧单助手执行流程面板,用户可见身份保持“小财管家”。[CONCEPT: 流式过程摘要] 证据:`stewardDelegated` 分支跳过 flow step 与 review panel scope并在最终消息设置 `assistantName: '小财管家'``stewardPlanModel.js` 助手标签兜底不再显示“财务助手”。
- [x] 小财管家在后续步骤发现关键缺口时,主动转成可回答的问题和选项,而不是只展示待补充表格。[CONCEPT: 用户可见结果展示] 证据:`useTravelReimbursementSubmitComposer.js` 在申请核对缺少“出行方式”时只输出主动追问和火车/飞机/轮船选项,不提前挂载 `applicationPreview``stewardPlanModel.js` 的内部 `carry_text` 不再把“高铁、飞机”等示例写进缺字段提示,避免本地抽取误当成用户已选择;`TravelReimbursementCreateView.js` 在用户选择后不再直接补旧表格,而是重新进入小财管家的委派流;`web/tests/expense-application-fast-preview.test.mjs` 覆盖该回归。
- [x] 用户补齐出行方式后,小财管家必须先思考、模拟查询票据和测算金额,再展示申请核对表。[CONCEPT: 用户可见结果展示] 证据:`stewardFieldCompletionModel.js` 将补齐字段后的当前任务、本体字段和旧预览重组为续跑输入;`TravelReimbursementCreateView.js``continueStewardApplicationFieldCompletion` 调用 `submitComposerInternal` 触发流式思考、申请复核和费用测算,不再调用 `commitApplicationPreviewEditor` 直接闪现表格。
- [x] 防止残留预算上下文抢占小财管家的申请续跑链路。[CONCEPT: 执行流] 证据:`budgetAssistantReportModel.js` 不再因存在 `initialBudgetContext` 就无条件进入预算编制报告;`useTravelReimbursementSubmitComposer.js``stewardDelegated` 显式跳过预算编制分支;`expense-application-fast-preview.test.mjs` 覆盖“申请续跑 + 残留预算上下文”不得进入预算编制。
- [x] 支持用户直接输入“确认/无误/可以提交”命中当前申请核对表提交动作,而不是重新规划。[CONCEPT: 用户确认] 证据:`TravelReimbursementCreateView.js` 通过 `handleStewardRuntimeDecision` 优先请求运行时决策智能体;模型返回 `submit_current_application` 后复用 `confirmApplicationSubmit`;本地 `handleApplicationSubmitConfirmationText` 仅作为模型不可用时的兜底;提交成功后标记 `applicationSubmitConfirmed`,避免后续重复提交;测试 `text confirmation submits pending application preview before replanning steward task` 覆盖该优先级。
- [x] 增加小财管家运行时决策智能体,把“确认、继续下一项、补字段、重新规划”的上下文判断迁到后端 function calling。[CONCEPT: 用户确认] 证据:`POST /steward/runtime-decisions` 调用 `StewardRuntimeDecisionAgent`,通过 `submit_steward_runtime_decision` 返回 `submit_current_application``continue_next_task``fill_current_slot``plan_new_tasks` 等动作;前端 `handleStewardRuntimeDecision` 先提交 `runtime_state`,再执行模型返回的结构化动作,本地规则仅兜底。
- [x] 增加第二层任务字段决策智能体,动态判断当前任务应追问用户还是展示核对结果。[CONCEPT: 算法与公式] 证据:`POST /steward/slot-decisions` 调用 `StewardSlotDecisionAgent`,通过 `submit_steward_slot_decision` function calling 输出 `ask_user` / `render_preview`、canonical 缺失字段、问题和选项;前端 `useTravelReimbursementSubmitComposer.js` 在小财管家委派申请时消费该决策。
- [x] 防止字段决策模型把申请阶段非阻塞字段误判为用户必填项。[CONCEPT: 用户可见结果展示] 证据:`StewardSlotDecisionAgent` 过滤 `amount``attachments``employee_no``department_name``employee_name`,模型误返 `ask_user` 且过滤后无缺口时改为 `render_preview`;前端 `APPLICATION_NON_BLOCKING_ONTOLOGY_FIELDS` 同步过滤兜底缺口和选项;测试覆盖附件/员工编号误判。
- [x] 小财管家思考气泡必须体现业务意图和关键缺口,不能退化为系统执行日志。[CONCEPT: 流式过程摘要] 证据:`steward_planner.py` 将差旅申请缺少“出行方式”纳入计划缺口并追加业务缺口思考事件;`useTravelReimbursementSubmitComposer.js``TravelReimbursementCreateView.js` 的确认后思考改为读取任务摘要、已识别信息和待补充项。
- [x] 确认申请任务后,将任务摘要分派到现有申请助手会话。[CONCEPT: 执行流] 证据:确认动作携带 `session_type=application``auto_submit=true`
- [x] 确认报销任务后,将任务摘要和附件带入现有报销助手会话。[CONCEPT: 执行流] 证据:确认动作携带 `session_type=expense``carry_files=true``auto_submit=true`
- [x] 附件归集建议确认后,将选中附件作为报销助手上下文继续处理。[CONCEPT: 附件归集] 证据:附件归集确认动作携带归集附件名称和排除附件名称。

View File

@@ -0,0 +1,88 @@
# 申请单关联归档状态概念文档
## 功能一句话
申请单审批完成后先进入关联单据状态,只有关联的报销单完成付款归档后,申请单才同步归档。
## 背景与问题
当前费用申请单审批完成后,部分列表和进度展示会把申请单视为归档;但业务上申请单只是完成了事前审批,还需要等待后续报销单关联、报销审批、付款完成后,申请单生命周期才真正闭环。
这会导致用户看到报销单仍在处理、申请单却已归档,或者报销单已完成但申请单还停留在进行中的割裂状态。
## 目标
1. 申请单审批完成不直接进入归档中心。
2. 申请单进度在归档前增加“关联单据状态”节点。
3. 已有关联报销单但未付款完成时,该节点显示“关联中”。
4. 没有关联报销单时,该节点显示“未关联”。
5. 关联报销单付款完成后,申请单同步进入“申请归档”。
## 非目标
1. 不新增数据库表。
2. 不改变报销单本身的审批、付款权限。
3. 不改变申请单审批通过自动生成报销草稿的现有能力。
## 用户与场景
涉及角色:
- 申请人:查看申请单是否已经关联后续报销单。
- 审批人:审批申请单后不再误以为该申请已经归档。
- 财务人员:付款完成报销单时,同步闭环关联申请单。
关键场景:
1. 申请单审批通过,但未生成或未关联报销单:显示“关联单据状态 / 未关联”。
2. 申请单审批通过,并已生成报销草稿或报销单仍在流程中:显示“关联单据状态 / 关联中”。
3. 关联报销单已付款:报销单进入已付款,申请单进入“申请归档”。
## 方案设计
后端:
- 申请单 `approved + 审批完成` 不再被归档查询命中。
- 申请单只有 `approved + 申请归档` 才属于归档。
- 报销单付款完成时,从 `application_handoff``application_link` 风险事件中读取关联申请单。
- 找到关联申请单后,追加同步归档事件,并将申请单阶段置为“申请归档”。
前端:
- 申请单进度增加“关联单据状态”和“已归档”节点。
- 审批完成但未归档的申请单,当前节点停留在“关联单据状态”。
- 根据申请单自身的 `generated_draft_claim_no` 或报销单侧关联事件显示“关联中 / 未关联”。
- 只有“申请归档”阶段才展示归档完成。
## 算法与公式
当前功能不涉及显式数学公式。
关联状态判断:
```text
has_linked_reimbursement = exists(application.generated_draft_claim_no)
or exists(reimbursement.risk_flags.application_claim_id/no == application.id/no)
application_archived = application.status in {approved, completed}
and application.approval_stage == "申请归档"
```
## 测试方案
1. 后端状态测试:审批完成申请单不归档,申请归档才归档。
2. 后端付款测试:关联报销单付款后,申请单同步进入“申请归档”。
3. 前端进度测试:审批完成申请单显示“关联单据状态”和“已归档”。
4. 前端归档判断测试:`审批完成` 申请单不算归档,`申请归档` 才算归档。
## 验收标准
1. 单据中心普通视图仍能看到审批完成但未归档的申请单。
2. 归档中心不会提前出现仅审批完成的申请单。
3. 申请单进度在审批完成后能看到“关联单据状态”。
4. 报销单付款完成后,关联申请单同步显示为归档。
## 风险与开放问题
- 旧数据中可能存在已经把申请单审批完成当作归档的数据,本次按新业务规则修正展示与查询口径。
- 如果历史申请单缺少关联报销事件,只能展示“未关联”,不做自动猜测。

View File

@@ -0,0 +1,8 @@
# 申请单关联归档状态开发 TODO
- [x] 梳理申请单审批完成、报销单关联、报销单付款、归档查询的现有链路。[CONCEPT: 背景与问题] 证据:已确认 `expense_claim_status_registry.py``expense_claim_access_policy.py``expense_claim_approval_flow.py``useRequests.js` 的当前行为。
- [x] 调整后端归档查询口径:申请单 `审批完成` 不再视为归档,仅 `申请归档` 才归档。[CONCEPT: 方案设计] 证据:`ExpenseClaimAccessPolicy.build_archived_claim_condition()` 仅将 `APPLICATION_ARCHIVE_STAGE` 视为申请归档。
- [x] 调整报销单付款完成逻辑:根据关联事件同步推进申请单到 `申请归档`。[CONCEPT: 方案设计] 证据:`mark_claim_paid()` 调用 `_archive_linked_applications_after_reimbursement_paid()`,新增付款同步测试通过。
- [x] 调整前端申请单进度:增加 `关联单据状态``已归档` 节点,并显示 `关联中/未关联`。[CONCEPT: 方案设计] 证据:`useRequests.js` 新增申请单进度节点和关联状态计算。
- [x] 补充前后端回归测试,覆盖未关联、关联中、已归档三类申请单状态。[CONCEPT: 测试方案] 证据:`requestProgressSteps.test.mjs``document-center-archived-scope.test.mjs``expense-claim-archive.test.mjs``test_expense_claim_service.py` 已覆盖。
- [x] 在容器或前端定向测试中完成验证,并记录命令结果。[CONCEPT: 验收标准] 证据:前端 Node 定向测试、容器内 py_compile、状态/路由/归档/付款同步 pytest、`npm.cmd --prefix web run build` 均通过。

View File

@@ -0,0 +1,131 @@
# 费用申请审批财务规则概念文档
## 功能一句话
在财务规则中心新增《公司费用申请审批规则》,统一维护业务招待、办公用品和通用大额费用的事前申请与审批阈值,并让报销风险规则引用该规则执行。
## 背景与问题
现有系统已经有“业务招待无申请”“办公采购无申请”“大额费用无申请”等风险规则,但制度依据主要以风险规则 JSON 的口径字段存在,财务规则中心缺少一张可被制度管理员查看、编辑和追溯的规则表。
用户明确要求:
- 业务招待费超过 500 元需要申请。
- 大额办公用品需要申请。
- 金额超过 2000 元的费用都需要走审批。
- 这些要求最好形成财务规则,而不是散落在代码或前端提示中。
## 目标与非目标
目标:
- 新增一张财务规则资产《公司费用申请审批规则》。
- 规则资产以 Excel 形式进入 `finance-rules` 规则库,并在规则中心按“财务规则”展示。
- 风险规则引用统一的 `finance_rule_code`,不再使用零散口径 code。
- 报销阶段按结构化金额规则判断,而不是只靠关键词命中。
- 关联有效申请单后不触发“缺少申请”风险。
非目标:
- 本轮不新增数据库字段。
- 本轮不新增非本体业务字段。
- 本轮不改造完整审批流节点,只补充申请前置与风险执行依据。
## 用户与场景
- 报销人:上传或录入业务招待、办公用品、大额费用报销时,系统自动识别是否缺少事前申请。
- 直属领导和财务审核人:审核单据时能看到风险来自财务规则。
- 财务制度管理员:能在规则中心看到并维护《公司费用申请审批规则》。
## 功能能力
### 财务规则表
规则表包含以下行:
- 业务招待费:单次费用金额大于 500 元时,必须先提交费用申请单。
- 办公用品费:单次或批量采购金额大于 2000 元时,必须先提交办公采购或费用申请单。
- 通用大额费用:任意费用金额大于 2000 元时,必须进入审批流程。
### 风险规则执行
- `meal``entertainment` 都视为业务招待费。
- `office` 视为办公用品费。
- `all` 视为通用大额费用。
- 报销阶段没有关联有效申请单时,超过阈值命中高风险。
- 已有关联申请单时,不命中缺少申请风险。
## 方案设计
### 后端
-`agent_asset_spreadsheet.py` 中新增费用申请审批规则 code 与文件名常量。
- 在财务规则同步中新增该资产的 metadata、Excel 工作簿生成和版本快照。
- 在初始化和补齐逻辑中创建该财务规则资产,确保老库和新库都能看到。
- 将三条风险规则改为 `composite_rule_v1`,使用金额阈值和申请单存在性执行。
-`risk_rule_template_executor.py` 中补齐 `application.*` 字段解析,桥接现有 `application_link` / `application_handoff` / `application_detail` 风险上下文。
### 前端
本轮不新增前端页面。规则中心已有财务规则和 JSON 风险规则展示能力,后端资产同步后前端可直接展示。
### 数据与本体
本轮只使用现有本体字段:
- `expense_type`
- `amount`
- `reason`
- `application_claim_id`
- `application_claim_no`
- `application_detail`
不新增非本体字段。
## 算法与公式
业务招待费规则:
$$
hit = expenseType \in \{meal, entertainment\} \land amount > 500 \land \neg hasApplication
$$
办公用品规则:
$$
hit = expenseType = office \land amount > 2000 \land \neg hasApplication
$$
通用大额规则:
$$
hit = amount > 2000 \land \neg hasApplication
$$
其中:
- `amount` 来自 `claim.amount`
- `hasApplication` 来自 `application.id``application.claim_no` 或等价申请单上下文。
## 测试方案
- 单元测试:验证 `application.*` 字段能从已有申请关联上下文解析。
- 规则执行测试:超过 500 元业务招待费且无申请命中风险。
- 规则执行测试:超过 2000 元办公用品费且无申请命中风险。
- 规则执行测试:超过 2000 元通用费用且无申请命中风险。
- 规则执行测试:已关联申请单的超额费用不命中缺少申请风险。
- 资产测试:规则中心种子数据包含《公司费用申请审批规则》,且 `config_json.tag` 为“财务规则”。
## 指标与验收
- 财务规则中心能看到新增规则资产。
- 新增资产 `finance_rule_code` 统一为 `expense.preapproval.policy`
- 三条风险规则均引用该财务规则 code。
- 容器内后端定向测试通过。
- 不新增非本体业务字段。
## 风险与开放问题
- “大额办公用品”的金额阈值按用户同句“大额/超过 2000 都需要审批”落为 2000 元。
- 当前申请单上下文主要存在 `risk_flags_json` 的申请关联 flag 中,本轮先补执行器解析,不新增外键字段。
- 后续如果要支持不同部门或不同职级阈值,可以在同一张财务规则表中扩展分档行。

View File

@@ -0,0 +1,23 @@
# 费用申请审批财务规则 TODO
## 调研与契约
- [x] 盘点现有财务规则资产、风险规则 JSON 与规则同步链路。[CONCEPT: 背景与问题] 证据:确认现有 `finance-rules` 仅差旅和通信两张核心规则表,前置申请规则当前在 `risk-rules` 中。
- [x] 明确本轮不新增非本体业务字段。[CONCEPT: 数据与本体] 证据:规则只使用 `expense_type``amount``reason` 和申请单上下文。
## 后端实现
- [x] 新增《公司费用申请审批规则》财务规则资产常量与 Excel 工作簿内容。[CONCEPT: 财务规则表] 证据:`COMPANY_PREAPPROVAL_RULE_CODE``COMPANY_PREAPPROVAL_RULE_FILENAME``_ensure_company_preapproval_rule_spreadsheet_seed()` 已实现。
- [x] 初始化种子和老库补齐逻辑都能创建该财务规则资产。[CONCEPT: 方案设计] 证据:`agent_foundation_asset_seed.py``agent_foundation_asset_topup.py` 均接入该资产。
- [x] 将大额费用、业务招待、办公用品三条前置申请风险规则改为结构化金额判断。[CONCEPT: 风险规则执行] 证据:三条 `risk.application.*without_preapproval.json` 已改为 `composite_rule_v1`
- [x] 补齐 `application.*` 字段解析,支持从现有关联申请上下文判断是否已有申请。[CONCEPT: 后端] 证据:`risk_rule_template_executor.py` 新增 `_resolve_application_values()`
## 测试与验证
- [x] 新增执行器测试:申请单上下文存在时 `application.id` 可解析。[CONCEPT: 测试方案] 证据:`test_application_context_values_are_available_to_composite_rules` 通过。
- [x] 新增风险规则执行测试:业务招待费超过 500 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 meal。
- [x] 新增风险规则执行测试:办公用品超过 2000 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 office。
- [x] 新增风险规则执行测试:通用费用超过 2000 元且无申请命中。[CONCEPT: 测试方案] 证据:`test_preapproval_amount_rules_hit_without_linked_application` 覆盖 software。
- [x] 新增资产同步测试:财务规则中心包含新增规则资产。[CONCEPT: 指标与验收] 证据:`test_finance_rules_use_risk_rule_scenario_categories` 断言新增财务规则资产和规则文档。
- [x] Docker `x-financial-main` 容器内定向测试通过。[CONCEPT: 指标与验收] 证据:新增与相邻回归共 15 个后端测试通过。
- [x] 重启后端并验证运行时健康状态。[CONCEPT: 指标与验收] 证据:`x-financial-main` 已重启并进入 healthy真实库可查到 `rule.expense.company_preapproval_requirement`