收口付款批次创建与复核(08-01-reimbursement-notification-progress-clarity)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-08-02 00:29:47 +08:00
父节点 78b80f88d7
当前提交 7c39f8b0f9
共修改 17 个文件,包含 591 行新增和 227 行删除
@@ -76,3 +76,44 @@
- 移动财务工作台在付款能力开启时固定显示财务卡片,不再要求先存在批次或异常;卡片进入受同一付款权限保护的 `/mobile/payment-batches`,复用现有响应式付款页,避免企微小屏把 PC 路径重定向回首页。
- 入口只对真实 finance/finance_mgr 且具备付款权限的人员显示;不向普通员工或仅审批人开放创建能力。
- 本轮不自动打开创建面板、不自动选择报销、不代替真实财务动作。
## 8. 付款批次创建与复核闭环
### 8.1 已确认的状态事实
- `POST /payment-batches` 已在同一事务内生成 `batch_no`、创建批次与批次项、写创建审计,并创建 `payment_batch.review_requested`;事务提交后立即进入企微投递。
- 当前没有 submit API。`draft` 不是“尚未提交”,而是“已经提交付款复核、尚未被非制单人复核”。继续向用户显示“草稿”会制造一个不存在的提交动作。
- 不新增状态和接口:数据库继续使用 `draft -> reviewed -> executed/failed`,用户语义改为 `待付款复核 -> 待财务付款 -> 已付款/登记失败`。
### 8.2 KISS 创建合同
- 创建页只保留候选搜索、报销选择、已选数量和一个主按钮“创建并提交复核”。
- 服务端 `name` 改为可选;未传时按 `APP_TIMEZONE` 生成 `YYYY-MM-DD 付款批次`。现有调用方显式传入名称时继续兼容。
- 唯一批次编号继续由服务端生成,不把编号输入暴露给用户;本轮不引入数据库序列表或编号迁移。
- 未传付款渠道时默认 `bank`,从而保持银行回单门禁;付款日期不在创建日预填,登记付款完成时未覆盖则按公司时区当天写入。凭证前缀保持可选且默认空。
- 既有报销批次若历史渠道为空,API 展示和执行门禁按 `bank` 解释但不回写数据库;因此当前真实批次也会先要求回单,不需要生产数据修正。
- 日期、渠道、凭证号的异常覆盖继续留在批次项,不让低频字段占据首次创建主路径。
### 8.3 当前责任与动作
- 创建成功反馈:`已提交付款复核`;详情说明:`等待负责人复核,制单人不可复核自己的批次`。
- `draft`:复核责任人显示“负责人”;符合 maker-checker 的复核账号显示主动作“复核通过”,制单人不显示伪装成可用动作的禁用复核按钮。
- `reviewed`:财务责任人显示“财务”;页面说明先在线下银行完成付款并上传回单,主动作改为“登记付款完成”。
- `reviewed + bank + 0 份有效回单`:唯一主动作是“上传银行回单”,点击直接打开既有文件选择器;上传成功刷新附件计数后,主动作切换成“登记付款完成”。非银行渠道不强制回单,直接显示登记动作。
- `executed`:显示“已付款”,不再提供付款动作;`failed` 显示“付款登记失败”并允许财务按既有规则重试。
- PC 与移动复用同一响应式页面、状态函数和责任说明,不建立第二套移动状态机。
- 付款批次状态中文映射放入客户端共享模块,付款列表、详情和其他客户端调用方统一导入;服务端报销处理进度继续输出业务阶段,但用跨层测试断言其“待付款复核”语义与客户端 `draft` 映射一致。
### 8.4 单一复核责任人
- 解析 active、具备 `payment.batch.review` 且不是制单人的候选人。
- 先按稳定顺序选择 `ceo` 一人;不存在时再选择 `manager` 一人。一个员工同时有多个角色仍只产生一个收件人。
- 创建事务在写批次之前完成候选解析;没有合格人员时返回可解释的业务错误,保证不会出现“批次已创建但无人能复核”。
- 无合格人员错误面向财务显示“当前没有可复核人(复核人必须是非制单人且在职),请联系管理员”,并保留固定错误详情供自动化断言。
- 页面显示职责而不预猜姓名;通知只发给最终选中的真实责任人。历史通知不补发、不删除。
### 8.5 兼容与回滚
- 不改 Prisma schema、历史批次或报销事实;既有 `draft` 批次部署后直接按“待付款复核”展示。
- 若新创建合同需回滚,客户端可恢复旧表单,服务端仍接受显式名称和可选默认字段;状态机与历史数据不变。
- 任何真实批次复核、回单上传、付款登记仍由业务人员操作,不纳入部署自动化。
@@ -78,3 +78,20 @@
- 提交 `37b4ef2` 已推送并通过既有安装固化入口部署;环境合同、远端 preflight、migration、`/ready`、external deps、runtime smoke、公网构建标识和前端资源扫描通过。
- runtime smoke 明确证明 env true 与 `payment_batch_v1=flag_force_on_global`;生产只读核验确认唯一 active 财务人员仍有付款管理权限、系统导航含 `paymentBatches`、已批准未付款计数为 1、可建批次候选计数为 1。
- 没有替财务创建付款批次,没有替负责人复核,也没有上传回单或执行付款。下一条真实验证由王芝玲创建批次触发,届时核验马建勇收到付款复核企微通知。
## 8. 首张真实付款批次闭环修正(已实施,待部署批准)
- [x] 只读核对创建路由、状态转换、通知发送点、前端按钮显隐和聚焦 E2E;确认不存在 submit API,`draft` 创建时已经发送复核通知。
- [x] 生产只读核验最新真实批次:已自动编号、状态 `draft`、未复核/未付款、含 1 个报销项;复核通知已生成且有 1 次企微成功投递。核验未读取名称、金额、人员标识、消息正文或原始 payload。
- [x] 服务端允许省略名称,自动生成批次标题和银行渠道默认值;付款完成登记缺少日期时按公司时区当天落账。
- [x] 既有报销批次渠道为空时按银行转账进行 API 展示和回单门禁,不执行生产数据回填。
- [x] 复核责任人解析改为单一 `ceo` 优先、`manager` 兜底;没有合格非制单复核人时在任何业务写入前拒绝创建。
- [x] 创建页收敛为选择报销 + “创建并提交复核”,移除名称、默认日期、渠道和凭证前缀的高频路径输入;异常覆盖仍留在详情。
- [x] 统一状态和动作:`draft=待付款复核`、`reviewed=待财务付款`、`executed=已付款`、`failed=付款登记失败`;“复核”改为“复核通过”,“执行”改为“登记付款完成”。
- [x] 提取付款批次共享状态映射并替换客户端局部映射;增加跨层语义回归,锁定报销进度与付款页对 `draft` 的一致表达。
- [x] 详情按状态显示当前责任职责、下一步和 maker-checker 说明;银行渠道无有效回单时唯一主动作是“上传银行回单”,上传后切换为“登记付款完成”;不新增 Tab、流程设计器、第二轮复核或 submit API。
- [x] 更新 server route 单测与付款主链 Playwright,覆盖自动字段、无复核人 fail-closed、单一收件人、状态/动作中文和实际付款日缺省值。
- [x] 运行 server focused Vitest、客户端 typecheck/build、聚焦 Playwright、Prisma validate、Trellis/governance/process/sensitive/diff 门禁。
- [x] 因修改付款责任解析和状态表达,实施后执行只读 reviewer 审查;通过后再申请提交、部署和公网/真机验证批准。
本地验证(2026-08-01):付款/报销详情/通知/导出/导航聚焦 Vitest 85 passed;隔离 PostgreSQL 付款并发门禁覆盖双执行、执行/取消、重复建批次和直接付款竞争并全部通过;客户端 typecheck/build 通过;付款权限 5 条、高风险动作 8 条 Playwright 共 13 passed。reviewer 首轮未发现数据安全或状态机阻断项,指出“兼任复核职责的制单人仍显示自审按钮”和“回单查询失败误报为空”两项交互问题;已修为前端同步排除制单人、失败态只显示错误与重新加载,复查未发现新 blocker。既有真实批次未被读取正文、修改、复核、上传回单或登记付款。
@@ -11,6 +11,8 @@
- 当前员工详情展示“付款批次复核”“付款与回单”,容易被理解为两轮额外审批;实际前者是非制单人付款复核,后者是财务线下付款后的回单与状态登记,不是审批。
- 当前职责基线:马建勇负责主管审批和非制单付款复核;王芝玲负责财务复核、创建付款批次、线下付款、上传回单和登记付款完成。一个付款批次可以覆盖多张报销单。
- `client/src/lib/approvalDisplay.ts` 已把 `start` 映射为“提交”,但 PC `WorkflowTaskDetailPage.tsx` 与移动 `MobileApprovalsPage.tsx` 各自复制了缺少 `start` 的局部映射,导致显示 `start · 杨俊`。
- 首张真实付款批次暴露了创建闭环的表达缺陷:服务端在创建事务内已经自动编号、锁定报销、生成付款复核通知并开始投递,但数据库状态和页面仍显示“草稿”,页面也不存在提交接口或提交按钮,导致制单人无法判断是否已经送审、由谁处理、下一步是什么。
- 生产只读核验确认该真实批次已经自动编号,当前未复核/未付款;付款复核通知已经生成并有企微成功投递。当前解析同时创建了 `ceo` 和 `manager` 两类站内收件记录,不符合“一个明确责任人、不要泛发”的小团队运行目标。
## Scope
@@ -22,6 +24,9 @@
- 每周集中建立一次付款批次作为当前运行约定,不在本任务建设定时排程、自动组批或强制付款日。
- 修复财务首次使用时的入口死锁:付款能力正式常开时,即使尚无付款批次,财务人员也必须能在 PC 和移动工作台看到“付款”入口并进入创建页。
- 恢复生产 `payment_batch_v1` 正式常开基线,并防止新环境初始化或 QA 窗口收尾把正式常开状态静默改回关闭。
- 收口付款批次创建到复核的首个真实闭环:创建页只要求选择待付款报销,编号、标题和常用付款默认值由服务端生成;创建动作明确等价于提交付款复核,不再让用户寻找不存在的二次提交按钮。
- 付款页用业务状态而非内部状态名表达下一责任:`draft` 显示“待付款复核”,`reviewed` 显示“待财务付款”,`executed` 显示“已付款”;详情说明当前责任职责和唯一下一步。
- 付款复核通知收件人按 `ceo` 优先、`manager` 兜底选择一个确定的非制单人;没有合格复核人时创建前失败并给出可解释提示,不生成无人负责的批次。
## Requirements
@@ -34,6 +39,12 @@
- 付款开关恢复前先查询 R54 变更历史;若当前库无变更审计,必须区分“seed 首次创建默认值”和“seed 覆盖已有值”,不得把不存在的 runner/人工操作写成根因。
- QA 短窗口结束时必须恢复调用前快照;正式启用流程成功后保持常开,失败才回滚,不得无条件写死 `force_off`。
- 正式环境和新初始化的试运行环境必须同时满足环境硬开关与数据库开关常开;任何一层关闭都应由部署/运行门禁发现。
- 付款批次内部仍可保留 `draft` 作为兼容状态,但该状态已代表“创建并提交、等待独立复核”,前端、通知和测试不得再把它描述成尚未提交的可编辑草稿。
- 新建批次不要求财务手工编批次名称、付款日期、渠道或凭证前缀;服务端继续自动生成唯一批次编号,按公司时区生成标题,默认付款渠道为银行转账,实际付款日期在登记付款完成时缺省取登记当天。异常项仍可在批次详情中覆盖。
- 付款动作必须使用“登记付款完成”等事实性文案,不得用“执行付款”暗示 OA 会连接银行或自动转账。
- 付款复核仍是一轮 maker-checker;责任收件人只选一个,优先具备复核权限的 active `ceo`,没有时再按稳定顺序选择 active `manager`,始终排除制单人。
- 付款页同一时刻只显示一个主动作:银行渠道复核通过但尚无有效回单时显示“上传银行回单”;上传后才显示“登记付款完成”,不能让用户先撞到 `bank_receipt_required` 才知道前置条件。
- 付款批次状态标签必须使用共享展示映射;列表、详情、移动响应式视图和相关测试不得各自复制 `draft/reviewed/executed/failed/cancelled` 中文文案。
## Acceptance Criteria
@@ -47,6 +58,15 @@
- [ ] 财务人员在尚无付款批次但存在已批准待付款报销时,PC 与移动端均可看到“付款”入口,并能看到该报销作为新建批次候选。
- [ ] 正式初始化基线为付款批次常开;QA 窗口测试覆盖原值为 on/off 两种情况并恢复原值,不再硬编码关闭。
- [ ] 生产恢复后只验证入口和候选可见,不代替财务创建批次、负责人复核或执行付款。
- [ ] 新建批次页面只需选择报销;提交后自动得到唯一编号、按公司时区生成的标题、银行转账默认渠道,并直接进入“待付款复核”。
- [ ] 创建按钮显示“创建并提交复核”,成功反馈明确“已提交,等待负责人复核”;页面不存在需要用户寻找的第二个提交动作。
- [ ] 制单人看到“待付款复核”和“负责人复核(制单人不可自审)”;实际复核人看到可用的“复核通过”;复核后财务看到“待财务付款”和“登记付款完成”。
- [ ] 同一批次只通知一个确定的非制单复核责任人,`ceo` 优先、`manager` 兜底;无合格复核人时拒绝创建且不写批次、批次项、审计或通知。
- [ ] 未填写实际付款日期时,登记付款完成以公司时区当天落账;银行转账仍要求先上传银行回单,OA 不执行真实转账。
- [ ] 银行渠道复核通过且没有有效回单时,唯一主动作是“上传银行回单”;上传成功后唯一主动作切换为“登记付款完成”,不会先触发可预见的 409。
- [ ] 无合格复核人的错误明确说明“复核人必须是非制单人且在职,请联系管理员”,不把配置问题伪装成财务人员操作错误。
- [ ] 既有真实批次不改 ID、不改金额、不改报销绑定、不改复核/付款事实;部署后仅获得新的业务文案和下一步说明,不替任何人推进状态。
- [ ] 既有报销批次渠道为空时按银行转账展示并执行回单门禁,但不回写历史记录;当前真实批次同样先上传回单再登记付款完成。
## Out of Scope
@@ -55,6 +75,8 @@
- 不建设每周付款日排程、自动组批、批次自动复核或定时通知。
- 不在未获批准时修改生产通知渠道、员工推送开关、企微绑定、环境变量或服务状态。
- 不顺带重构全部审批页面或统一所有业务状态标签。
- 不新增“提交中”数据库状态或单独 submit API,不增加第二轮付款审批,不建设可配置的付款复核人选择器。
- 不把批次创建与财务复核合并,不由系统自动复核、自动上传回单或自动登记付款完成。
## Deferred Decision With Trigger