Files
Auto-Finance/config/validation_rules.json
wandering 0d9cc7b4ca 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 提交并手跑等价检查。
2026-10-21 13:49:12 +08:00

164 lines
9.4 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"version": "1.1",
"custom_checks": {
"is_valid_date": "检查日期格式是否为 YYYY-MM-DD",
"is_positive_number": "检查是否为正数(整数或浮点数)",
"is_positive_integer": "检查是否为正整数",
"is_valid_vehicle": "检查交通工具能否落到财务系统的下拉框上(含 train→火车 等别名)"
},
"travel": {
"description": "差旅报销校验规则",
"fields": [
{
"path": ["basic_info", "travel_purpose"],
"required": true,
"check_empty": true,
"max_len_bytes": 100,
"description": "出差事由"
},
{
"path": ["basic_info", "travel_location"],
"required": true,
"check_empty": true,
"description": "出差地点"
},
{
"path": ["basic_info", "start_date"],
"required": true,
"check_empty": true,
"custom_check": "is_valid_date",
"description": "出差开始日期"
},
{
"path": ["basic_info", "end_date"],
"required": true,
"check_empty": true,
"custom_check": "is_valid_date",
"description": "出差结束日期"
}
],
"arrays": [
{
"path": ["reimbursement_details", "transport_fee"],
"min_items": 1,
"description": "交通费用明细",
"element_fields": [
{"path": ["vehicle_type"], "required": true, "check_empty": true, "custom_check": "is_valid_vehicle", "description": "交通工具类型(火车/汽车/轮船/自带车/公务车/飞机/租车/自驾车,也接受 train/car/plane 等英文写法)"},
{"path": ["start_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "出发日期"},
{"path": ["end_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "到达日期"},
{"path": ["departure_place"], "required": true, "check_empty": true, "description": "出发地"},
{"path": ["arrival_place"], "required": true, "check_empty": true, "description": "目的地"},
{"path": ["amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "金额"},
{"path": ["bill_count"], "required": true, "check_empty": true, "custom_check": "is_positive_integer", "description": "票据张数"},
{"path": ["remark"], "required": true, "check_empty": false, "max_len_bytes": 100, "description": "备注说明(财务后端超宽直接 500,见 config/README 或 AGENTS.md)"}
]
},
{
"path": ["reimbursement_details", "hotel_fee"],
"min_items": 0,
"description": "住宿费用明细(没有住宿时可整段缺省)",
"element_fields": [
{"path": ["checkin_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "入住日期"},
{"path": ["checkout_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "退房日期"},
{"path": ["days"], "required": true, "check_empty": true, "custom_check": "is_positive_integer", "description": "住宿晚数"},
{"path": ["person_count"], "required": true, "check_empty": true, "custom_check": "is_positive_integer", "description": "住宿人数"},
{"path": ["invoice_amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "发票金额"},
{"path": ["reimburse_amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "报销金额"},
{"path": ["remark"], "required": true, "check_empty": false, "max_len_bytes": 100, "description": "备注说明"}
]
},
{
"path": ["reimbursement_details", "conference_fee"],
"min_items": 0,
"description": "会务费/培训费明细(没有会务费时可整段缺省)",
"element_fields": [
{"path": ["bill_count"], "required": true, "check_empty": true, "custom_check": "is_positive_integer", "description": "票据张数"},
{"path": ["amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "金额"},
{"path": ["remark"], "required": true, "check_empty": false, "max_len_bytes": 100, "description": "备注说明"}
]
},
{
"path": ["payment_methods"],
"min_items": 1,
"description": "支付方式记录",
"element_fields": [
{"path": ["card_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "刷卡日期"},
{"path": ["card_amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "支付金额"},
{"path": ["merchant"], "required": true, "check_empty": true, "max_len_bytes": 100, "description": "商户名称"},
{"path": ["remark"], "required": true, "check_empty": false, "max_len_bytes": 100, "description": "备注"}
]
},
{
"path": ["subsidy_list"],
"min_items": 1,
"description": "补助清单",
"element_fields": [
{"path": ["person_id"], "required": true, "check_empty": true, "description": "人员工号"},
{"path": ["person_name"], "required": true, "check_empty": true, "description": "人员姓名"},
{"path": ["start_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "补助开始日期"},
{"path": ["end_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "补助结束日期"},
{"path": ["days"], "required": true, "check_empty": true, "custom_check": "is_positive_integer", "description": "补助天数"}
]
},
{
"path": ["attachments"],
"min_items": 0,
"description": "附件列表",
"element_fields": [
{"path": ["filename"], "required": true, "check_empty": true, "description": "文件名"},
{"path": ["attachment_type"], "required": true, "check_empty": true, "description": "附件类型"},
{"path": ["attachment_desc"], "required": false, "check_empty": false, "max_len_bytes": 100, "description": "附件说明"}
]
}
]
},
"normal": {
"description": "普通报销校验规则",
"fields": [
{
"path": ["basic_info", "reimbursement_description"],
"required": true,
"check_empty": true,
"max_len_bytes": 40,
"description": "报销说明(财务系统里这栏很短,20 个汉字以内)"
},
{
"path": ["reimbursement_details", "total_invoices"],
"required": true,
"check_empty": true,
"custom_check": "is_positive_integer",
"description": "发票总数"
},
{
"path": ["reimbursement_details", "total_amount"],
"required": true,
"check_empty": true,
"custom_check": "is_positive_number",
"description": "总金额"
}
],
"arrays": [
{
"path": ["payment_methods"],
"min_items": 1,
"description": "支付方式记录",
"element_fields": [
{"path": ["card_date"], "required": true, "check_empty": true, "custom_check": "is_valid_date", "description": "刷卡日期"},
{"path": ["card_amount"], "required": true, "check_empty": true, "custom_check": "is_positive_number", "description": "支付金额"},
{"path": ["merchant"], "required": true, "check_empty": true, "max_len_bytes": 100, "description": "商户名称"},
{"path": ["remark"], "required": true, "check_empty": false, "max_len_bytes": 100, "description": "备注"}
]
},
{
"path": ["attachments"],
"min_items": 0,
"description": "附件列表",
"element_fields": [
{"path": ["filename"], "required": true, "check_empty": true, "description": "文件名"},
{"path": ["attachment_type"], "required": true, "check_empty": true, "description": "附件类型"},
{"path": ["attachment_desc"], "required": false, "check_empty": false, "max_len_bytes": 100, "description": "附件说明"}
]
}
]
}
}