fix: 优化报销制单下载与付款进度(09-08-reimbursement-payment-closeout)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-09-10 16:39:01 +08:00
父节点 73fcd5a65a
当前提交 fe025e65cf
共修改 15 个文件,包含 364 行新增和 42 行删除
+8 -1
查看文件
@@ -84,8 +84,15 @@ explicit deferred decision, not a completed scope restriction.
`payment_order_export_*` fields.
- Reveal APIs use `POST` with JSON `{ "reason": "2-500 chars" }`; ordinary read
APIs return only bank name and masked account.
- Payment-order API: `POST /api/payment-batches/:id/payment-order` with a reason;
- Payment-order API: `POST /api/payment-batches/:id/payment-order` with `{}`;
success is an in-memory BIFF8 `.xls` download with `Cache-Control: no-store`.
- Payment-order download confirms sensitive-file handling, but does not require
a typed reason. Re-download warns about duplicate bank import/payment.
Audit records system purpose `reimbursement_bank_transfer` with
`purposeSource: system`; optional legacy user reasons remain genuine input,
never fabricated. Account reveal, cancellation and receipt policies stay unchanged.
- Filename is `报销制单_<batchNo>.xls`, sent with RFC 5987 UTF-8 encoding and
ASCII fallback. No names, amounts or account numbers enter the filename.
- Runtime: Node passes validated row JSON through stdin to the fixed
`fill-payment-order-template.py`; the dedicated Python runtime returns BIFF8
bytes on stdout. `PAYMENT_ORDER_PYTHON_BIN` may select the fixed interpreter,
@@ -2,6 +2,19 @@
## 2026-09-10 退回删除接续
### 提交准备(未提交)
用户要求继续操作;本轮按官方 Phase 3.4 先准备两笔提交,不将泛化的继续操作视为提交/推送/生产授权。当前 inline 无独立 reviewer,主会话只读复查及原自动验证不冒充独立复核。
1. `fix: 退回报销支持留痕删除(09-04-reimbursement-state-gap-finance-view)`:使用原独立删除包的 27 文件,包含迁移、参与人/状态守卫、历史材料保留、查询过滤、PC/手机入口、测试及对应规约。
2. `fix: 优化报销制单下载与付款进度(09-08-reimbursement-payment-closeout)`:在第一笔树上应用付款体验及集成验收记录;共享 system-action-confirmation.spec.ts、test-invoice-first-http.cjs 按差异追加,不整文件覆盖。包括中文文件名解析及其回归,不重复携带删除运行时代码。
用临时 Git index 构造两笔文件树并比对最终候选,正式 index、HEAD 和分支均不修改;具体文件清单及树摘要见 artifacts/qa-flow/20260910-combined/commit-plan.json。根 checkout 的治理/task 未提交内容全部排除,不自动快进本地 main、不推送、不部署。
发布需重新核对基线、磁盘、备份、独立回滚制品与迁移状态;existing 模式不得执行初始化 seed。本次含删除标记迁移,首次出现留痕删除后旧应用会忽略标记,不能用只回旧镜像作为完整回退方案。最终候选及该回滚限制须随发布方案单独交审,旧权限修复例外不沿用。
合并验收补记:已在独立集成副本按补丁与 09-08 付款体验合并,未覆盖原独立删除副本,原复核包摘要不变。合并后后端 296 项及下载文件名 7 项通过;真实 PostgreSQL/认证/HTTP/桌面/手机联合流程通过并退出 0(含新迁移、退回删除、凭证留存、发票重用、重新提交审批、付款组批/独立复核/中文制单)。合并证据在 artifacts/qa-flow/20260910-combined/real-db-browser.log;OCR 为 mock provider,不是真腾讯新验证,不执行银行付款。独立复核、提交、部署仍未完成。
- 用户要求继续剩余任务,先退回删除、后付款体验;沿既有 task,不新增管理任务。独立副本 `artifacts/isolated-worktrees/20260910-rejected-delete` 基线 e5685f1,官方 current 已对齐,无新分支,未混入其他工作树未提交内容。
- 已核对最新 PRD 追加范围及付款 task 综合方案。现有 DELETE 会级联删除 workflow 历史;draft 本身不是可物理删除的充分条件。当前模型没有专用删除标记,不能只放开 rejected。
- design 顶部补充 deleted_at/deleted_by 最小迁移、审计与材料引用、参与人授权、查询排除、锁顺序及旧应用回滚风险;行业调研后用户确认实施,本轮已编写迁移并仅在一次性合成数据库执行,未运行生产写入。
@@ -65,3 +65,59 @@ AP task 保留原实施写入面和已通过用户复核。提交/推送后冻
本轮界面修复仅改变已选付款详情的动作优先级,继续使用既有按钮/更多/移动端固定操作区,不重画页面、不调整角色、审批、付款状态机、数据快照或后台接口。保留现金/历史批次人工付款、已有回单直接登记及回单查询失败时不冒充空状态的行为。
报销主体和收款资料应在组批前补齐,因为批次冻结的是当时的账户快照;生成文件不能静默取之后变更的个人账号替换已复核快照。已有批次若需取消/重建,重新交审,不直接更新旧快照。
# 2026-09-09 后续主线综合方案(规划,非部署授权)
## 范围与归属
付款体验沿用本 task;退回单删除/历史可见性归 09-04-reimbursement-state-gap-finance-view;选票后自动生成明细与关联归 08-29-reimbursement-expense-policy-invoice-guard。用户已确认该默认操作取向,本轮按要求更新规划;撤回上一版正常路径的“待关联区→手工建明细→再关联”。验证随对应功能共同交付,不为每个按钮、测试或部署后检查新建 task,不启动 09-07 认证任务的历史批量迁移。各 task PRD 的同日增量是本次需求入口,本文组织跨任务依赖,不覆盖旧阶段事实。
当前生产已发布 b87cc55;用户确认付款复核及文件下载可用,尚无实际支付完成证据。原主工作树含其他未提交治理/状态差异,实施从最新已发布/已推送基线的干净独立副本开始;按官方 task current/start 对齐实际执行目录,已部署副本及冻结包不改。两个报销子项有共享文件,可在同一已批准的报销修复副本协调,但必须有各自验收和可审增量;付款变更单独副本,不能将路径隔离冒充文件不重叠。
## 第一批:报销录入与退回重建
先核实删除事务、workflow 历史、材料关系、占用/去重、查询投影及绑定接口,再完成最小设计补充。界面“删除退回单”,存储层保留历史,优先复用能表达该语义的已有机制;不得假定只有删除按钮变化或无需 schema。若发现必须迁移或实质扩大历史访问/数据修复范围,明确变更清单与回滚后再交审,不偷偷切状态掩盖删除。
退回原单修改重提保持可用;不再使用的单据确认删除后停止流转,解除合法发票的有效占用。软删除/取消历史如何读取、原附件如何保留、财务查询/待办如何排除均列入服务端合同。禁止把“可读历史”误扩成“可继续操作旧单”。撤回变 draft 但有历史的单据要单列,保护原审批留痕。
默认点击“添加发票”打开“我的发票”面板,选择可用旧票或上传新 PDF;新票自动腾讯 OCR,识别成功默认勾选且尊重用户取消。点击“添加到报销单”才触发一票一条可编辑明细并自动关联,多选批量生成;不是 OCR 完成就悄悄创建明细。票面价税合计、开票日期、项目说明作可编辑初值,类型仅可靠时推荐,不确定只补必要字段。用户无需再关联,正常明细仅显示发票数量/预览;手动关联仅保留为异常修复。已有明细入口则直接添加票到指定明细,不生成新明细或覆盖原值。允许提前存票,池和报销内使用同一数据来源。明细生成/票据占用原子完成,失败逐票解释、重试幂等;票据门禁仍严格。费用发生日期不能被开票日期无提示替代,不虚构缺失金额/类型;详细数据兼容与事务方案在发票 task 收敛。
## 第二批:付款下载与详情体验
后端输出中文文件名并使用兼容的 Content-Disposition 编码;前端解析中文 filename*,本地回退名一致,浏览器实测下载名而非只断言 toast。保持 BIFF8 模板、列顺序、格式、金额与批次内容不变,文件名不引入敏感资料。
制单接口单独调整原因合同,不放宽共享 REASON_SCHEMA。系统记录用途来源、操作者、批次、生成序次、成功/失败等必要审计;用户不填理由,不以固定文字假装用户说明。首次确认敏感文件用途,再次确认重复付款风险,权限/状态门禁与防双击保留。取消批次、查看完整账号、回单下载/作废的现有理由策略不在本轮改变。
只将 ProcessingProgress 移到付款页操作卡片下方,复用既有组件/样式,桌面与窄屏验证阅读和键盘顺序。本地未提供 frontend-design skill,不引入新视觉系统;不顺手改报销页壳或进行大文件重构。
## 验证先行,执行端负责
1. 实施前用合成数据复现空单添加发票和退回不能删除的原状,明确测试预期是新业务要求还是既有回归;先有可复现用例,避免按现状写出假绿。
2. 每个改动有单测/路由测试,状态、权限、并发、历史可见性有反例。单测可 mock,但证明业务闭环的端到端测试必须使用真实应用后端、隔离 PostgreSQL、附件存储与合法登录;不 mock 核心业务 API 后声称真实流程通过。
3. 使用专用合成申请人、审批人、财务,按角色分别登录操作。独立复核约束必须保留,不能全程拿 admin 通配抵扣角色验收。合成票据不得含真实银行资料;真实腾讯 OCR 自动识别是交付要求,关闭/误配属于异常,不再作为正常成功分支。需要获准样票和调用条件,缺条件时由执行端准备补齐方案,不能用 mock 或数据库 provider 标记冒充真实识别成功,不擅自改生产密钥或发真实票据。
4. 浏览器必跑空单→我的发票弹窗上传→自动 OCR→选新/旧票→自动生成明细并关联→刷新→核对/补必要项→提交→审批→独立付款复核→下载,以及提前存票、多选票、取消选择、已有明细多票、部分失败/重试/并发、退回修改重提、删除退回→释放发票→新单重用→提交。不允许测试夹具预造明细或手工补一次关联来掩盖默认路径失败。网银付款不自动执行,回单/付款登记仅在完全隔离测试环境使用明确标记的合成资料。
5. 桌面/窄屏核验右侧进度布局,实际下载文件名、BIFF8 结构及重复下载提示;截图/日志脱敏,不能输出真实票据、银行账号或凭证。
6. 涉及状态/权限/数据合同,需只读独立复核;inline 不能派 implement/check 代理,准备明确交审包,不能把主会话复测冒充独立复核。
## 发布与部署后验证合同
每批独立提交、集成验证、冻结候选;提交/推送/部署分别按明确授权执行。两批可以分别交付,不让付款的小优化必须等报销模型改造,但不能积压多批未提交差异。既有完整候选门禁仍有缺口,局部业务链全绿不等于完整候选全绿;发布资格按完整门禁或新的明确例外处理,旧 b87cc55 例外不复用。
上线前先确认可执行的部署后检查方式,不能部署完才发现没有测试账号。执行端负责公网版本/资源、权限、接口及浏览器验证,不把员工的日常业务操作当 QA。
生产写入验证必须先形成并获批测试数据清单:专用账户与角色、测试业务主数据/主体及付款资料、标记、允许接口、预期记录数、通知去向和收尾方式。能保证隔离才执行;专用账号本身不保证隔离,要防止真实审批派给员工、真实通知、预算/报表污染及测试制单流入网银。不改真实账号角色、不拿当前真人单据做删除/重提测试。
若生产无法安全隔离写入,先提供与候选同制品的隔离环境完整验证,再做公网只读/无副作用检查;明确生产写入链未验证,不声称等价,也不让员工补测。缺条件时执行端准备补齐方案,需新增权限或生产写入授权才向用户提出具体请求,不反复索取同范围许可。
每批回执分列:代码/本地单测/真实后端 E2E/独立复核/部署/公网验证/剩余缺口/下一动作。未执行、被环境阻断或失败均不能算通过。测试数据只按获批收尾规则处理,不能为清理测试痕迹物理删除审计或正式单据。
## 暂不扩展
不修改六个 view_all、不启用 R1/合同阶段 B、不逐条修 58 条、不实施通用软删除框架、不重构全部报销页面。统一待办投影是后续主线,本轮只保证本次删除/提交产生的待办正确更新;不以此另造待办引擎。错误豁免 10-05 到期事项沿原任务继续跟踪,不能因本轮反馈被遗忘或统一延期。生产磁盘已清理至足够余量的近期观测只是发布输入,下一次发布仍需检查时效,不追加清理。
# 2026-09-10 付款体验实施补记
- 制单接口使用专用可选原因合同;空对象有效,旧客户端的合法真实原因兼容,非法原因/未知字段仍拒绝。共享必填原因合同不变。
- 成功、重复和生成失败审计标明系统用途及来源;不以固定文本冒充用户原因。权限失败/请求校验失败沿既有位置拒绝,不虚报进入生成审计。
- 文件名使用现有安全 Content-Disposition 工具,UTF-8 中文名和 ASCII fallback;前端缺少响应文件名时使用批次号兜底,模板和二进制生成不变。
- 保留敏感文件确认、重下载警告、取消零请求与 pending 防重复点击。下载次数更新后主动作仍切换上传回单,不表示付款完成。
- 右侧操作卡与进度卡相邻;移动端保留底栏快捷动作且正文操作/进度可达。操作卡不独立 sticky,避免滚动覆盖紧随其后的进度。
- 验证:路由与 BIFF8 单测、mock 桌面/移动端真实下载、隔离 PostgreSQL/真实认证 HTTP 创建复核下载,再与退回删除做同候选验证;禁止真实网银付款和伪造回单。
@@ -1,5 +1,29 @@
# 执行顺序(本地技术审查/修复已批准,真实业务动作另批)
## 2026-09-10 当前执行
### 合并候选验证与发布边界
- 最终页面回归:合并构建产物 preview,Playwright system-action-confirmation.spec.ts 按“财务先制单/制单失败/付款/银行回单/报销”选择,19/19,退出 0;ui-final.log 为最终证据,ui.log 为中断记录。已检查桌面与手机截图:操作卡下接进度,窄屏无横向溢出,底栏动作可达。当前本地实现与联合验证完成,等待独立复核及提交发布授权。
- 本轮独立付款副本基线 e5685f1;与退回删除按补丁合入 artifacts/isolated-worktrees/20260910-reimbursement-payment-integration,没有提交或覆盖主 checkout 的既有改动。
- 合并 focused 后端:23 文件、296/296;另下载文件名解析 7/7。命令以删除 task 的 focused 列表加 paymentOrderXls.test.js 为准;文件名测试为 tests/unit/utils/client-download-filename.test.js。记录见合并副本 artifacts/qa-flow/20260910-combined/unit.log、filename.log。
- 真实隔离执行:RUN_ISOLATED_DB_TEST=1 RUN_RETAINED_DELETE_TEST=1 RUN_BROWSER_TEST=1 RUN_PAYMENT_EXPERIENCE_TEST=1 node scripts/qa/test-invoice-first-http.cjs;BIFF8 使用既有受控测试解释器。real-db-browser.log 为 PASS_REAL_DB_HTTP,退出 0,数据库、合成文件及浏览器完成清理。
- 联合验证涵盖上传选票填明细、退回重提与三步审批、退回留痕删除与票据复用、并发/事务回滚、财务组批、CEO 复核、非授权下载拒绝、桌面/手机真实下载中文 BIFF8、不要求理由、再次下载警告。不执行真实银行付款,OCR 为真实 worker + mock provider,不能称为本轮腾讯 OCR 新验证。
- 前端 typecheck/build、Prisma validate、UI strict/self-test、错误解释 strict、process baseline、task validate、Trellis governance、diff 检查通过。文档 registry errors=0 / warnings=1,为既有 22 个未登记文件,不扩修。
- 最初真实付款 fixture 缺环境功能开关导致 409,修正仅限隔离配置;浏览器实际复现中文名称被旧解析器丢弃,已修产品代码并补七项解析测试。合并页面首轮受 SIGTERM 中断(143),不能视为通过,单独重跑结果另记。
- 保留生产边界:未提交/推送/部署,未触碰真实单据/账户;六个 view_all 与审批角色不变,不能宣称经理只能看相关报销。退回留痕删除含新增迁移,旧镜像可能重新显示留痕删除记录,不能复用“无迁移、只改权限”旧例外。
- 主会话执行本地自审与自动验证;独立只读 reviewer 未执行。下一步先复核两份独立补丁,再按明确授权分别提交、冻结统一候选、重新发布预检和部署后自动验收,不交给员工发现基础缺陷。
联调发现并已修:共享下载客户端只解析 filename,忽略 filename*,导致服务端中文名仍被 ASCII fallback 替代。现优先解析 UTF-8 扩展名;损坏编码、不支持编码、空值回退原 filename。新增 7 项客户端解析回归,已通过。付款路由/BIFF8 93 项通过;最终浏览器和合并验证见本节记录,本地通过不代表已发布。
用户批准本轮报销/付款改动全部完成、合并验证后再部署。付款在独立副本实施,基线 e5685f1,不混入退回删除的迁移。既有历史阶段不代表当前发布状态。
1. 中文制单文件名、无手填理由的敏感下载确认、操作卡下方处理进度。
2. 制单独立请求合同允许省略原因;旧客户端真实填写的原因仍保留,系统用途及来源独立记录,不伪造用户原因。
3. 路由、BIFF8、桌面/移动浏览器定向回归,再与退回删除合并做隔离数据库全链验证。
4. 独立复核、提交和发布尚未完成;生产动作另行授权,不以员工正式业务代测。
## 2026-09-08 获批技术执行
1. 检查 CLI/项目/npm 稳定版本及官方 update dry-run;保留现有定制,稳定通道无新版则不切 beta、不强刷文件。
@@ -144,3 +168,18 @@ T0 是新增代码工作的前置;T1 数据库路径获成功证据后推进 T
## 2026-09-09 提交与推送授权
用户对“AP 与付款修复分两笔提交并推送,不部署、不执行真实恢复、不混入后续准备文档”明确回复“是”。本次只提交本 task 对应已隔离交审文件及当前授权记录;原恢复 task、错误豁免后续阶段和另外两个未跟踪 task 不进入这两笔。实际提交 SHA 与远端结果以 Git 回执为准,不提前宣称 push 成功;生产仍未部署,业务验收状态不随提交改变。
## 2026-09-09 后续工作执行顺序(按已确认选票流程更新规划)
本节为最新规划,旧阶段结果保留;已确认付款独立复核和制单下载,不确认实际付款。当前只更新已有 task 需求与设计,没有创建 task、改代码、运行产品测试或部署。
- [x] 收口用户取向:报销制单中文名;首次/再次不强制手填理由但保留确认与审计;处理进度右移;退回单可以删除后新建;验证由执行端承担。
- [x] 将删除阶段归入 09-04-reimbursement-state-gap-finance-view,将“选票自动生成明细并关联”归入 08-29-reimbursement-expense-policy-invoice-guard,付款优化留本 task;对应 PRD/design/implement 同步。明确替换旧手工关联方案,不新建 task。
- [ ] 综合方案确认后,先为第一批补齐存储/绑定接口设计与隔离端到端夹具,复现两个原始阻断;评估是否涉及迁移,不默认免迁移。
- [ ] 第一批在干净副本实施:退回单删除留痕与发票占用释放、选票自动生成明细并关联及已有明细直接加票;验证所有旧状态的拒绝边界,核实真实腾讯 OCR,异常不交给员工发现。
- [ ] 并行准备部署后专用合成测试条件;缺失项由执行端列出具体配置和授权请求,不调用真人单据或凭据。
- [ ] 第一批完成真实后端角色链、桌面/窄屏验证及只读交审,取得明确提交推送授权后收口;不把另一批产品变更叠入同一脏树。
- [ ] 第二批按已确认付款方案实施中文名、独立下载原因合同和布局;完成文件内容/审计/权限/布局回归及本批交审。若第一批遇真正外部阻塞,第二批可在独立副本提前完成,不扩大范围。
- [ ] 每批冻结候选并提出发布方案,附可执行的部署后自动检查;部署另批,上线后由执行端运行验证、报告失败与回滚建议,必要回滚按具体授权执行。
- [ ] 功能交付后回到统一待办投影;同期维护原错误豁免截止日队列,不批量归档或延期。
首个实施动作明确为“用空报销合成数据复现发票顺序问题,并核查退回删除事务/材料关系”,不是继续生产清理或让 majianyong 再尝试一次。主工作树在旧基线且有治理差异,执行副本须从最新 origin/main 核验建立,按任务登记分批文件清单与测试命令。
@@ -2,6 +2,21 @@
## Goal
### 2026-09-10 本轮批准范围
本轮报销/付款体验全部完成并合并验证后再部署,不等待项目所有存量技术债。付款三项为中文文件名、下载免手填理由、操作卡下方处理进度;退回留痕删除由 09-04 task 独立交付,共同验收。已发布的发票优先录入保留回归,不重复实施。本段覆盖下方历史 R8 的“制单下载必须原因”;不覆盖回单下载、完整账号查看或取消原因策略。真实付款仍由业务人员执行。
### 2026-09-09 真人反馈后的后续验收增量
当前业务事实:用户反馈独立付款复核后,已成功下载银行制单且文件内容没有问题;未据此确认网银付款或回单登记完成。以下付款体验取向已获用户采纳,报销状态与录入改动的综合实施/测试方案见 design.md 最新阶段,待整体方案确认后执行,不继承上次部署授权。
后续确认:用户选择“添加发票→我的发票弹窗→选择旧票/上传并自动 OCR→添加到报销单→自动生成明细并关联”的默认路径。无需再手工建立明细后关联;已有明细入口直接加票,正常页面只展示发票摘要而非关联状态。真实腾讯 OCR 默认可用是业务要求,不是尚待选择是否启用的产品选项;是否配置正确/识别成功仍需执行端验证。此轮授权是更新规划,不表示已实施、已部署或取得新的生产配置/票据发送授权。详细合同归 08-29 发票 task,退回删除与付款三项保持已确认方向。
- 下载文件名统一为“报销制单_批次号.xls”,例如报销制单_PB-20260909-001.xls;保留唯一批次号,不放姓名/金额/账户信息,不改变 BIFF8 内容、工作表、模板和列格式。
- 首次和再次下载均不强制手填用途;敏感文件确认保留,再次下载明确提醒重复导入/重复付款风险。保留权限、已复核状态、独立复核约束及完整下载审计,系统用途不得伪装为用户填写原因;查看完整账号、作废回单、取消批次等理由要求不变。
- 桌面付款详情右侧为操作卡片、处理进度卡片,左侧为概要和单据明细;小屏操作与进度相邻且可达,避免横向溢出。不改流程含义,不将文件下载次数等同银行付款结果。
- 交付需包含相关真实后端端到端验证和部署后验证,不将员工/经理的正式业务操作作为发现基础功能缺陷的默认验收方法。银行实付、真实单据业务判断仍由业务人员负责,代理不得代付或伪造回单。
以业务结果为目标:已审批未付款的 0014 完成付款准备、独立付款复核、按用户模板生成建行制单、银行付款及回单登记;三张退回报销由本人修改重提,实际审批后再进入付款,不让两条业务线互相等待。
2026-09-08 首轮为规划;用户随后明确批准检查并按指南更新 Trellis、多角度审查修订计划,以及完成影响这些业务的技术债务。当前执行范围为本地技术审查、针对性合成验证和已定位阻断的最小修复;不改变既有人工制单/网银流程。未批准生产数据回填、真实账号解密、真实提交/审批/组批/导出/付款、部署或外部通知。此前财务直接经理单字段修正已完成,不重复操作。
@@ -21,6 +21,6 @@
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "用户追加批准Trellis更新检查、多角度计划复核及影响付款业务的本地技术债修复。稳定版已最新,不切beta、不覆盖项目定制。沿用人工下载xls/网银流程,修复首次制单动作优先级并补合成验证;生产数据/真实银行卡解密/实际业务操作/提交推送部署仍另批。",
"notes": "2026-09-10:代码已实现付款中文文件名、下载免手填理由、右侧处理进度及共享UTF-8文件名解析;与09-04退回留痕删除按独立补丁完成本地联合验证(296+7单测、19页面回归、真实隔离DB/HTTP/双端),不混提交。发布未执行;业务仅确认用户已成功下载旧版制单,银行实付/回单未代办。当前等待独立只读复核及明确提交发布授权;不让员工代测。详见implement.md本轮证据。",
"meta": {}
}