173 lines
6.0 KiB
Python
173 lines
6.0 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from types import SimpleNamespace
|
||
|
|
|
||
|
|
from app.schemas.steward import StewardActionExecuteRequest, StewardTask
|
||
|
|
from app.services.steward_query_executors import (
|
||
|
|
build_travel_standard_query_steps,
|
||
|
|
execute_travel_standard_query,
|
||
|
|
resolve_travel_standard_snapshot,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _build_current_user(grade: str = "P5") -> SimpleNamespace:
|
||
|
|
return SimpleNamespace(
|
||
|
|
username="test_user",
|
||
|
|
name="测试员工",
|
||
|
|
grade=grade,
|
||
|
|
department_name="技术部",
|
||
|
|
position="工程师",
|
||
|
|
role_codes=["employee"],
|
||
|
|
is_admin=False,
|
||
|
|
employee_no="E00001",
|
||
|
|
manager_name="李总",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _build_request(
|
||
|
|
*,
|
||
|
|
location: str = "武汉",
|
||
|
|
employee_grade: str = "",
|
||
|
|
standard_category: str = "",
|
||
|
|
message: str = "我去武汉出差的住宿标准是多少",
|
||
|
|
) -> StewardActionExecuteRequest:
|
||
|
|
ontology_fields: dict[str, str] = {}
|
||
|
|
if location:
|
||
|
|
ontology_fields["location"] = location
|
||
|
|
if employee_grade:
|
||
|
|
ontology_fields["employee_grade"] = employee_grade
|
||
|
|
if standard_category:
|
||
|
|
ontology_fields["standard_category"] = standard_category
|
||
|
|
task = StewardTask(
|
||
|
|
task_id="task_query_001",
|
||
|
|
task_type="query_travel_standard",
|
||
|
|
assigned_agent="policy_query_assistant",
|
||
|
|
title="差旅标准查询",
|
||
|
|
summary=message,
|
||
|
|
ontology_fields=ontology_fields,
|
||
|
|
)
|
||
|
|
return StewardActionExecuteRequest(
|
||
|
|
action_type="execute_travel_standard_query",
|
||
|
|
message=message,
|
||
|
|
task=task,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_resolve_travel_standard_snapshot_returns_lodging_and_transport_for_known_city_and_grade():
|
||
|
|
snapshot = resolve_travel_standard_snapshot(
|
||
|
|
location="武汉",
|
||
|
|
employee_grade="P5",
|
||
|
|
)
|
||
|
|
assert snapshot["location"] == "武汉"
|
||
|
|
assert snapshot["city_tier"] == "tier_2" # 武汉是二类城市
|
||
|
|
assert snapshot["employee_grade"] == "P5"
|
||
|
|
assert snapshot["lodging"] is not None
|
||
|
|
assert snapshot["lodging"]["daily_cap"] == "480.00" # P5 + tier_2
|
||
|
|
assert snapshot["transport"] is not None
|
||
|
|
assert snapshot["transport"]["flight_level"] == 1
|
||
|
|
assert snapshot["matched_any"] is True
|
||
|
|
|
||
|
|
|
||
|
|
def test_resolve_travel_standard_snapshot_filters_by_standard_category():
|
||
|
|
lodging_only = resolve_travel_standard_snapshot(
|
||
|
|
location="北京",
|
||
|
|
employee_grade="P7",
|
||
|
|
standard_category="lodging",
|
||
|
|
)
|
||
|
|
assert lodging_only["lodging"] is not None
|
||
|
|
assert lodging_only["lodging"]["daily_cap"] == "900.00" # P7 + tier_1
|
||
|
|
assert lodging_only["transport"] is None
|
||
|
|
|
||
|
|
transport_only = resolve_travel_standard_snapshot(
|
||
|
|
location="北京",
|
||
|
|
employee_grade="P7",
|
||
|
|
standard_category="transport",
|
||
|
|
)
|
||
|
|
assert transport_only["transport"] is not None
|
||
|
|
assert transport_only["transport"]["flight_level"] == 3 # P7 飞机等级
|
||
|
|
assert transport_only["lodging"] is None
|
||
|
|
|
||
|
|
|
||
|
|
def test_resolve_travel_standard_snapshot_normalizes_grade_variants():
|
||
|
|
# "p5" 小写、未标准化写法应被归一为 "P5"
|
||
|
|
snapshot = resolve_travel_standard_snapshot(
|
||
|
|
location="武汉",
|
||
|
|
employee_grade="p5",
|
||
|
|
)
|
||
|
|
assert snapshot["employee_grade"] == "P5"
|
||
|
|
assert snapshot["lodging"]["daily_cap"] == "480.00"
|
||
|
|
|
||
|
|
|
||
|
|
def test_resolve_travel_standard_snapshot_handles_unknown_grade():
|
||
|
|
snapshot = resolve_travel_standard_snapshot(
|
||
|
|
location="武汉",
|
||
|
|
employee_grade="",
|
||
|
|
)
|
||
|
|
# 无职级时无法匹配住宿标准(需要职级档位);补助为占位说明,不计入 matched_any
|
||
|
|
assert snapshot["lodging"] is None
|
||
|
|
assert snapshot["matched_any"] is False
|
||
|
|
assert snapshot["allowance"] is not None # 仍返回占位说明
|
||
|
|
|
||
|
|
|
||
|
|
def test_execute_travel_standard_query_returns_succeeded_with_answer_markdown():
|
||
|
|
request = _build_request(location="武汉", employee_grade="P5")
|
||
|
|
response = execute_travel_standard_query(
|
||
|
|
executor=None,
|
||
|
|
request=request,
|
||
|
|
current_user=_build_current_user("P5"),
|
||
|
|
trace=[],
|
||
|
|
)
|
||
|
|
assert response.status == "succeeded"
|
||
|
|
assert response.action_type == "execute_travel_standard_query"
|
||
|
|
assert "差旅标准查询结果" in response.message
|
||
|
|
assert "480.00" in response.message # 住宿标准
|
||
|
|
assert response.result_payload["matched"] is True
|
||
|
|
assert response.result_payload["standards"]["lodging"]["daily_cap"] == "480.00"
|
||
|
|
|
||
|
|
|
||
|
|
def test_execute_travel_standard_query_falls_back_to_current_user_grade_when_field_missing():
|
||
|
|
request = _build_request(location="武汉", employee_grade="")
|
||
|
|
response = execute_travel_standard_query(
|
||
|
|
executor=None,
|
||
|
|
request=request,
|
||
|
|
current_user=_build_current_user("P5"),
|
||
|
|
trace=[],
|
||
|
|
)
|
||
|
|
assert response.status == "succeeded"
|
||
|
|
# 应回退到 current_user.grade = P5
|
||
|
|
assert response.result_payload["standards"]["employee_grade"] == "P5"
|
||
|
|
|
||
|
|
|
||
|
|
def test_execute_travel_standard_query_returns_no_match_when_grade_and_city_unknown():
|
||
|
|
request = _build_request(
|
||
|
|
location="未知城市",
|
||
|
|
employee_grade="",
|
||
|
|
message="查差旅标准",
|
||
|
|
)
|
||
|
|
# ontology_fields 也没有 grade,current_user 也没有
|
||
|
|
response = execute_travel_standard_query(
|
||
|
|
executor=None,
|
||
|
|
request=request,
|
||
|
|
current_user=_build_current_user(""),
|
||
|
|
trace=[],
|
||
|
|
)
|
||
|
|
assert response.status == "succeeded"
|
||
|
|
assert response.result_payload["matched"] is False
|
||
|
|
assert "未能匹配" in response.message
|
||
|
|
|
||
|
|
|
||
|
|
def test_build_travel_standard_query_steps_generates_single_executable_step():
|
||
|
|
task = StewardTask(
|
||
|
|
task_id="task_query_001",
|
||
|
|
task_type="query_travel_standard",
|
||
|
|
assigned_agent="policy_query_assistant",
|
||
|
|
title="差旅标准查询",
|
||
|
|
summary="查武汉住宿标准",
|
||
|
|
ontology_fields={"location": "武汉", "employee_grade": "P5"},
|
||
|
|
)
|
||
|
|
steps = build_travel_standard_query_steps(task)
|
||
|
|
assert len(steps) == 1
|
||
|
|
assert steps[0].action_type == "execute_travel_standard_query"
|
||
|
|
assert steps[0].requires_confirmation is False
|
||
|
|
assert steps[0].payload["ontology_fields"]["location"] == "武汉"
|