文件
hyb-oa/.trellis/tasks/07-28-travel-reimbursement-guide/implement.md
T
wangsli 665cf4add5
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
修复铁路OCR空金额回退(07-28-travel-reimbursement-guide)
2026-07-29 15:32:16 +08:00

10 KiB

实施计划

1. 外部前置门禁

  • 用户确认采用 OA OCR 专用最小权限子用户密钥。
  • 用户在腾讯云侧创建该专用子用户和密钥。
  • 在实际账号确认通用票据识别(高级版)每月 1,000 次专用免费包已到账,生产配置使用中国大陆地域。
  • 在 OCR 控制台设置页确认后付费关闭;额度耗尽时接受 OCR 失败关闭。
  • 配置费用或余额告警作为二次兜底。
  • 确认腾讯 OCR 服务和 ocr:RecognizeGeneralInvoice 最小权限可用,不接独立火车票接口。
  • 确认住宿电子普通发票和铁路电子客票各一份 PDF 样票的测试授权及仓库外受控位置;不得向 Codex 或聊天提供票据。

2. 腾讯 adapter 修正

  • 将现有腾讯调用改为 RecognizeGeneralInvoice,固定单页 PDF 和最小返回选项。
  • 分别归一化住宿 VAT/电子普通发票和 ElectronicTrainTicketFull。
  • 按安全票种标识执行必填字段检查;删除代码/号码互相伪回填。
  • 不持久化腾讯原始响应、乘车人姓名、证件号或完整票面字段;命中旧版腾讯缓存时按同一白名单压缩。
  • 发票上传增加 7MiB OCR 输入上限和明确错误。
  • 增加两类票种、无代码、多票/不支持票据、敏感字段、大小门禁和 provider 错误聚焦测试。

3. 生产配置

  • 对当前生产环境文件制作受控、限权、短期回退副本,不输出内容。
  • 由用户在现场终端静默写入 OCR_PROVIDER=tencent 及专用凭证;地域设置为中国大陆地域。
  • 脱敏检查 provider、凭证非空、环境文件权限和配置合同。
  • 仅重建实际执行 jobs 的 server,不启动独立 worker。

3.1 生产部署根收敛

  • 只读确认活动 Compose、生产环境文件和四个运维 timer 均引用重复嵌套部署根。
  • 暂停相关 timer,将活动根原子改名为时间戳回退目录,并建立干净标准单层部署根。
  • 把生产环境文件在远端复制到标准相对位置,保持所有者和 0600 权限;不回显或经本地传输 Secret。
  • 使用 DEPLOY_DATA_MODE=existing、既有外置数据库/附件宿主目录和同一 Compose project 发布批准提交;未初始化数据或创建 worker。
  • 重新安装 daily、watchdog、drill-reminder 和 WARCH3 timer,确认 unit 不再引用重复目录。
  • 验证 /ready、构建标识、单一 job executor、四个 timer 状态和一次受控备份/新鲜度检查;旧根仅保留作短期回退,不在本任务删除。

回退点:标准根发布或任一 timer 验收失败,恢复时间戳回退根及原 unit 引用并重建原 server;数据库和附件宿主目录不移动、不重置。

回退点:外部依赖 smoke 前若任一配置门禁失败,恢复变更前环境文件并重建 server;保持真实票据禁止上传。

4. 生产与真实能力验证

  • 检查公网 /ready 和预期构建标识。
  • 在 server 内运行现有 external deps 和运行时 smoke,不输出 Secret 或原始响应。
  • 确认实际 provider 为 tencent,且只有一个 OCR job executor。
  • 修正 live 样票脚本:复用 RecognizeGeneralInvoice、按票种必填字段和安全持久化白名单,支持单 PDF 标准输入且仅输出脱敏摘要。
  • 使用合成 PDF/provider 响应覆盖住宿、铁路、非 PDF、超限、缺字段和原始响应不输出,并完成本地门禁、提交和生产部署。
  • 为铁路 Total/Fare 增加只含存在、类型、非空和可解析布尔值的临时诊断;证明持久化白名单丢弃诊断且 live runner 不输出真实值。
  • 完成本地门禁、提交和生产部署后,使用剩余一次授权诊断铁路金额字段;铁路未 PASS 时仍不调用住宿样票。
  • 修正铁路空 Total 阻断可解析 Fare 回退的问题,增加回归测试并完成提交、生产部署与运行身份复核。
  • 经新增授权复验铁路票;仅在铁路 PASS 后调用住宿票,总计最多两次腾讯 OCR 调用。
  • 经单独样票批准后分别运行住宿电子普通发票和铁路电子客票 live OCR PDF 验收。
  • 只保存脱敏状态、耗时、provider 和字段命中摘要;确认不存在 mock 调用证据。
  • 按正常 API/业务生命周期清理或归档测试记录,并执行只读残留检查。

回退点:真实调用失败时停止样票和真实票据上传,保留可解释失败摘要;不得改库伪造成功或切回 mock 处理真实票据。

5. 文档更新

  • 更新 docs/员工快速上手.md 的差旅报销一页指南。
  • 更新 docs/报销发票附件规则.md 的支付截图、实报实销差异、退款/代付和人工复核规则。
  • 不新建平行员工指南,不写入真实票据、支付信息、账号或环境路径。

