feat(check): 规则检查(报价形式、形式要件、响应表),表格按单元格分行
- check/rules.py(规则集 2026.11-r1,不调模型):大小写金额、分项合计、超最高限价、 多个报价、别的项目名称、没填的地方、落款日期、投标有效期、附加条件、响应表里的未响应; 每条挂投标原文,有依据的挂招标侧出处;缺限价、截止时间、有效期要求时写进覆盖范围 - 文字层的句子带上单元格框,表格按单元格上沿分行 - 按 Fable 审读意见收紧致命级:认不准的降为重要或提示 - 评测:score.py 评规则问题;P07 注入记录改为空白处前后原文,剔除注入到人员表的 D10 - 上传页的检查范围文案同步 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -272,3 +272,36 @@ async def test_response_modes_are_stored_editable_and_used(user: User) -> None:
|
||||
(f,) = await findings(user, run["id"])
|
||||
assert f["type"] == "manual_review" and f["severity"] == "hint"
|
||||
assert run["counts"]["fatal"] == 0
|
||||
|
||||
|
||||
async def test_rule_findings_are_written_with_citations_and_carried(user: User) -> None:
|
||||
"""规则检查(报价形式、形式要件):问题挂规则编号和投标原文,复查时按 match_key 沿用处理状态。"""
|
||||
project_id, tender_id = await project_with_tender(user)
|
||||
await run_parse(user, tender_id)
|
||||
bid = await upload_bid(user, project_id, "bid-mini-forms.pdf")
|
||||
run = await run_check(user, project_id, [bid["id"]])
|
||||
assert run["status"] == "succeeded", run
|
||||
rule = {f["rule"]["code"]: f for f in await findings(user, run["id"]) if f["detector"] == "rule"}
|
||||
assert set(rule) == {
|
||||
"PRICE.CAPITAL_MISMATCH",
|
||||
"PRICE.MULTIPLE_QUOTES",
|
||||
"FORM.BLANK_FIELD",
|
||||
"FORM.CONDITION_ADDED",
|
||||
}
|
||||
cap = rule["PRICE.CAPITAL_MISMATCH"]
|
||||
assert cap["type"] == "price_form" and cap["severity"] == "important" and cap["checklist_item"] is None
|
||||
assert cap["rule"]["description"] == "大写金额和小写金额核对"
|
||||
(c,) = cap["bid_citations"] # 同一页的几句合成一条出处,各句分别画框
|
||||
assert "壹拾贰万捌仟元整" in c["quote"] and "1,280,000.00" in c["quote"] and len(c["quads"]) >= 2
|
||||
assert c["document_label"] == "技术分册"
|
||||
# 「让利后总价」和投标总价不同:多半另报了一个价,但不是「备选方案」那种明确的两个报价,按重要
|
||||
assert rule["PRICE.MULTIPLE_QUOTES"]["severity"] == "important" and rule["FORM.BLANK_FIELD"]["severity"] == "hint"
|
||||
assert any("报价形式" in x for x in run["coverage"]["checked"])
|
||||
assert run["coverage"]["rule_set_version"] == "2026.11-r1"
|
||||
|
||||
await user.post(f"/findings/{cap['id']}/resolve", json={"status": "ignored", "note": "大写栏已手工更正"})
|
||||
again = await run_check(user, project_id, [bid["id"]])
|
||||
cap2 = next(
|
||||
f for f in await findings(user, again["id"]) if (f["rule"] or {}).get("code") == "PRICE.CAPITAL_MISMATCH"
|
||||
)
|
||||
assert cap2["presence"] == "carried" and cap2["status"] == "ignored"
|
||||
|
||||
Reference in New Issue
Block a user