feat: 本体字段治理与风险规则模板执行器重构
- 新增本体字段注册表与字段治理审计脚本 - 重构风险规则模板执行器、DSL 验证与清单分类器 - 完善票据夹服务与差旅请求详情页交互 - 优化趋势图表与总览页数据展示 - 增强报销平台风险分级与模拟公司筛选 - 补充本体字段、风险规则生成与票据夹服务测试覆盖
This commit is contained in:
78
document/development/ontology-field-governance/CONCEPT.md
Normal file
78
document/development/ontology-field-governance/CONCEPT.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 本体字段治理
|
||||
|
||||
## 背景
|
||||
|
||||
当前费用申请、报销助手、单据详情、风险规则和预算控制中存在字段口径不一致的问题。例如同一语义在不同环节被命名为 `transport_type`、`transport_mode`、`application_transport_mode`,或 `occurred_date`、`business_time`、`time_range`。这些字段如果不先进入本体层,会导致语义识别、规则判断、草稿保存和前端展示各自解释同一业务事实。
|
||||
|
||||
## 原则
|
||||
|
||||
所有业务字段必须先设计为本体字段,再下放到业务模块使用。
|
||||
|
||||
- 本体字段注册表是唯一字段源。
|
||||
- 业务层只允许消费本体 canonical 字段。
|
||||
- 非本体字段只能作为输入别名,必须在语义入口归一。
|
||||
- 页面控件字段、兼容字段、后端历史字段不能直接进入业务判断。
|
||||
- 新增业务字段时,必须先更新本体字段设计,再更新表单、助手上下文、持久化、风险规则和测试。
|
||||
|
||||
## 当前第一阶段范围
|
||||
|
||||
第一阶段先治理费用申请和报销链路:
|
||||
|
||||
- 个人工作台意图识别。
|
||||
- 费用申请预览和提交。
|
||||
- 报销助手快速发起报销。
|
||||
- 关联申请单生成报销草稿。
|
||||
- 报销详情智能录入和附件归集。
|
||||
- AI 预审、风险规则、审批流和预算流。
|
||||
|
||||
## 字段分层
|
||||
|
||||
本体 canonical 字段:
|
||||
|
||||
- `expense_type`
|
||||
- `time_range`
|
||||
- `location`
|
||||
- `reason`
|
||||
- `amount`
|
||||
- `transport_mode`
|
||||
- `attachments`
|
||||
- `customer_name`
|
||||
- `merchant_name`
|
||||
- `participants`
|
||||
- `application_claim_id`
|
||||
- `application_claim_no`
|
||||
- `application_days`
|
||||
- `application_date`
|
||||
- `application_lodging_daily_cap`
|
||||
- `application_subsidy_daily_cap`
|
||||
- `application_transport_policy`
|
||||
- `application_policy_estimate`
|
||||
|
||||
输入兼容别名:
|
||||
|
||||
- `transport_type`、`transportMode`、`application_transport_mode` -> `transport_mode`
|
||||
- `occurred_date`、`business_time`、`application_business_time` -> `time_range`
|
||||
- `business_location`、`application_location` -> `location`
|
||||
- `reason_value`、`business_reason`、`application_reason` -> `reason`
|
||||
- `attachment_names` -> `attachments`
|
||||
- `reimbursement_type`、`scene_label` -> `expense_type`
|
||||
|
||||
## 非合规判断
|
||||
|
||||
以下情况视为字段不合规:
|
||||
|
||||
- 新业务流程直接新增 `context_json` 字段但没有进入本体注册表。
|
||||
- 风险规则读取未注册字段。
|
||||
- 前端 `review_form_values` 输出页面控件字段。
|
||||
- 后端服务用别名字段做业务判断,而不是先归一成本体字段。
|
||||
- 同一业务事实在申请、报销、审批、预算中使用不同字段名。
|
||||
|
||||
## 验收口径
|
||||
|
||||
完成后应满足:
|
||||
|
||||
- 语义层能从上下文中生成统一本体实体。
|
||||
- 报销助手关联申请单后不再因为字段别名丢失追问出行方式。
|
||||
- `review_form_values` 对外输出本体字段,不输出页面别名字段。
|
||||
- 后端测试覆盖别名归一到本体字段。
|
||||
- 前端测试覆盖快速报销和核对抽屉只输出本体字段。
|
||||
@@ -0,0 +1,40 @@
|
||||
# 本体字段纠察记录
|
||||
|
||||
## 纠察口径
|
||||
|
||||
所有会参与意图识别、申请/报销草稿、费用明细、风险规则、审批或预算判断的字段,必须先进入本体字段注册表。
|
||||
|
||||
字段分为三类:
|
||||
|
||||
- 本体业务字段:可被业务逻辑、规则、页面表单直接消费。
|
||||
- 输入兼容别名:只允许在语义入口归一,不允许在业务判断中继续直接读取。
|
||||
- 上下文元数据:只表达会话、上传、编辑态、权限和执行链路,不作为业务事实。
|
||||
|
||||
## 已注册的业务字段
|
||||
|
||||
- 费用事实:`expense_type`、`time_range`、`location`、`reason`、`amount`、`transport_mode`、`attachments`
|
||||
- 对象事实:`customer_name`、`merchant_name`、`participants`
|
||||
- 员工事实:`employee_name`、`employee_no`、`department_name`、`employee_position`、`employee_grade`、`manager_name`
|
||||
- 预算事实:`budget_period`、`budget_subject`、`budget_amount`、`cost_center`、`warning_threshold`、`control_action`
|
||||
- 申请关联事实:`application_claim_id`、`application_claim_no`、`application_days`、`application_date`、`application_policy_estimate`
|
||||
|
||||
## 已登记为元数据的字段
|
||||
|
||||
- 会话与流程:`conversation_id`、`conversation_history`、`conversation_scenario`、`conversation_intent`、`session_type`、`entry_source`
|
||||
- 编辑与动作:`review_action`、`draft_claim_id`、`application_edit_mode`、`application_edit_claim_id`
|
||||
- 上传与 OCR:`attachment_count`、`attachment_names`、`ocr_documents`、`ocr_summary`、`review_document_form_values`
|
||||
- 客户端运行态:`client_now_iso`、`client_timezone_offset_minutes`
|
||||
- 权限与调试:`role_codes`、`is_admin`、`simulate_tool_failure`、`simulate_orchestrator_exception`
|
||||
|
||||
## 当前审计结论
|
||||
|
||||
- 未注册字段:已清零。
|
||||
- 历史别名直接读取:主要集中在员工上下文顶层字段,例如 `name`、`grade`、`department`、`position`。
|
||||
- 第一轮已把申请/报销关键链路的表单字段统一到 `expense_type`、`time_range`、`location`、`reason`、`amount`、`transport_mode`。
|
||||
|
||||
## 后续清理策略
|
||||
|
||||
1. 新增业务字段前,先更新 `ontology_field_registry.py`。
|
||||
2. 旧字段只作为输入别名保留,入口归一到 canonical 字段。
|
||||
3. 业务模块逐步停止直接读取旧别名。
|
||||
4. 使用 `server/scripts/audit_ontology_context_fields.py --strict` 作为收口质量闸。
|
||||
15
document/development/ontology-field-governance/TODO.md
Normal file
15
document/development/ontology-field-governance/TODO.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# 本体字段治理 TODO
|
||||
|
||||
- [x] 建立本体字段注册表,集中维护 canonical 字段和输入别名。[CONCEPT: 字段分层]
|
||||
- [x] 在语义解析入口归一 `context_json.review_form_values`。[CONCEPT: 原则]
|
||||
- [x] 在本体实体抽取中把上下文字段桥接为 `transport_mode`、`reason`、`location` 等实体。[CONCEPT: 当前第一阶段范围]
|
||||
- [x] 报销助手 review 入口复用本体字段注册表,不再自己维护字段别名。[CONCEPT: 原则]
|
||||
- [x] 快速报销关联申请单上下文去除 `business_time`、`business_location`、`reason_value`、`reimbursement_type` 等非本体输出字段。[CONCEPT: 非合规判断]
|
||||
- [x] 核对抽屉提交上下文归一为本体字段。[CONCEPT: 验收口径]
|
||||
- [x] 补充本体层和前端字段归一回归测试。[CONCEPT: 验收口径]
|
||||
- [ ] 清查申请助手字段:`application_preview`、`application_fields`、`business_time_context` 是否都已归一本体。
|
||||
- [ ] 清查报销详情字段:智能录入、附件归集、费用明细、异常说明是否仍有非本体字段直传。
|
||||
- [ ] 清查风险规则字段:规则中心、Hermes 归一字段、OCR pipeline 字段是否有未注册业务字段。
|
||||
- [ ] 清查预算字段:预算控制、预算复核、预算操作上下文是否全部使用本体字段。
|
||||
- [ ] 清查审批字段:审批意见、退回原因、流程节点字段是否需要纳入本体或定义为流程元数据。
|
||||
- [ ] 增加字段合规扫描脚本,对新增 `review_form_values` / `context_json` 字段进行检查。
|
||||
@@ -236,3 +236,31 @@ $$
|
||||
- 本轮采用文件元数据而非数据库,适合先完成闭环;后续若需要审计、权限、跨用户协作和全文检索,应升级到资产表。
|
||||
- 已关联状态如何自动回写,需要在后续把票据夹 ID 与报销明细 `invoice_id` 建立更强绑定。
|
||||
- 多票据关联时,如果用户中途取消对话,本轮仍保留为未关联,避免误标。
|
||||
|
||||
## 2026-06-03 详情页与上传治理补充
|
||||
|
||||
本轮根据新的验收要求收敛为三块核心内容:
|
||||
|
||||
- 左侧为票据预览,使用共享详情页主区域承载,图片和 PDF 都以完整票据可见为优先目标,不再提供“打开源文件”按钮。
|
||||
- 右侧为识别票据详情,展示当前票据所有 OCR 字段和基础字段;用户点击“编辑”后可直接修改识别内容,保存后写回票据夹元数据。
|
||||
- 底部为关联信息;左侧预览卡底部同时展示用户编辑操作记录,用于后续财务判断人工修改痕迹。
|
||||
|
||||
编辑记录治理:
|
||||
|
||||
- `PATCH /receipt-folder/{receipt_id}` 在保存前后对可编辑票据信息做字段级 diff。
|
||||
- 每条编辑日志记录操作者、操作时间、字段名称、修改前值、修改后值。
|
||||
- 前端详情页只展示真实 `edit_logs`,不再用模拟操作日志替代。
|
||||
|
||||
重复上传治理:
|
||||
|
||||
- OCR 持久化票据时计算源文件 `sha256`。
|
||||
- 同一用户再次上传相同源文件时,不新建票据目录,返回已有 `receipt_id`,并在 OCR 文档 warnings 中提示“已上传过同样的单据,请不要重复上传。”
|
||||
|
||||
报销助手联动:
|
||||
|
||||
- 用户在报销助手上传新附件前,如果票据夹中存在未关联票据,先提示用户是否进入票据夹关联。
|
||||
- 用户可以选择“去票据夹关联”,也可以选择“继续上传新附件”;继续上传时只跳过本次未关联提醒,不影响后续重复附件校验。
|
||||
|
||||
删除级联:
|
||||
|
||||
- 已关联票据对应的报销单被删除时,票据夹中关联该报销单的票据源文件、预览文件和元数据一并删除。
|
||||
|
||||
@@ -99,3 +99,16 @@
|
||||
|
||||
- [x] 更新本 TODO 的完成状态和验证记录。[CONCEPT: 测试方案]
|
||||
证据:本文件已补充完成勾选和验证命令记录。
|
||||
|
||||
## 阶段八:2026-06-03 详情页与上传治理收口
|
||||
|
||||
- [x] 将票据夹详情页收敛为共享详情布局下的三块内容:左侧完整预览、右侧识别票据详情、底部关联信息。[CONCEPT: 2026-06-03 详情页与上传治理补充]
|
||||
证据:`node web/tests/receipt-folder-view.test.mjs`、`npm.cmd run build`、容器内 `cd /app/web && npm run build` 均通过。
|
||||
- [x] 支持识别票据详情编辑,并在后端保存字段级编辑日志。[CONCEPT: 编辑记录治理]
|
||||
证据:容器内 `pytest -q server/tests/test_ocr_endpoints.py server/tests/test_receipt_folder_service.py` 通过,3 passed。
|
||||
- [x] OCR 持久化时识别同一用户重复上传的相同源文件,返回已有票据并提示不要重复上传。[CONCEPT: 重复上传治理]
|
||||
证据:`test_ocr_endpoints.py` 已覆盖重复上传返回原 `receipt_id` 和 warnings。
|
||||
- [x] 报销助手上传附件前提示票据夹中存在未关联票据,并提供进入票据夹关联或继续上传的建议动作。[CONCEPT: 报销助手联动]
|
||||
证据:`receipt-folder-view.test.mjs` 覆盖 `fetchReceiptFolderItems('unlinked')`、`open_receipt_folder` 和 `continue_upload_with_unlinked_receipts`。
|
||||
- [x] 删除已关联报销单时,同步删除票据夹中关联该报销单的票据文件。[CONCEPT: 删除级联]
|
||||
证据:`test_receipt_folder_service.py` 已覆盖 `delete_receipts_for_claim` 删除后不可再读取票据。
|
||||
|
||||
Reference in New Issue
Block a user