6. 验证与审查

  • 静态核对页面/API 上传格式、明细绑定和员工/财务字段边界。
  • 运行腾讯 adapter、OCR service/job 和发票上传聚焦测试。
  • cd server && npm run prisma:validate
  • node scripts/qa/check-process-contract.mjs --baseline --json
  • node scripts/qa/audit-docs.mjs --check-registry(0 个错误;22 个既有未注册文档 warning,本任务未新增)
  • node scripts/qa/check-trellis-governance.mjs
  • git diff --check
  • 对生产配置、样票证据和文档口径进行只读复核。
  • 部署与公网检查均通过后,才通知杨俊可以提交真实差旅报销。

2026-07-29 live OCR 验收工具生产部署记录

  • 已部署提交 fa326f9;公网 /ready 与运行容器构建标识一致。
  • external deps smoke、runtime smoke 和公网前端资源扫描通过;实际 OCR provider 为 tencent。
  • 运行拓扑为 server 单一 job executor,未启动 worker。
  • 自动备份 daily、watchdog、drill-reminder 与 WARCH3 四个 timer 均为 enabled/active,冻结构建与标准部署根一致,未引用旧重复目录。
  • 部署后受控自动备份和新鲜度检查均成功,未调用真实 OCR 样票。
  • 真实住宿和铁路样票验收仍等待单独调用授权;在两类样票通过前,不通知员工上传真实票据。

2026-07-29 授权样票验收尝试

  • 已匿名选择铁路 PDF 并执行最多一次 provider 调用,但外层 shell 在探针非零退出时提前终止,未保留已生成的脱敏 JSON,因此本次不能作为 PASS 或可解释 provider 终态证据。
  • 按“第一份未取得明确 PASS 即停止”约束,未调用住宿样票,也未重试铁路样票。
  • 空 stdin 捕获自检证明修正后的调用方式可在 provider 调用前保留 HOLD/sample_empty 摘要;该自检未消耗 OCR 次数。
  • 本次没有创建 OA 发票、附件或数据库记录;真实样票仍未验收通过,员工上传门禁保持关闭。
  • 经额外授权后,修正包装器重新验收铁路 PDF,明确得到 HOLD/sample_pdf_invalid;失败发生在 provider 调用前,本次未消耗腾讯 OCR 次数。
  • 匿名结构预检确认铁路 PDF 的 EOF 后存在非空白尾随数据,不符合现行严格 PDF 终止边界;不截断原件、不放宽安全门禁,需重新取得官方原始电子票据。
  • 住宿 PDF 的 PDF 头部、EOF 终止边界和 7 MiB 上限预检均通过,但因铁路票未 PASS,未调用住宿样票 provider。
  • 用户另行指定的铁路 PDF 通过同一结构预检,证明上一份 sample_pdf_invalid 是旧文件特有的 EOF 尾随数据问题,不是所有铁路 PDF 或校验器普遍失败。
  • 新铁路 PDF 经真实腾讯 OCR 识别为单张 ElectronicTrainTicketFull,票号、日期和购买方字段命中,但 totalAmount 未命中,终态为 HOLD/missing_required_fields:totalAmount;未输出或持久化任何识别值、原始响应或票面字段。
  • 当前适配器已按腾讯 SDK 合同读取铁路票 Total 与 Fare 两个金额字段;现有脱敏摘要不能区分 provider 未返回金额与返回值格式不可解析,需在另行批准后增加字段形态布尔诊断。铁路票未 PASS,因此仍未调用住宿样票 provider。

2026-07-29 铁路金额字段诊断实现验证

  • 聚焦测试 19 项、完整后端 168 个文件/1075 项、Prisma validate、前端 typecheck/build、流程合同、Trellis governance、敏感内容和 diff 门禁通过;仅有既有依赖弃用提示与 22 个既有未注册文档 warning。
  • P2 聚合器的后端聚焦测试 94 项及前端门禁通过;其业务流因合成账号首次改密状态失败,live-readiness 因本地旧凭据和部署前构建标识不一致失败。进入 live OCR 步骤时已主动终止,生产最近 10 分钟新增发票和 OCR 尝试记录均为 0。
  • 诊断只存在于 provider 返回到 live runner 的进程内对象,持久化 sanitizer 丢弃整个 diagnostics;合成敏感标记未出现在序列化摘要中。
  • 诊断提交 5f2788c 已部署;公网构建、external deps、runtime smoke、单一 job executor、四个 timer、自动备份和新鲜度检查均通过。
  • 最后一次授权调用确认腾讯返回的铁路 Total 是空字符串,而 Fare 非空且可被当前解析器接受。现有 info?.Total ?? info?.Fare 在解析前选择空字符串,阻断了 Fare 回退;根因是适配器空字符串回退顺序,不是 PDF、凭证、网络或腾讯票种识别失败。
  • 本次仍为 HOLD/missing_required_fields:totalAmount,住宿样票未调用;所有既有真实 OCR 调用授权已用尽,修复后复验必须重新取得授权。
  • 已将铁路金额改为分别解析 Total 与 Fare 后回退,并增加“空 Total + 可解析 Fare”回归测试;聚焦测试 10 项、Prisma validate、流程合同、Trellis governance、敏感内容和 task validate 均通过。
  • 已在现有 OCR code-spec 固化同类字段回退规则和测试要求;本轮尚未提交、部署或调用腾讯 OCR。

风险文件与操作

  • 生产环境文件:包含 Secret,只允许用户现场静默输入;不得由补丁、聊天或命令参数传入。
  • server 重建:短暂影响 OA;仅操作当前实际 server,保留回退配置。
  • 真实样票:包含发票和个人/企业信息;只留在仓库外受控位置。
  • 文档:员工指南必须短且与生产费用类型、PDF-only 和附件入口一致,避免把财务付款回单误写成员工材料。