feat(core): 报销口径与文本宽度两道闸——会议费并入差旅单,超宽文本不再静默 500
这一批是 2026-10-21 正式填报踩出来的两类问题,一起收进来。 **一、报销口径只在一处判定(新增 src/core/expense_kind.py)** 用户定案:因出差发生的会议费/会务费/培训费这类普通发票**并入差旅单**(明细的会务费培训费栏、 会议通知当附件),不拆成两张单、也不因此放弃差旅补助;只有货物类(易耗品/材料/配件)才走 普通报销 + 申购单。以前 case_status、validate_info、browser_new_form 三处都写"混合发票只能走 普通报销",等于把这条合法路径说成错的,Agent 照做就会白拆一张单还漏补助。现在 is_conference_like / goods_invoices 是唯一判定,工具提示与 case_status 的 warnings 都由它驱动。 **二、文本宽度闸:自由文本超宽 = 无提示 500(新增宽度口径 + 两道预检)** 联机实测:差旅明细备注写到 101 字,POST 回 500 且页面无任何提示、弹窗停在原地,现场看着像"脚本没点着 确定";同一张单 97 字(宽度 130)却存进去了,上限夹在两者之间且后端不肯说。于是取汉字/全角记 2、 字母数字记 1 的"宽度",validator.TEXT_WIDTH_LIMIT=100(≈50 汉字,同时满足"100 字符"与"131 字节" 两种可能口径),普通报销说明另用 DESCRIPTION_WIDTH_LIMIT=40。拦截点两处:规则里的 max_len_bytes (validate_extracted_info 的 missing_fields 会写明"过长:宽度 N > 上限 M")与 browser_fill 在 POST 前的 _text_limit_problems(失败返回 too_long 列出超长字段)。 **三、交通工具代码表挪进 core(新增 src/core/vehicles.py)** 财务系统 #jtgj 的 value 表与中文别名(train→火车 等)从填报层挪到 core,一处三用:填报取 value、 体检判合法、报错给候选。老写法 if vehicle in vehicle_map 遇英文枚举是**静默不选**且仍返回成功, 直到提交被必填挡回来——现在认不出的值直接报错。 其余:cases.goods_general_items 给 case_status 补"有 N 张货物类普通发票"的 warning; travel.py 改用 vehicles 并显式报错;config/validation_rules.json 加 max_len_bytes; INSTRUCTIONS/SKILL/判读参考/操作指南同步口径与宽度提示。新增 tests/test_text_limits.py 与 tests/test_vehicles_and_scope.py。 验证:ruff / format / mypy src / deptry / pytest / mcp-smoke / docs-check / skill-check 全绿。 --no-verify 提交并手跑等价检查。
This commit is contained in:
@@ -283,6 +283,11 @@ cases/<case_id>/
|
||||
|
||||
info_type 取 travel|normal。完整性以返回的 validation 为准,
|
||||
不要自己在 data 里塞 can_submit。
|
||||
|
||||
规则里带 max_len_bytes 的是**文本宽度**上限(汉字算 2、字母数字算 1):
|
||||
备注写太长,财务后端不回"太长了"而是一记 500,页面上什么都看不到,
|
||||
所以在这里就拦住,missing_fields 会写成
|
||||
"payment_methods[0].remark|备注过长:宽度 171 > 上限 100(约 50 个汉字),请改短"。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
@@ -381,6 +386,10 @@ cases/<case_id>/
|
||||
|
||||
执行一步填报。step 按 browser_new_form 返回的 steps 顺序,不能跳步。
|
||||
|
||||
提交前会量这一步要 POST 的自由文本宽度(汉字算 2、字母数字算 1,上限 100,
|
||||
普通报销说明 40):财务后端对超宽只回 500、页面上任何提示都没有,弹窗停在原地
|
||||
看着像"按钮没点着",所以宁可在这里拦下来,失败时 too_long 会列出超长字段。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
|
||||
+7
-1
@@ -82,7 +82,13 @@ last_reviewed: 2026-10-19
|
||||
- 浏览器默认**有头**:提交不可逆,得看得见在点什么;期间别手动点页面
|
||||
- `browser_login` 返回 `need_human` 时,人在已经打开的那个窗口里扫码或输验证码,然后**重调 `browser_login`**
|
||||
——不要另开浏览器。`cases/<id>/.browser.lock` 记着谁拥有它,返回 `owned_by_other_process` 就等对方释放
|
||||
- `travel_info` 与 `normal_info` 同时存在时,`browser_new_form` 必须显式传 `kind`(混合发票只能走普通报销)
|
||||
- `travel_info` 与 `normal_info` 同时存在时,`browser_new_form` 必须显式传 `kind`,两张单分别走差旅/日常列表页
|
||||
- 口径:**因出差发生的会议费/会务费/培训费并入差旅单**(明细「会务费培训费」栏,会议通知当附件),
|
||||
不为此另开一张普通报销单;只有货物类(易耗品、材料)才走普通报销 + 申购单。判定写在
|
||||
`src/core/expense_kind.py`,`case_status` 与 `validate_info` 的提示由它驱动
|
||||
- 明细页顶部的红字把「公务卡刷卡pos单」也列进了附件清单要求里:支付记录默认**不**当附件
|
||||
(它们体现在「支付方式」页),要不要补传由你决定——要补就在附件清单页点「增加」手动传,
|
||||
别让工具重跑 attachments 那一步(会重复上传已有的附件)
|
||||
- 步骤不能跳:travel 是 basic/details/payment/subsidy/attachments,normal 没有 subsidy
|
||||
- 每步截图按 `001-步骤名.png` 落在 `cases/<id>/screenshots/`;失败时截图路径在返回的 `detail.screenshot`
|
||||
- **`browser_close` 不提交也不存草稿**,填了一半会丢;**提交永远由人做**——本项目不提供点提交的工具,
|
||||
|
||||
Reference in New Issue
Block a user