feat: 财务看板口径重构与半年模拟数据及报销状态注册表
- 重构 finance_dashboard 口径计算,新增模拟公司画像数据生成与筛选 - 引入 expense_claim_status_registry 统一报销状态流转 - 完善报销草稿流程、Item Sync 与本体解析器 - 优化总览页趋势图、分页组件与请求进度步骤 - 增强报销申请快速预览、本体工具与详情展示 - 新增半年报销模拟数据种子脚本与状态审计工具 - 补充财务看板、报销状态注册与模拟数据测试覆盖
This commit is contained in:
@@ -209,7 +209,8 @@ def test_user_agent_application_context_uses_application_language() -> None:
|
||||
|
||||
assert "费用申请" in response.answer
|
||||
assert "| 字段 | 内容 |" in response.answer
|
||||
assert "| 行程时间 | 2026-05-25 至 2026-05-27 |" in response.answer
|
||||
assert "| 出发时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 返回时间 | 2026-05-27 |" in response.answer
|
||||
assert "支持上海国网服务器部署" in response.answer
|
||||
assert "当前还需要补充:出行方式" in response.answer
|
||||
assert "请先在下面选择报销场景" not in response.answer
|
||||
@@ -224,7 +225,8 @@ def test_user_agent_application_infers_natural_reason_and_expands_single_date()
|
||||
with session_factory() as db:
|
||||
response = build_application_user_agent_response(db, message)
|
||||
|
||||
assert "| 行程时间 | 2026-05-25 至 2026-05-27 |" in response.answer
|
||||
assert "| 出发时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 返回时间 | 2026-05-27 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑上海国网服务器部署 |" in response.answer
|
||||
assert "当前还需要先补充:申请事由" not in response.answer
|
||||
@@ -250,7 +252,8 @@ def test_user_agent_application_normalizes_location_to_region_city() -> None:
|
||||
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-27 |" in yili_response.answer
|
||||
assert "| 出发时间 | 2026-05-25 |" in yili_response.answer
|
||||
assert "| 返回时间 | 2026-05-27 |" in yili_response.answer
|
||||
assert "| 地点 | 新疆,伊犁 |" in yili_response.answer
|
||||
assert "| 事由 | 支撑新疆电力仿生产部署 |" in yili_response.answer
|
||||
assert "伊犁出差" not in yili_response.answer
|
||||
@@ -289,7 +292,8 @@ def test_user_agent_application_uses_selected_time_and_natural_language_fields()
|
||||
)
|
||||
)
|
||||
|
||||
assert "| 行程时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 出发时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 返回时间 | 2026-05-25 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑国网服务器上线部署 |" in response.answer
|
||||
assert "当前还需要补充:出行方式" in response.answer
|
||||
@@ -317,10 +321,10 @@ def test_user_agent_application_builds_system_estimate_after_transport_choice()
|
||||
assert "| 出行方式 | 飞机 |" in response.answer
|
||||
assert "| 系统预估费用 |" in response.answer
|
||||
assert "交通" in response.answer
|
||||
assert "参考票价" in response.answer
|
||||
assert "按 2026-05-25 参考票价" in response.answer
|
||||
assert "| 交通费用口径 | 预估交通费用 2,330元 |" in response.answer
|
||||
assert "2,330元" in response.answer
|
||||
assert "查询耗时" in response.answer
|
||||
assert "参考票价" not in response.answer
|
||||
assert "查询耗时" not in response.answer
|
||||
assert response.requires_confirmation is True
|
||||
assert response.suggested_actions == []
|
||||
|
||||
@@ -362,14 +366,64 @@ def test_user_agent_application_uses_selected_date_range_and_keeps_reason() -> N
|
||||
)
|
||||
)
|
||||
|
||||
assert "| 行程时间 | 2026-02-20 至 2026-02-23 |" in response.answer
|
||||
assert "| 出发时间 | 2026-02-20 |" in response.answer
|
||||
assert "| 返回时间 | 2026-02-23 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑国网仿生产环境部署 |" in response.answer
|
||||
assert "| 天数 | 4天 |" in response.answer
|
||||
assert "| 住宿上限/天 | 450元/天 |" in response.answer
|
||||
assert "| 补贴标准/天 | 100元/天 |" in response.answer
|
||||
assert "| 规则测算参考 | 交通 2,460元 + 住宿 1,800元 + 补贴 400元 = 4,660元(4天) |" in response.answer
|
||||
assert "| 发生时间 |" not in response.answer
|
||||
assert "| 事由 | 2026-02-20 至 2026-02-23 |" not in response.answer
|
||||
|
||||
|
||||
def test_user_agent_application_keeps_labeled_reason_in_structured_travel_form() -> None:
|
||||
session_factory = build_session_factory()
|
||||
message = (
|
||||
"发生时间:2026-02-20 至 2026-02-23\n"
|
||||
"地点:上海\n"
|
||||
"事由:支撑国网仿生产环境建设\n"
|
||||
"天数:4天"
|
||||
)
|
||||
context_json = {
|
||||
"session_type": "application",
|
||||
"entry_source": "application",
|
||||
"name": "曹笑竹",
|
||||
"department_name": "技术部",
|
||||
"position": "财务智能化产品经理",
|
||||
"manager_name": "向万红",
|
||||
"grade": "P5",
|
||||
}
|
||||
with session_factory() as db:
|
||||
ontology = SemanticOntologyService(db).parse(
|
||||
OntologyParseRequest(
|
||||
query=message,
|
||||
user_id="pytest-structured-application-reason@example.com",
|
||||
context_json=context_json,
|
||||
)
|
||||
)
|
||||
response = UserAgentService(db).respond(
|
||||
UserAgentRequest(
|
||||
run_id=ontology.run_id,
|
||||
user_id="pytest-structured-application-reason@example.com",
|
||||
message=message,
|
||||
ontology=ontology,
|
||||
context_json=context_json,
|
||||
tool_payload={"clarification_required": ontology.clarification_required},
|
||||
)
|
||||
)
|
||||
|
||||
assert "| 申请类型 | 差旅费用申请 |" in response.answer
|
||||
assert "| 出发时间 | 2026-02-20 |" in response.answer
|
||||
assert "| 返回时间 | 2026-02-23 |" in response.answer
|
||||
assert "| 地点 | 上海市 |" in response.answer
|
||||
assert "| 事由 | 支撑国网仿生产环境建设 |" in response.answer
|
||||
assert "| 天数 | 4天 |" in response.answer
|
||||
assert "申请事由" not in response.answer
|
||||
assert "当前还需要补充:出行方式" in response.answer
|
||||
|
||||
|
||||
def test_user_agent_application_derives_days_from_selected_date_range() -> None:
|
||||
session_factory = build_session_factory()
|
||||
message = "去上海出差,支撑国网仿生产服务器部署,火车"
|
||||
@@ -418,7 +472,8 @@ def test_user_agent_application_derives_days_from_selected_date_range() -> None:
|
||||
)
|
||||
)
|
||||
|
||||
assert "| 行程时间 | 2026-02-20 至 2026-02-23 |" in response.answer
|
||||
assert "| 出发时间 | 2026-02-20 |" in response.answer
|
||||
assert "| 返回时间 | 2026-02-23 |" in response.answer
|
||||
assert "| 天数 | 4天 |" in response.answer
|
||||
assert "| 天数 | 待补充 |" not in response.answer
|
||||
assert "(4天)" in response.answer
|
||||
@@ -452,7 +507,8 @@ def test_user_agent_application_precomputes_time_from_today_and_days() -> None:
|
||||
)
|
||||
|
||||
assert "这是费用申请核对结果" in response.answer
|
||||
assert "| 行程时间 | 2026-05-29 至 2026-05-31 |" in response.answer
|
||||
assert "| 出发时间 | 2026-05-29 |" in response.answer
|
||||
assert "| 返回时间 | 2026-05-31 |" in response.answer
|
||||
assert response.requires_confirmation is True
|
||||
|
||||
|
||||
@@ -547,7 +603,8 @@ def test_user_agent_application_submit_enters_leader_review() -> None:
|
||||
"| 字段 | 内容 |\n"
|
||||
"| --- | --- |\n"
|
||||
"| 申请类型 | 差旅费用申请 |\n"
|
||||
"| 行程时间 | 2026-05-25 |\n"
|
||||
"| 出发时间 | 2026-05-25 |\n"
|
||||
"| 返回时间 | 2026-05-27 |\n"
|
||||
"| 地点 | 上海市 |\n"
|
||||
"| 事由 | 支持上海国网服务器部署 |\n"
|
||||
"| 天数 | 3天 |\n"
|
||||
@@ -585,7 +642,8 @@ def test_user_agent_application_submit_enters_leader_review() -> None:
|
||||
def test_user_agent_application_submit_blocks_duplicate_business_time() -> None:
|
||||
session_factory = build_session_factory()
|
||||
initial_message = (
|
||||
"行程时间:2026-05-25 至 2026-05-27\n"
|
||||
"出发时间:2026-05-25\n"
|
||||
"返回时间:2026-05-27\n"
|
||||
"地点:上海\n"
|
||||
"事由:支持上海国网服务器部署\n"
|
||||
"天数:3天\n"
|
||||
@@ -597,7 +655,8 @@ def test_user_agent_application_submit_blocks_duplicate_business_time() -> None:
|
||||
"| 字段 | 内容 |\n"
|
||||
"| --- | --- |\n"
|
||||
"| 申请类型 | 差旅费用申请 |\n"
|
||||
"| 行程时间 | 2026-05-25 至 2026-05-27 |\n"
|
||||
"| 出发时间 | 2026-05-25 |\n"
|
||||
"| 返回时间 | 2026-05-27 |\n"
|
||||
"| 地点 | 上海市 |\n"
|
||||
"| 事由 | 支持上海国网服务器部署 |\n"
|
||||
"| 天数 | 3天 |\n"
|
||||
@@ -1385,6 +1444,7 @@ def test_user_agent_uses_linked_application_context_for_review_slots() -> None:
|
||||
"application_location": "北京",
|
||||
"application_amount": "3000元",
|
||||
"application_business_time": "2026-06-01 至 2026-06-03",
|
||||
"application_transport_mode": "火车",
|
||||
},
|
||||
"user_input_text": message,
|
||||
}
|
||||
@@ -1412,6 +1472,15 @@ def test_user_agent_uses_linked_application_context_for_review_slots() -> None:
|
||||
assert slot_map["location"].value == "北京"
|
||||
assert slot_map["amount"].value == "3000.00元"
|
||||
assert slot_map["time_range"].value == "2026-06-01 至 2026-06-03"
|
||||
assert UserAgentService._resolve_review_form_values(
|
||||
UserAgentRequest(
|
||||
run_id=ontology.run_id,
|
||||
user_id="pytest-linked-application-review@example.com",
|
||||
message=message,
|
||||
ontology=ontology,
|
||||
context_json=context_json,
|
||||
)
|
||||
)["transport_mode"] == "火车"
|
||||
assert "事由说明" not in response.review_payload.missing_slots
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user