feat: 增强风险规则生成引擎与预算中心页面
后端拆分风险规则生成为解释器、语义分析、本体对齐等子模块, 优化模板执行和流程图生成,完善员工种子数据和导入逻辑,增强 报销单权限策略和草稿持久化,前端新增预算中心视图和趋势图 组件,重构审计页面和风险规则测试对话框交互,完善文档中心 和报销创建页面细节,补充单元测试覆盖。
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -208,11 +209,11 @@ def test_user_agent_application_context_uses_application_language() -> None:
|
||||
assert "| 字段 | 内容 |" in response.answer
|
||||
assert "| 发生时间 | 2026-05-25 至 2026-05-28 |" in response.answer
|
||||
assert "支持上海国网服务器部署" in response.answer
|
||||
assert "当前还需要补充:出行方式、预计金额/预算" in response.answer
|
||||
assert "当前还需要补充:出行方式、用户预估费用" in response.answer
|
||||
assert "请先在下面选择报销场景" not in response.answer
|
||||
assert response.review_payload is None
|
||||
assert [item.label for item in response.suggested_actions] == ["一次性补充申请信息"]
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "出行方式:\n预计总费用:"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "出行方式:\n用户预估费用:"
|
||||
|
||||
|
||||
def test_user_agent_application_infers_natural_reason_and_expands_single_date() -> None:
|
||||
@@ -222,13 +223,38 @@ def test_user_agent_application_infers_natural_reason_and_expands_single_date()
|
||||
response = build_application_user_agent_response(db, message)
|
||||
|
||||
assert "| 发生时间 | 2026-05-25 至 2026-05-28 |" in response.answer
|
||||
assert "| 地点 | 上海 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑上海国网服务器部署 |" in response.answer
|
||||
assert "当前还需要先补充:申请事由" not in response.answer
|
||||
assert "当前还需要补充:出行方式、预计金额/预算" in response.answer
|
||||
assert "当前还需要补充:出行方式、用户预估费用" in response.answer
|
||||
assert [item.label for item in response.suggested_actions] == ["一次性补充申请信息"]
|
||||
|
||||
|
||||
def test_user_agent_application_normalizes_location_to_region_city() -> None:
|
||||
session_factory = build_session_factory()
|
||||
yili_message = (
|
||||
"发生时间:2026-05-25\n"
|
||||
"地点:伊犁\n"
|
||||
"事由:支撑新疆电力仿生产部署\n"
|
||||
"天数:3天"
|
||||
)
|
||||
beijing_message = (
|
||||
"发生时间:2026-05-25\n"
|
||||
"地点:北京\n"
|
||||
"事由:支撑总部系统部署\n"
|
||||
"天数:3天"
|
||||
)
|
||||
with session_factory() as db:
|
||||
yili_response = build_application_user_agent_response(db, yili_message)
|
||||
beijing_response = build_application_user_agent_response(db, beijing_message)
|
||||
|
||||
assert "| 发生时间 | 2026-05-25 至 2026-05-28 |" in yili_response.answer
|
||||
assert "| 地点 | 新疆,伊犁 |" in yili_response.answer
|
||||
assert "| 事由 | 支撑新疆电力仿生产部署 |" in yili_response.answer
|
||||
assert "伊犁出差" not in yili_response.answer
|
||||
assert "| 地点 | 北京市 |" in beijing_response.answer
|
||||
|
||||
|
||||
def test_user_agent_application_uses_selected_time_and_natural_language_fields() -> None:
|
||||
session_factory = build_session_factory()
|
||||
message = "出差上海,支撑国网服务器上线部署"
|
||||
@@ -262,12 +288,12 @@ def test_user_agent_application_uses_selected_time_and_natural_language_fields()
|
||||
)
|
||||
|
||||
assert "| 发生时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 地点 | 上海 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑国网服务器上线部署 |" in response.answer
|
||||
assert "当前还需要补充:出行方式、预计金额/预算" in response.answer
|
||||
assert "当前还需要补充:出行方式、用户预估费用" in response.answer
|
||||
assert [item.label for item in response.suggested_actions] == ["一次性补充申请信息"]
|
||||
assert response.suggested_actions[0].action_type == "prefill_composer"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "出行方式:\n预计总费用:"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "出行方式:\n用户预估费用:"
|
||||
|
||||
|
||||
def test_user_agent_application_asks_amount_after_transport_choice() -> None:
|
||||
@@ -286,10 +312,10 @@ def test_user_agent_application_asks_amount_after_transport_choice() -> None:
|
||||
)
|
||||
|
||||
assert "| 出行方式 | 飞机 |" in response.answer
|
||||
assert "当前还需要补充:预计金额/预算" in response.answer
|
||||
assert "当前还需要补充:用户预估费用" in response.answer
|
||||
assert [item.label for item in response.suggested_actions] == ["一次性补充申请信息"]
|
||||
assert response.suggested_actions[0].action_type == "prefill_composer"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "预计总费用:"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "用户预估费用:"
|
||||
|
||||
|
||||
def test_user_agent_application_missing_base_actions_prefill_composer() -> None:
|
||||
@@ -300,10 +326,10 @@ def test_user_agent_application_missing_base_actions_prefill_composer() -> None:
|
||||
"地点:上海\n事由:支撑国网服务器部署\n天数:3天",
|
||||
)
|
||||
|
||||
assert "当前还需要补充:发生时间、出行方式、预计金额/预算" in response.answer
|
||||
assert "当前还需要补充:发生时间、出行方式、用户预估费用" in response.answer
|
||||
assert [item.label for item in response.suggested_actions] == ["一次性补充申请信息"]
|
||||
assert response.suggested_actions[0].action_type == "prefill_composer"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "申请时间段:\n出行方式:\n预计总费用:"
|
||||
assert response.suggested_actions[0].payload["prompt_prefill"] == "申请时间段:\n出行方式:\n用户预估费用:"
|
||||
|
||||
|
||||
def test_user_agent_application_builds_preview_when_amount_is_ready() -> None:
|
||||
@@ -328,7 +354,7 @@ def test_user_agent_application_builds_preview_when_amount_is_ready() -> None:
|
||||
assert "| 字段 | 内容 |" in response.answer
|
||||
assert "| 事由 | 支持上海国网服务器部署 |" in response.answer
|
||||
assert "| 出行方式 | 飞机 |" in response.answer
|
||||
assert "| 预计总费用 | 12000元 |" in response.answer
|
||||
assert "| 用户预估费用 | 12000元 |" in response.answer
|
||||
assert "请核对上述信息无误" in response.answer
|
||||
assert "[确认](#application-submit)" in response.answer
|
||||
assert response.requires_confirmation is True
|
||||
@@ -349,11 +375,11 @@ def test_user_agent_application_submit_enters_leader_review() -> None:
|
||||
"| --- | --- |\n"
|
||||
"| 申请类型 | 差旅费用申请 |\n"
|
||||
"| 发生时间 | 2026-05-25 |\n"
|
||||
"| 地点 | 上海 |\n"
|
||||
"| 地点 | 上海市 |\n"
|
||||
"| 事由 | 支持上海国网服务器部署 |\n"
|
||||
"| 天数 | 3天 |\n"
|
||||
"| 出行方式 | 飞机 |\n"
|
||||
"| 预计总费用 | 12000元 |\n\n"
|
||||
"| 用户预估费用 | 12000元 |\n\n"
|
||||
"请核对上述信息无误,确认无误后 [确认](#application-submit) 提交至审批流程。"
|
||||
)
|
||||
with session_factory() as db:
|
||||
@@ -372,9 +398,9 @@ def test_user_agent_application_submit_enters_leader_review() -> None:
|
||||
assert "当前操作已完成,单据已经推送给 陈硕 进行审核,请耐心等待" in response.answer
|
||||
assert "当前状态:陈硕审核中" in response.answer
|
||||
assert "预算占用参考" in response.answer
|
||||
assert "APP-20260525-" in response.answer
|
||||
assert re.search(r"AP-\d{14}-[A-HJ-NP-Z2-9]{8}", response.answer)
|
||||
assert response.suggested_actions == []
|
||||
claim = db.query(ExpenseClaim).filter(ExpenseClaim.claim_no.like("APP-20260525-%")).one()
|
||||
claim = db.query(ExpenseClaim).filter(ExpenseClaim.claim_no.like("AP-%")).one()
|
||||
assert claim.status == "submitted"
|
||||
assert claim.approval_stage == "直属领导审批"
|
||||
assert claim.expense_type == "travel_application"
|
||||
|
||||
Reference in New Issue
Block a user