18 KiB
报销状态空隙与财务处理视角
Goal
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:已通过但未组批的报销必须成为财务可见、可执行的队列
- 报销
approved且未付款、未进入任何非取消付款批次、付款能力对其部门有效时,必须出现在付款页一级“待组批”视图;候选资格继续由服务端现有候选合同决定,前端不得自行复制状态或部门门禁。 - “待组批”只对具备
payment.batch.manage的人员显示和查询;仅具备payment.batch.review的复核人继续查看已创建的付款批次,不获得组批候选或创建能力。 - 付款页在无批次详情参数时提供“待组批”和“付款批次”两个明确视图。对组批管理员默认进入“待组批”,标签显示服务端返回的候选总数;复核只读角色默认进入“付款批次”。URL 必须可表达当前视图并支持刷新、返回和报销详情深链。
- “待组批”复用现有候选 API、搜索、分页和创建合同,显示单号、报销人、报销日期、权威总额及摘要。它不是第二套候选计算,也不得同时保留一份隐藏在“新建批次”里的重复候选列表。
- 财务可从待组批列表选择一张或多张报销并进入现有“创建并提交复核”流程;创建成功后候选立即从待组批队列消失,付款批次视图出现新批次,其状态为“待付款复核”。不得自动组批、自动选择、自动复核或改动 maker-checker 规则。
- 报销详情在无批次的
approved状态下,把下一步明确写为“等待财务组建付款批次”。具备payment.batch.manage时提供进入付款页待组批视图的单一入口,并以当前报销编号预置搜索;其他用户只看到状态说明,不暴露付款管理能力。 - 报销处理进度必须区分“组建付款批次”和“付款复核”:
- 无批次的
approved:组批阶段为当前,说明“待财务组建付款批次”;付款复核仍为待处理。 - 已有
draft批次:组批阶段已完成,付款复核为当前,继续使用“待付款复核”。 - 后续
reviewed/executed/failed/cancelled继续由共享付款阶段语义投影,不改变付款写状态机。
- 无批次的
- 列表必须有加载、错误、空态和分页反馈;空态只说明当前没有待组批报销,不把“系统正常”写成解释性噪音。PC 与现有响应式付款页保持同一数据源,移动端不新建第二套付款状态机。
R2:全范围只展示已经成为业务事实的他人草稿
- “业务事实”判据固定为:报销单至少存在一个
entity_type=reimbursement的 workflow 实例。不得用当前 workflow 状态、最后一次 outcome、页面标签、单号是否为空或更新时间猜测。 - 报销人为本人或提交人为本人时,仍可查看自己的全部草稿,不要求存在 workflow 实例。
- 对他人的
draft:- 从未进入流程、无 workflow 实例:从全范围列表、全局搜索、导出和按报销聚合的统计中排除,直接访问详情或材料接口返回无权限。
- 曾经进入流程、有 workflow 实例:继续按既有全范围角色边界可见,包括审批人退回和申请人撤回后回到
draft的记录。
- 非
draft状态的既有可见性不变;经理仍限本人、提交人及直属下属,财务/财务负责人/CEO/HR/管理员仍限现有全局范围。本任务不新增角色、不授予expense.view_all、不改变编辑权限。 - 服务端必须统一强制该判据。前端可以隐藏不可见记录,但不得作为授权边界;详情、普通附件下载、附件预览 URL、完整材料预览和
POST /reimbursements/:id/precheck必须共同收紧,避免通过已知 ID 绕过列表。precheck返回的预算提示、费用标准、审批规则和风险标记同样属于受保护的报销内容。 - 报销统计与导出不得把他人从未提交的草稿当作正式台账事实;本人草稿是否进入个人视角统计沿用既有行为。付款候选只接受
approved,不受本条授权筛选影响。 - 被排除的记录对无权读取者使用既有自然中文无权限合同,不泄露“该 ID 存在但尚未提交”、workflow 计数或内部判据。
Acceptance Criteria
- AC1(R1):以
approved + unpaid + no active batch + gate enabledfixture 请求待组批视图,能看到目标报销;任一条件不满足时不出现。生产只读复核能在待组批视图搜索到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 发布或拆出明确依赖任务,不能把列表隐藏冒充权限修复完成。
- 真实付款批次创建属于财务业务动作,不作为自动化验收。部署后只证明候选可见、入口可用和数据未被自动修改。