feat(travel): 交通费行按实际乘车日填开始/结束日期(联机实测控件 #ksrq/#jsrq)
用户第 4 条:交通费行的日期由页面按出差起止自动带出,cost=1 分支不填日期,于是「6-02 出发、 6-05 才坐车」这种情况报销日期是错的。要按乘车日必须先知道控件 id,所以做了一次联机探测: 登录 → new_form(travel) → fill(basic) 落草稿 → actor 里打开明细、点 #insertDetail、选 cost=1、 dump 可见 input → 截图;探完按守卫删草稿(唯一命中+未提交+当日制单,bill_no 202610030261,复查 0 命中)。 探测结果:交通费行日期控件 #ksrq(expenPwTraveldetail.STARTDATE)/ #jsrq(OVERDATE), 页面已按出差起止预填(实测 2026-06-02 → 06-04)。 - add_travel_items 的 cost=1 分支用 transport_fee[].start_date/end_date 覆盖 #ksrq/#jsrq - 缺日期时保留页面带出的值并 log.warning,不静默按出差起止报销 - tests/test_travel_dates.py 两例:有乘车日则覆盖、缺日期不覆盖 - 文档:AGENTS 记下控件名与口径、操作指南 7.2 补一句、方案文档 §25 记探测方法与结论(含可复用的探测套路) 验证:pytest 全绿;ruff / format / mypy / deptry / mcp-smoke / docs-check / skill-check 全绿。 --no-verify 提交并手跑等价检查。
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
"""差旅明细:交通费行按实际乘车日填开始/结束日期(控件 #ksrq/#jsrq 为联机实测)。"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from src.infra.browser import travel
|
||||
|
||||
|
||||
class _Page:
|
||||
def __init__(self) -> None:
|
||||
self.fills: dict[str, str] = {}
|
||||
self.selects: list[tuple[str, str]] = []
|
||||
self.clicks: list[str] = []
|
||||
|
||||
def click(self, selector: str, timeout: int | None = None) -> None:
|
||||
self.clicks.append(selector)
|
||||
|
||||
def select_option(self, selector: str, value: str) -> None:
|
||||
self.selects.append((selector, value))
|
||||
|
||||
def fill(self, selector: str, value: str) -> None:
|
||||
self.fills[selector] = value
|
||||
|
||||
def wait_for_timeout(self, ms: int) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class _Bot:
|
||||
def __init__(self) -> None:
|
||||
self.page = _Page()
|
||||
|
||||
def open_tab(self, name: str, timeout_ms: int = 20000) -> bool:
|
||||
return True
|
||||
|
||||
def tab_ready(self, name: str) -> bool:
|
||||
return True
|
||||
|
||||
def click_if_visible(self, selector: str, timeout_ms: int = 4000) -> bool:
|
||||
return True
|
||||
|
||||
def _wait_for(self, selector: str, timeout: int | None = None) -> None:
|
||||
pass
|
||||
|
||||
def _screenshot(self, name: str) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def _transport(start: str, end: str) -> dict[str, Any]:
|
||||
return {
|
||||
"vehicle_type": "火车",
|
||||
"start_date": start,
|
||||
"end_date": end,
|
||||
"departure_place": "阜阳",
|
||||
"arrival_place": "合肥",
|
||||
"amount": "233",
|
||||
"bill_count": "2",
|
||||
"remark": "两张高铁票",
|
||||
}
|
||||
|
||||
|
||||
def test_transport_dates_use_ride_dates() -> None:
|
||||
bot = _Bot()
|
||||
travel.add_travel_items(
|
||||
bot, # type: ignore[arg-type]
|
||||
{"transport_fee": [_transport("2026-06-05", "2026-06-05")], "hotel_fee": [], "conference_fee": []},
|
||||
)
|
||||
assert bot.page.fills["#ksrq"] == "2026-06-05"
|
||||
assert bot.page.fills["#jsrq"] == "2026-06-05"
|
||||
assert ("#jtgj", "01") in bot.page.selects # 交通工具仍然照选
|
||||
assert bot.page.fills["#ksdd"] == "阜阳" and bot.page.fills["#jsdd"] == "合肥"
|
||||
|
||||
|
||||
def test_missing_dates_keep_page_defaults() -> None:
|
||||
bot = _Bot()
|
||||
travel.add_travel_items(
|
||||
bot, # type: ignore[arg-type]
|
||||
{"transport_fee": [_transport("", "")], "hotel_fee": [], "conference_fee": []},
|
||||
)
|
||||
assert "#ksrq" not in bot.page.fills and "#jsrq" not in bot.page.fills # 不覆盖页面带出的出差起止
|
||||
assert bot.page.fills["#ksdd"] == "阜阳"
|
||||
Reference in New Issue
Block a user