Files
bid-doctor/server/tests/fixtures/make_bid_fixtures.py
YANG JIANKUAN 6e0d4c1dd6
Some checks are pending
ci / server (push) Waiting to run
ci / web (push) Waiting to run
ci / contract (push) Waiting to run
feat(addendum): 补遗追加(FR-M2-10)
- 招标文件解析后可以追加补遗 / 澄清:单独解析、扣 1 次;新条目标「补遗 N」进正式清单,清单回到草稿(AD1)
- 同一种日期、时间不同的旧条目标「已被补遗 N 更新」,逐条确认更新或保留两条(AD2、AD3)
- 项目字段的新值在概览「采用 / 不采用」:采用时以补遗为准、清掉人工值;采用截止时间时日期条目一起确认;
  没确认前查标用旧值,检查预览提示(AD4)
- 补遗不改项目名称、编号、采购人、代理机构、法律体系(更正公告标题会被抽成项目名称);时间比较按北京时间补时区
- 接口:fields/{key}/pending、checklist-items/{id}/supersession;清单项 origin_document、superseded_by;
  关键日期 replaces;解析结果 dates_superseded、fields_pending;检查预览 pending_updates
- 前端:补遗模式的上传页、解析页结果、概览确认、读标页来源筛选和日期确认、检查预览提示
- 决策 AD1–AD6;方案和落地记录 docs/architecture/addendum-plan.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:27:21 +08:00

81 lines
4.8 KiB
Python
Raw 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.

"""生成查标测试用的虚构投标文件(对应 tender-mini.pdf 的三条 ★ 条款)。内容全部虚构。
cd server && ../.venv/bin/python tests/fixtures/make_bid_fixtures.py # 需要 Gotenberg(:3109)
- bid-mini-v1.pdf:响应了资质证书和服务器内存,漏了交换机硬件 BFD → 1 个致命问题「未找到响应」;
- bid-mini-v2.pdf:补上了交换机硬件 BFD → 复查时这个问题「本次已解决」;
- bid-mini-forms.pdf:v2 的内容 + 格式文件里的规则问题(大写和小写金额不一致、授权书没填投标人名称、
报价附加条件、另外给了一个优惠报价),措辞故意和评测集的开发词库不同;
- bid-mini-quals.pdf:v2 的内容 + 企业资质情况表(证书、编号、有效期,全部虚构),资质匹配的端到端测试用;
- addendum-mini.pdf:tender-full.pdf 的更正公告(补遗,FR-M2-10):递交截止时间推后一周、新增一条 ★ 参数。
"""
from __future__ import annotations
from pathlib import Path
import httpx
HERE = Path(__file__).parent
GOTENBERG = "http://127.0.0.1:3109/forms/chromium/convert/html"
HEAD = """<!doctype html><html><head><meta charset="utf-8"><style>
body { font-family: "Noto Serif CJK SC", "Noto Sans CJK SC", serif; font-size: 12pt; line-height: 1.8; margin: 0; }
h1 { font-size: 16pt; text-align: center; }
table { border-collapse: collapse; width: 100%; } td, th { border: 1pt solid #333; padding: 4pt; }
</style></head><body>"""
COMMON = [
"<h1>某市智慧政务系统集成项目投标文件(测试样例,内容虚构)</h1>",
"<p>投标人:某某信息技术有限公司(虚构单位,仅用于测试)。</p>",
"<p>一、项目理解。本投标文件是测试用的虚构样例,用于验证投标文件检查流程,内容不对应任何真实的投标人或采购项目。"
"我方已认真阅读采购文件的全部内容,愿意按采购文件的要求提供货物和服务。</p>",
"<p>二、资格证明。投标人须具备有效的信息系统集成服务资质证书:我公司具备有效的信息系统集成服务资质证书,"
"证书复印件见附件1。</p>",
"<p>三、技术响应。服务器内存不低于32GB的要求:我方服务器内存配置为64GB,并提供产品彩页作为证明材料,见附件2。</p>",
]
BFD = "<p>交换机支持硬件BFD,最小报文发送间隔不大于50毫秒的要求:我方交换机支持硬件BFD,最小报文发送间隔为3.3毫秒。</p>"
TAIL = ["<p>四、售后服务。我公司提供7×24小时售后服务,接到报修后2小时内响应。</p>", "</body></html>"]
def render(name: str, parts: list[str]) -> None:
html = HEAD + "".join(parts)
r = httpx.post(GOTENBERG, files={"files": ("index.html", html.encode(), "text/html")}, timeout=60)
r.raise_for_status()
(HERE / name).write_bytes(r.content)
print(name, len(r.content))
FORMS = [
"<p>五、法定代表人授权委托书。本人王某(姓名)系(投标人名称)的法定代表人,现授权李某为我方代理人。</p>",
"<p>六、开标一览表</p>",
"<table><tr><th>项目名称</th><th>投标总报价(元)</th><th>投标总报价(大写)</th></tr>"
"<tr><td>某市智慧政务系统集成项目</td><td>1,280,000.00</td><td>壹拾贰万捌仟元整</td></tr></table>",
"<p>让利后总价:1,250,000.00元。</p>",
"<p>七、本次报价未包含设备运输费用,运输费用由采购人另行承担。</p>",
]
QUALS = [
"<p>五、企业资质情况表</p>",
"<table><tr><th>证书名称</th><th>证书编号</th><th>等级</th><th>有效期</th></tr>"
"<tr><td>安全生产许可证</td><td>(测)JZ安许证字〔2023〕000001</td><td>—</td><td>2023年11月16日至2026年11月15日</td></tr>"
"<tr><td>ISO9001质量管理体系认证证书</td><td>00000Q00001</td><td>—</td><td>2025年3月10日至2028年3月9日</td></tr>"
"</table>",
]
ADDENDUM = [
"<h1>关于某市智慧政务系统集成项目的更正公告(测试样例,内容虚构)</h1>",
"<p>各潜在供应商:本项目采购文件更正如下,其他内容不变。</p>",
"<p>一、响应文件递交截止时间更正为:2026年12月8日9时30分(北京时间)。</p>",
"<p>二、★新增技术要求:存储系统可用容量不低于100TB,并提供产品彩页作为证明材料。</p>",
"<p>本更正公告是采购文件的组成部分,与采购文件具有同等效力。</p>",
"</body></html>",
]
if __name__ == "__main__":
render("bid-mini-v1.pdf", [*COMMON, *TAIL])
render("bid-mini-v2.pdf", [*COMMON, BFD, *TAIL])
render("bid-mini-forms.pdf", [*COMMON, BFD, *FORMS, *TAIL])
render("bid-mini-quals.pdf", [*COMMON, BFD, *QUALS, *TAIL])
render("addendum-mini.pdf", ADDENDUM)