文件
hyb-oa/.trellis/tasks/archive/2026-10/09-04-reimbursement-state-gap-finance-view/prd.md
T
wangsli和Claude Opus 5.5 377bda322e 归档报销状态空隙与财务处理视角任务(09-04-reimbursement-state-gap-finance-view)
- 依用户线上反馈收口:待组批可找到、他人未提交草稿不可见、权限内退回/撤回草稿仍可见(设备未注明,不记为双端验收)
- 实现 f9aee4c9、229867f5 均包含于生产 4a5cd8f2;原未勾清单与历史记录保留
- 银行导入、付款交接、通知送达等继续由原任务跟进

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 10:41:38 +08:00

163 行
24 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# 报销状态空隙与财务处理视角
## 2026-10-11 收口归档(用户已批准,未提交)
用户针对财务线上使用情况回复“1可以找到 2看不到 3能看见”:符合条件的报销可在待组批找到;全范围看不到他人从未提交的私人草稿;原权限范围内的退回或撤回草稿仍可见。设备未注明,不将本次反馈写成电脑、手机双端验收。第一项仅记录“可以找到”,不追加“已有批次不重复”的现场确认,后者仍以既有软件测试为据。
本地 Git 已核实本任务登记的实现提交 `f9aee4c9`、本人报销发布 `229867f5` 均包含在已确认的生产基线 `4a5cd8f2` 中;本轮未连接生产。原 AC1/AC11 要求 `0014` 位于待组批是历史时点,既有记录表明它后来已组批、复核并导出制单,现在不要求它再次成为候选,也不回放真实业务来满足旧清单。
三项主要页面行为已有本次用户反馈支持。用户核对记录后明确回复“可以归档”,授权收口本任务;官方归档命令已成功,任务状态为 `completed`、完成日期为 `2026-10-11`,目录位于 `archive/2026-10/`。原勾选清单和历史证据保留,不补勾为全量重新验收;真实银行导入、付款交接、通知送达及恢复验收不由本次页面反馈替代,继续沿各自原任务跟进。本次授权仅归档,不含提交、推送或部署,具体收尾见 implement 顶部。
## 2026-09-17 真人反馈:审批后进度刷新与付款明细顺序
用户要求修复财务复核通过后当前页进度仍旧、同批多报销明细未按单号排序。沿本task既有详情一致性范围本地实施,先于借款与精简;不读取真人单据、不重放真实审批。
验收:PC/手机同文档审批成功后,报销处理进度消费新的服务端详情,不需刷新/切页/重新聚焦;退回、转审及已被处理冲突同样重取权威状态,不能把写入失败乐观画成通过。付款列表/详情DTO的报销items按报销编号自然升序、同号按稳定ID兜底,原数组/写入/锁序/凭证编号/导出顺序保持;既有批次无需数据迁移。补三个单据的乱序反例和当前页刷新正反例,保留原权限/副作用断言。仅本地合成验证,提交推送部署仍另批。
## 2026-09-12 财务本人报销闭环(已批准本地实施)
用户已批准本地实施和验证:财务本人报销由CEO一次审批,财务创建付款批次、CEO独立复核;提交/推送/部署及生产写入另批。复用当前任务。隔离验证已复现本人报销死结,不据此宣称真人单据已阻断。
以报销归属人持finance为触发条件,新快照统一为一个CEO审批步骤,即使存在第二位财务。财务代填普通员工单据不算财务本人报销。普通员工及仅CEO归属人保留原规则;归属人同时持finance与ceo仍必须由另一个合法CEO审批。
- 申请人范围同时包含归属人与提交人,代提不能成为自审旁路;多角色、委托不豁免自审限制。
- 不摘角色、不加finance角色、不改付款复核权限,不把报销审批当作付款复核。
- 财务本人报销不再重复经理/CEO/finance三步,这不是全局按审批人去重。付款复核仍是另外一次独立动作。
- 无合法替代CEO时在提交前明确阻断,不生成明知无人可处理的新流程;不得返回成功后再等待管理员救单。
- 仅适用于新提交及合法重提生成的新快照;不自动改写在途、已审批及历史单据。
- 验收须覆盖普通员工、CEO本人、唯一财务本人、存在第二位财务、代提与多角色、停用/归档候选及无人可批;由执行端在合成环境验证,不要求员工代测。
## Goal
### 2026-09-12 最新备注方案(已批准修改、测试后部署)
用途保持“报销款”,备注改为“报销款 ”+完整报销编号,不加姓名。该方案是用户采纳的产品选择,不是国内系统调研结论,也不证明银行长度/导入接受性。一单一行、批次多单、快照及编号不变;不操作真实付款,不重写已下载文件。提交推送授权单独确认,部署按正式existing及新候选预检进行。
### 2026-09-12 整体宽度统一(已批准本地实施)
报销详情标题与正文、付款详情使用同一外层宽度和边距,移除报销正文独有的1280px居中限制。正文自适应、桌面侧栏320px及手机单列不变。复用当前任务;验收1280/1440/1920px两页整体左右边界及报销标题/正文边界,390px无横向溢出。只维护现有布局,不引入新视觉方案;不改权限或业务动作,提交、部署另批。
### 2026-09-11 最新确认:制单备注只保留报销编号
用户批准用途为“报销款”、备注仅完整报销编号;一张报销单对应一行银行转账,同一付款批次允许多张单,同人同账号不合并。本次复用当前任务承接,付款模板事实同步09-08任务,不新建task。只修改备注映射及回归,不改编号、权限、审批或生产数据;提交、推送和部署另批。
### 2026-09-11 追加:侧栏等宽与票据紧凑展示(已批准)
用户同轮要求“查看完整账号”改为账号旁Eye图标,保留44px触控、title/aria-label及键盘入口;账号仍默认脱敏,权限/角色/状态条件和填写原因、审计流程不变,不改为悬浮或点击即解密。
用户同轮追加“更多”紧随主按钮:报销和付款桌面动作行左对齐,主按钮按内容宽度,更多为相同下拉菜单;不足则换行,不改变手机付款底栏。保留菜单内删除/打印/下载/上传/取消的资格、禁用与确认语义。去掉空动作组件导致的重复分隔线,不隐藏实际撤回或错误信息。
报销详情/审批共用壳与付款详情桌面侧栏统一320px,lg以下仍单列,操作在上、进度在下;不改其他业务布局。发票桌面按号码、开票方、日期、金额、操作展示,号码沿用预览入口,金额右对齐;窄屏紧凑列表。补充附件保留独立文件列表及已有类型/大小、预览和有权删除入口,空态一行。不新增关联步骤,不隐藏未关联/OCR失败等异常处理。使用合成数据验收等宽、多票据、长名称、预览、附件删除及390px无页面溢出。无权限/API/生产变更,不混入制单备注补丁。
### 2026-09-11 追加需求:付款下一步与详情侧栏一致性(已批准本地实施)
用户反馈财务在报销详情同时看到“去组建付款批次”和已创建、已复核的付款进度。只记录脱敏状态矛盾,不复制真实截图、票据或金额。已发布 fe025e65 源码中右侧下一步及主动作只按报销 status=approved 判断,忽略已由服务端提供的付款阶段;报销进度插在主列材料之后,付款详情则在右栏操作下方。报销审批通过并不等于尚未组批,也不等于银行已经付款。
- 操作、下一步和进度必须消费同一份权威付款阶段,不再各自仅由报销状态猜测。只有明确处于待组批且当前用户有组批权限时才展示组批入口;已存在有效批次时进入该批次,不重复组建。
- 复用既有服务端 processingProgress、付款阶段语义和权限控制;批次入口不可因缺少 targetHref 而推断“未组批”。数据缺失、请求失败或不完整时不展示猜测性的创建入口。
- PC 统一为主列业务内容/材料,右栏上方操作及下一步、下方当前处理进度;进度不在主列重复。长历史按既有授权完整保留,可折叠或进入历史区域,不能因侧栏变窄截掉意见/记录。手机保持单列及底栏动作,同类页面状态/下一步/进度顺序一致,不强做双栏。
- 09-11 用户追加:报销详情“去组建付款批次”主按钮改为“创建批次”,桌面创建/查看批次入口按内容宽度左对齐,不铺满侧栏。仍是进入付款页而不是自动创建;状态、权限、目标与查询参数不变,触控高度维持既有 44px,手机不照搬桌面窄按钮。
- 联合回归发现原付款详情 PC 路由在窄屏同时展示桌面操作卡和手机底栏;属于本轮三类详情布局一致性范围。窄屏只保留手机底栏的同一动作模型,处理进度仍可见,不改批次状态或付款动作权限。
- 首批闭合报销详情、报销审批工作台与付款批次详情的状态/位置一致性;其他业务详情先列实际差异再按归属分批调整,不以“统一”重写全部页面、复制审批引擎或改变各业务状态机。
- 按已批准体验复用现有侧栏/进度样式,不引入新视觉体系。全系统位置原则需在方案获批后同步既有产品规则及共享组件规约,避免现有规则仍允许两种位置。
本阶段验收:无批次、待复核、已复核未制单、已制单未付、有回单待登记、已付款、失败/取消及数据未知分别有准确下一步;角色正反例和批次深链权限正确,同一目标入口不重复。必须在真实隔离角色链中创建/复核批次后返回原报销详情,比较动作、说明与进度;另测已打开页面重新聚焦/刷新,不能只检查付款页成功或源码存在某句文案。桌面与手机覆盖长材料、长意见、滚动、侧栏遮挡/溢出及显示唯一性。生产合成写入、消息发送和部署仍另批,不拿真人单据回放。
### 2026-09-09 后续阶段:退回报销的删除与重建
本阶段归属复用,不重开原 R1/R2 的全部范围;综合顺序与验证见 09-08-reimbursement-payment-closeout 的最新 design/implement。用户已明确业务取向:退回后既能修改原单重提,也能删除旧单再创建报销提交;界面使用“删除”,不要求员工理解底层作废/留痕术语。2026-09-10 行业调研后用户确认本地实施;本追加阶段允许 design 中的 nullable 删除标记迁移,旧 R1/R2 的“无 schema 变更”约束不适用于本阶段。提交、推送及部署仍另批。
- 删除退回单必须保留必要的提交、审批、退回及删除审计记录,不能只把 rejected 加入现有物理删除状态白名单。核对“退回为 draft 且已有 workflow 历史”的路径,不能只按显示状态判断是否可硬删除。
- 删除后旧单不能重提、审批、进入付款或继续修改,不再占据正常待处理列表;有权的历史/审计访问仍遵循原范围,普通列表/搜索/统计/深链行为必须一致。
- 按原申请人/合法代填参与关系设计权限,不能把管理员或 view_all 的全量读取当成删除授权;明确本人和非参与人的正反例。
- 删除与提交/审批/发票绑定并发时,只允许一个合法终态;检查活动审批、付款占用及最终状态,审批中/已通过/已支付不因本次改动变为可删。
- 解除旧单对发票的有效占用,原发票/附件证据不随历史单物理抹掉;只有仍符合当前归属、状态及去重条件的发票才可用于新单,不能覆盖其他单据的绑定或自动转移别人发票。
- 重复删除、旧深链、撤回再删除、发票重新使用均有回归。不批量删除既有真实退回单,是否删除由申请人决定,不替员工执行。
本阶段验收:桌面/手机退回单可取消或确认删除;修改重提保留;历史草稿不物理删除;本人及合法提交人可删,view_all/通配不替代参与关系;活动审批/付款/已付拒绝;列表、搜索、统计、导出和门户计数不展示删除记录;已删除深链只读且无“待处理”指引;发票重用不改变旧单凭证;删除与提交/绑定/重复删除并发及审计失败回滚可复现。
消除报销从审批通过到付款批次创建之间、以及报销回到草稿状态之后的两个运营空隙:财务应能在付款页直接发现并处理尚未组批的已通过报销,同时“全范围”不得暴露他人从未提交的私人草稿,但必须保留对已经进入过流程的退回或撤回草稿的追踪能力。
本任务来自真实业务单据 `0014` 的首次使用反馈。两个 Requirement 共享“状态空隙必须有明确责任人和可见入口”的产品原则,但必须保持代码边界、测试证据和回滚点独立,不能因一项回滚而被迫撤销另一项。
## Scope
- R1 覆盖付款页待组批视图、报销详情下一步深链及报销处理进度中的组批/复核阶段区分。
- R2 覆盖报销列表、详情、材料、提交前检查、全局搜索、导出和报销统计的“本人草稿或已进入流程”服务端读取边界。
- 两项分别实施、分别测试、分别提交和回滚;具体行为以 Requirements 为准,排除项以 Out of Scope 为准。
## Background
- 2026-09-04 对生产做了只读核验:目标单据唯一匹配,状态为 `approved`、未付款、无任何付款批次关联,`payment_batch_v1` 为 `force_on/global`,满足现有 `/payment-batches/candidates` 候选合同;未创建批次或改动单据。
- 同次脱敏统计显示:生产当前只有 1 张 `approved` 且未付款、未被活动批次占用的报销,即本次目标单据;当前 1 张 `draft` 从未产生 workflow 实例,暂无“有历史 workflow 的 draft”。这些计数只用于评估本次行为,不作为测试 fixture 或实现常量。
- 付款首页只查询已经创建的 `PaymentBatch`;候选报销仅在财务点击“新建批次”后才加载。`待我审批` 查询 workflow task,而付款批次复核不是报销 workflow task;组批前也不存在可复核的付款批次。
- 报销详情目前把无批次的 `approved` 投影为“付款复核 / 待安排 / 待财务安排付款”,同时页面下一步仅写“等待财务处理”。批次 `draft` 才真正表示“已创建并提交付款复核”。当前投影把批次级阶段提前套在尚未组批的报销上。
- 报销列表的状态与范围相互独立。具备 `expense.view_all` 的财务、财务负责人、CEO、HR、管理员可在 `草稿 + 全范围` 查看全公司的草稿;经理可查看本人、代填及直属下属草稿。现有详情和材料读取辅助函数也对 `expense.view_all` 无条件放行。
- 报销 `return` 和申请人 `withdraw` 都会把业务状态改回 `draft`,并保留 workflow 实例;从未提交的草稿没有 workflow 实例。仓库统计查询已使用 workflow 实例创建时间作为提交事实,因此“是否存在 workflow 实例”是现有、可推导且无需 schema 变更的“是否进入过流程”判据。
## Requirements
### R1:已通过但未组批的报销必须成为财务可见、可执行的队列
1. 报销 `approved` 且未付款、未进入任何非取消付款批次、付款能力对其部门有效时,必须出现在付款页一级“待组批”视图;候选资格继续由服务端现有候选合同决定,前端不得自行复制状态或部门门禁。
2. “待组批”只对具备 `payment.batch.manage` 的人员显示和查询;仅具备 `payment.batch.review` 的复核人继续查看已创建的付款批次,不获得组批候选或创建能力。
3. 付款页在无批次详情参数时提供“待组批”和“付款批次”两个明确视图。对组批管理员默认进入“待组批”,标签显示服务端返回的候选总数;复核只读角色默认进入“付款批次”。URL 必须可表达当前视图并支持刷新、返回和报销详情深链。
4. “待组批”复用现有候选 API、搜索、分页和创建合同,显示单号、报销人、报销日期、权威总额及摘要。它不是第二套候选计算,也不得同时保留一份隐藏在“新建批次”里的重复候选列表。
5. 财务可从待组批列表选择一张或多张报销并进入现有“创建并提交复核”流程;创建成功后候选立即从待组批队列消失,付款批次视图出现新批次,其状态为“待付款复核”。不得自动组批、自动选择、自动复核或改动 maker-checker 规则。
6. 报销详情在无批次的 `approved` 状态下,把下一步明确写为“等待财务组建付款批次”。具备 `payment.batch.manage` 时提供进入付款页待组批视图的单一入口,并以当前报销编号预置搜索;其他用户只看到状态说明,不暴露付款管理能力。
7. 报销处理进度必须区分“组建付款批次”和“付款复核”:
- 无批次的 `approved`:组批阶段为当前,说明“待财务组建付款批次”;付款复核仍为待处理。
- 已有 `draft` 批次:组批阶段已完成,付款复核为当前,继续使用“待付款复核”。
- 后续 `reviewed/executed/failed/cancelled` 继续由共享付款阶段语义投影,不改变付款写状态机。
8. 列表必须有加载、错误、空态和分页反馈;空态只说明当前没有待组批报销,不把“系统正常”写成解释性噪音。PC 与现有响应式付款页保持同一数据源,移动端不新建第二套付款状态机。
### R2:全范围只展示已经成为业务事实的他人草稿
1. “业务事实”判据固定为:报销单至少存在一个 `entity_type=reimbursement` 的 workflow 实例。不得用当前 workflow 状态、最后一次 outcome、页面标签、单号是否为空或更新时间猜测。
2. 报销人为本人或提交人为本人时,仍可查看自己的全部草稿,不要求存在 workflow 实例。
3. 对他人的 `draft`:
- 从未进入流程、无 workflow 实例:从全范围列表、全局搜索、导出和按报销聚合的统计中排除,直接访问详情或材料接口返回无权限。
- 曾经进入流程、有 workflow 实例:继续按既有全范围角色边界可见,包括审批人退回和申请人撤回后回到 `draft` 的记录。
4. 非 `draft` 状态的既有可见性不变;经理仍限本人、提交人及直属下属,财务/财务负责人/CEO/HR/管理员仍限现有全局范围。本任务不新增角色、不授予 `expense.view_all`、不改变编辑权限。
5. 服务端必须统一强制该判据。前端可以隐藏不可见记录,但不得作为授权边界;详情、普通附件下载、附件预览 URL、完整材料预览和 `POST /reimbursements/:id/precheck` 必须共同收紧,避免通过已知 ID 绕过列表。`precheck` 返回的预算提示、费用标准、审批规则和风险标记同样属于受保护的报销内容。
6. 报销统计与导出不得把他人从未提交的草稿当作正式台账事实;本人草稿是否进入个人视角统计沿用既有行为。付款候选只接受 `approved`,不受本条授权筛选影响。
7. 被排除的记录对无权读取者使用既有自然中文无权限合同,不泄露“该 ID 存在但尚未提交”、workflow 计数或内部判据。
## Acceptance Criteria
- [ ] AC1(R1):以 `approved + unpaid + no active batch + gate enabled` fixture 请求待组批视图,能看到目标报销;任一条件不满足时不出现。生产只读复核能在待组批视图搜索到 `0014`,但自动化不得创建真实付款批次。
- [ ] AC2(R1):付款批次管理员默认看到“待组批”及准确总数,搜索/分页/空态/错误态可用;仅复核角色看不到待组批和创建入口,原有批次复核能力不变。
- [ ] AC3(R1):从报销详情点击入口进入可刷新、可返回的待组批 URL,并预置当前单号;无管理权限时入口为 0,但“等待财务组建付款批次”仍准确显示。
- [ ] AC4(R1):无批次时进度显示“组建付款批次”为当前且“付款复核”为待处理;创建批次后前者完成、后者当前。`draft/reviewed/executed/failed/cancelled` 付款批次的既有语义、通知、权限和写状态机回归通过。
- [ ] AC5(R1):创建成功只刷新候选与批次查询,不出现重复候选列表,不自动执行任何付款写动作;PC 1280px 无横向溢出,移动端可完成搜索、选择和进入创建流程,交互目标不小于现有 44px 约束。
- [ ] AC6(R2):表驱动服务端测试覆盖本人/提交人、全局角色、经理直属团队、无关人员 × `draft` 无 workflow、`draft` 有 returned workflow、`draft` 有 cancelled/withdrawn workflow、所有非 draft 状态;只有“他人且从未进入流程的 draft”被排除。另有负向保护证明当前或历史 workflow 审批人读取自己任务关联的报销不受新过滤误伤。
- [ ] AC7(R2):同一未提交他人草稿在列表、全局搜索、CSV/XLSX 导出和报销统计中均不可见/不计入;直接详情、普通附件、预览 URL、完整材料预览和 `precheck` 均返回无权限。不得只做前端筛选。
- [ ] AC8(R2):退回或撤回后为 `draft` 且有 workflow 实例的报销仍可由原授权范围内人员查看;既有审批历史、只读投影和申请人编辑重提/再次提交路径不变。
- [ ] AC9(独立性):R1 与 R2 分成独立业务提交或至少独立可逆提交单元、独立 focused 测试组;分别回滚任一项时另一项仍可构建并通过自己的测试,不需要 schema、migration、seed、flag 或生产数据修正。
- [ ] AC10(门禁):前后端 focused 测试、前端 typecheck/build、UI strict/self-test、Prisma validate、workflow/权限过程级回归、Trellis governance 和 `git diff --check` 通过;涉及权限和 workflow 投影,实施后必须进行只读 review。
- [ ] AC11(部署后):`/ready` 与 bundle marker 等于候选短 SHA,公网文案扫描 findings=0;真实账号只读确认 `0014` 位于待组批且未被自动修改,未提交他人草稿不再可见,退回/撤回历史草稿 fixture 仍可见。真实组批、复核和付款仍由财务人工执行。
## Test Plan
- R1 focused:付款候选资格、manage/review 权限矩阵、待组批 URL/搜索/分页/空态、创建后查询刷新,以及无批次到五种批次状态的进度投影。
- R2 focused:角色与归属 × draft/非 draft × workflow 无/有的表驱动矩阵,并覆盖列表、详情、材料、`precheck`、全局搜索、CSV/XLSX 和统计旁路;单列 workflow reviewer 待办读取的负向保护。
- 回归与门禁:付款 maker-checker、报销退回/撤回/重提、B1/B2、非报销 workflow、前端 typecheck/build、UI strict/self-test、Prisma validate、Trellis governance 和 `git diff --check`。
- 生产验收只读检查候选可见性和授权结果;不自动创建、复核或执行真实付款批次。
## Out of Scope
- 不在本任务替财务创建 `0014` 的付款批次、复核或登记付款。
- 不修改 Prisma schema,不新增 `submitted_at`,不回写历史报销或 workflow 数据。
- 不合并报销 workflow 与付款批次状态机,不把付款复核塞进“待我审批”。
- 不修改 maker-checker、付款账号、回单、网银制单、B1/B2、预算、票据或通知 routing。
- 不改变采购、差旅、请假、补卡的列表、草稿权限或工作流。
- 不借本任务调整 `expense.view_all` 的角色授予;HR/CEO 是否应继续拥有该权限另行评估。
- 不新增批量自动组批、自动付款、真实支付接口或第二套移动付款页。
## Risks and Deferred Items
- workflow 实例存在表示“曾进入流程”,因此会有意保留退回和撤回草稿的全范围可见性;若后续业务要求撤回后重新私有化,必须新增独立产品判据,不能悄悄改成 outcome 白名单。
- 当前数据库无 `submitted_at`;workflow 关系查询需要通过 focused 性能测试确认列表、搜索、导出和统计没有不可接受退化。本任务不以冗余字段或 migration 预优化。
- 全局搜索、导出和统计是列表之外的旁路;若实现评估发现某一旁路无法在本候选安全收紧,必须阻断 R2 发布或拆出明确依赖任务,不能把列表隐藏冒充权限修复完成。
- 真实付款批次创建属于财务业务动作,不作为自动化验收。部署后只证明候选可见、入口可用和数据未被自动修改。