22 KiB
22 KiB
杨俊报销就绪
Goal
让已在企业微信通讯录中的杨俊尽快具备真实报销能力,同时避免让真实员工承担首轮试错:先使用通讯录中既有的“测试员工”和“测试主管”两个企微测试成员,在生产 OA 完成一条受控、可清理的报销体验验收;验证通过并清理测试数据后,再请杨俊通过企微进入 OA、创建并提交真实报销,由其真实直属主管马建勇审批,再进入王芝玲负责的财务处理链路。
Background
- 杨俊已存在于管理员导出的企业微信通讯录,因此具备企微成员账号;生产只读体检已确认他尚无 OA 员工记录和企微绑定。
- 上一轮通讯录 apply 只包含两名财务职责目标,明确没有把其余四名成员送入生产输入。
- 报销是当前急需的真实业务,不等待站内通知、入职向导、审批流简化或月度报表等后续产品项。
- 生产写入前需同时确认自动异机备份 timer 的构建合同未因最近部署发生漂移。
- 通讯录单人子集唯一、active、企业邮箱完整、手机号缺失但满足现有 nullable 合同。
- 当前有 37 个 active 费用类型和 1 个 active 报销工作流定义;active 法体为 0,但代码确认报销创建/提交不读取法体,法体不是本次硬门禁。
- 当前自动备份 daily/watchdog/drill-reminder 和日常巡检 service 的 BUILD_SHA 均与活动 server 不一致;最近一次备份成功发生在该漂移被今晚任务触发之前,不能视为今晚安全。
- 管理员导出的通讯录中已有“测试员工”和“测试主管”两个专用企微测试成员;二者均有唯一账号、部门及联系方式且状态为已激活,但生产 OA 尚无姓名包含“测试”的员工或绑定。
- 受控测试发现生产
OCR_PROVIDER=mock且腾讯 OCR 凭证未配置;合成 PDF 被写入虚构的 Mock 发票字段并直接标记可用。该行为可用于测试,但不得作为杨俊真实发票的正式识别结果。 - 生产已将
OCR_PROVIDER切换为off并重建实际承载后台任务的 server;复验确认票据不进入 OCR 队列、业务字段为空且仍可绑定和提交。ocr_provider因既有非空 schema 默认值仍记录为tencent,但 OCR 尝试数和请求/完成时间均为空;该历史字段语义不作为“已调用腾讯 OCR”的证据。
Requirements
- 生产只读体检必须一次性核对:OA 员工、企微绑定、active 状态、角色、直属主管、主管 active/审批权限、可用费用类型、报销功能开关和审批定义;法体仅记录现状,不作为报销阻断项。
- 同时比较自动备份 systemd unit 中烤入的 BUILD_SHA 与活动 server 构建标识;只输出是否一致,不输出环境文件或宿主路径。
- 若 OA 账号缺失,复用现有通讯录 stdin 路径只筛选目标员工,先 dry-run,另行获批后 apply;初始角色严格为
employee,其余通讯录成员不进入输入。 - 通讯录导入只允许把企微管理员导出的成员资料写入 OA 并建立身份绑定;OA 不调用企微成员 create/update/disable,不反向修改企微姓名、部门、主管、手机号或邮箱。企微成员资料由本人在企微或企微管理员在管理后台维护。
- 将杨俊的
direct_manager_id设置为用户已确认的真实直属主管马建勇;写入前仍需只读确认马建勇为不同、active 且具有expense.approve权限的 OA 员工,不得为了报销绕过审批或扩宽角色。 - 若费用类型或报销工作流缺失,只补足完成报销所需的最小主数据;不为了本次报销新建法体,不顺带整理全部组织架构或导入其余员工。
- 杨俊写入后只做账号、绑定、主管解析、费用类型和提交流程的安全验证;杨俊本人名下不创建测试报销、测试发票或测试付款数据。
- 允许从同一份管理员通讯录中仅筛选既有的“测试员工”和“测试主管”两个企微测试成员,先 dry-run 再 apply;不得新建企微成员,不得把其他真实成员带入输入。
- 两名测试成员进入 OA 后,“测试员工”角色严格为
employee,“测试主管”角色严格为employee + manager;测试员工的 OA 直属主管仅指向测试主管。不得授予finance、finance_mgr、administration或admin,不得借测试查看真实薪资、银行资料或系统管理数据。 - 每次受控验证最多创建一条明确标记“系统测试、非真实业务、禁止付款”的测试报销和一张不含真实票据、银行或个人资料的安全测试 PDF;金额使用最小测试值,测试单不得审批通过或进入财务付款链路。配置复验或固定门禁诊断需要重跑时,每批都必须独立退回、删除报销并归档票据。
- 受控测试必须覆盖:两个测试成员分别通过企微登录、申请人创建/编辑报销、上传安全 PDF、处理 OCR 失败分支(如发生)、绑定票据、提交、主管待办可见及执行“退回”。退回后申请人删除 draft 报销,释放后的测试票据手工归档。
- 测试结束后撤销两个测试成员的 OA 会话并停用其 OA 账号;仅停用 OA,不修改或停用企微中的两个测试成员。后续需要复测时可通过现有 OA 接口重新启用。
- 杨俊上传真实发票前必须消除生产 mock OCR:要么配置并验证真实腾讯 OCR,要么显式关闭 mock 并采用人工录入/核对方案;不得把 Mock 字段展示为真实识别结果。
- 真实报销提交前至少需要一条费用明细和一张已绑定、状态有效的票据;这由员工在真实业务中提供,不用合成数据代替。
- 最近部署后必须重装自动备份三项 service/timer 和日常巡检 timer,使 unit BUILD_SHA 与活动 server 一致;重装后手工触发一次真实自动异机备份,确认源端成功且 ARM 恢复点新鲜,再允许写入杨俊账号或主管关系。
- 第一笔真实业务由员工本人正常发起,目标链路为“员工提交 → 真实主管审批 → 财务处理”;付款批次仍遵守既有 maker-checker。
- 当前小团队取消报销金额分层,所有金额统一按“直属主管 → finance”审批;不得保留无人持有的
finance_mgr节点,也不得因马建勇同时是主管和 CEO 而让同一人重复审批。 - 真实首笔报销暴露审批可读性阻断:待办列表卡片能够进入审批任务详情,但任务详情只显示单号、申请人和金额摘要,没有通往费用明细、发票和附件的业务详情入口。移动端必须在审批任务详情区提供明确的“查看完整报销单”入口,复用既有
/mobile/reimbursements/:id路由和state.from回跳约定;PC 审批任务详情同步提供报销单入口。 - 报销详情当前把后端 ISO UTC 时间直接截取为字符串,附件和审批记录会在中国时区显示早 8 小时;报销链路的日期时间必须复用共享格式化能力并固定按
Asia/Shanghai展示,不修改数据库时间或 API ISO 合同。 - PC 与移动报销详情应按 KISS 原则收敛为“概况 → 明细 → 发票 → 附件 → 审批记录”的业务主线:删除重复状态、重复标题和面向只读用户的操作教学;没有实际内容或动作的辅助区块不渲染,同时保留编辑态必要控件、风险提示和审计信息。
- 生产真机验收确认企微 WebView 可继续运行部署前的旧前端包:公网资源已包含“查看完整报销单”,但存活页面仍只显示报销日期。页面从后台恢复到前台时必须用现有前后端构建标识做一次轻量比对;不一致时只显示用户可控的“发现新版本,点击刷新”,点击后清理旧 PWA 缓存并重载,不自动打断当前页面操作,不扩展为完整更新管理系统。
- 真实审批继续暴露材料查看阻断:PC 能打开普通附件,但 PC 与移动报销详情均没有发票原件入口,企微 WebView 中异步
window.open(blob:)只下载附件而不能预览。企业微信自建应用内必须优先使用官方ww.previewFile/wx.previewFile原生能力查看 PDF;普通 PC 浏览器保留浏览器预览,两端保持“查看原件”的业务能力一致。 - 生产验收发现移动报销列表固定请求
scope=own,导致已有expense.view_all的管理员无法在企微工作台找到杨俊的报销单并代为验证原生预览。移动端必须与 PC 的范围能力对齐:仅对expense.view_all用户显示“我的 / 全部”切换,默认仍为“我的”,选择“全部”时复用现有scope=allAPI;普通员工不显示范围切换,不修改后端权限模型。 - 企业微信原生预览使用准确的文件字节数、带扩展名的文件名和短时签名 URL。原生层不会携带 OA Bearer token 或可靠复用 WebView Cookie,因此附件可以在当前任务内增加仅用于
previewFile的短时 bearer URL 例外;该 URL 必须在签发前执行当前对象级授权和下载理由检查,绑定文件与访问人、短时过期、不得包含长期凭据,并在实际取件时写审计。 - 生产可见性验收进一步确认:费用明细内再次展示并预览关联发票仍然重复,审批人希望一次进入后连续查看本单全部材料。PC 与移动端应统一采用“明细只讲费用、材料一次通览”:费用明细不再渲染发票摘要或原件入口;发票和补充附件仍保留各自后台类型、关联、权限和审计,但只在单一“报销材料”区汇总,并提供一个“查看全部材料”动作。
- 企业微信官方
previewFile({ url, name, size })一次只接收一个文件。为满足企微与 PC 一次进入、连续查看全部 PDF/图片,本任务将整单材料按稳定顺序派生为一个短时合并 PDF:PDF 原页全部复制,图片各占一页;企微调用一次previewFile,PC 交给浏览器内置 PDF 阅读器。合并件仅供审批核对,不替代原件;任一材料加密、损坏、不支持、超限或合并失败时整包失败并回退逐份原件,绝不静默跳过材料或 PDF 页。 - 生产只读核查确认当前真实报销的 3 张票均已由腾讯 OCR 成功处理:号码、日期和金额齐全,无 OCR 错误;2 张为电子火车票,1 张为数电发票。三者按票种均无传统发票代码,电子火车票也没有销售方字段。页面显示“无代码 / 未识别销售方”属于票种展示错误,不得通过重新调用 OCR、伪造代码或把其他主体字段冒充销售方来补值。报销详情 API 应暴露已持久化 OCR 结果中的安全票种分类,前端按票种显示“电子火车票”或“数电发票”、号码、日期、金额及适用主体字段。
- 生产验收发现移动端“查看全部材料”被误放在“报销明细”区,必须归位到“报销材料”区;PC 已在正确区域,不重构其层级。
- 生产只读计时确认当前图片包串行处理约 1.8 秒,且火车票栅格图在企微中视觉上近似空白。新主路径不得继续现场栅格化 PDF;合并由 Node
worker_threads执行并设置材料数、源文件字节、总页数、输出大小和超时上限,避免阻塞单一 server 的事件循环。不启用 Compose worker profile,不引入 PDF.js。 - 合并产物必须可重复生成:材料查询使用显式排序键,缓存键包含报销单 ID、有序材料集合哈希与合并器版本;PDF 元数据和保存选项固定。同样输入独立生成两次必须字节完全相同。签发返回的
fileSize与实际 GET 返回的缓存字节严格一致;缓存缺失或进程重启不能临时拼出另一份字节冒充原签发产物,只能拒绝并让客户端重新签发或降级原件。 - 当前真实报销为“空白报销”创建且未关联差旅申请,现有数据模型没有独立的出差事由、地点和起止日期,因此详情页无法显示完整差旅概要。轻量差旅报销必须直接持久化这四项可选业务字段;存在任一差旅费用明细时,草稿/驳回态提交前必须补齐。既有审批中单据不自动伪造或回填地点;可以只读显示报销说明和明细日期的明确降级值,需完整补齐时由主管退回后申请人修改。
Scope
本轮范围只包括:修复生产 automatic-backup/WARCH3 timer 的构建合同并取得新鲜异机恢复点;从通讯录导入杨俊及两个既有企微测试成员;设置各自真实或测试主管关系;用两个测试成员完成一条可清理的生产报销体验验收;清理测试业务数据并停用测试 OA 账号;最后由杨俊本人使用真实数据发起报销;修复真实审批任务详情到完整报销单的移动端和 PC 入口。所有真实报销内容由杨俊本人提供和提交,所有真实审批与财务处理由对应真实人员完成。
Acceptance Criteria
- 只读体检给出脱敏、可执行的缺口清单,并确认 timer BUILD_SHA 是否与活动构建一致。
- 目标员工在 OA 中为 active,企微绑定唯一,初始业务角色不超过
employee。 - 至少有一个 active 费用类型可用于填单;法体缺失已确认不阻断当前报销创建/提交。
direct_manager_id能解析到真实、active 且具有expense.approve权限的不同员工。- 报销相关功能开关和工作流定义可用;无需差旅申请也能创建报销。
- 自动备份三项 timer 与日常巡检 timer 的 BUILD_SHA 均与活动 server 一致,且 timer 保持 enabled/active。
- timer 修复后生成一份新的成功异机批次,ARM 侧完整性/新鲜度检查通过;该门禁先于任何杨俊生产数据写入。
- 目标员工完成一次真实企微登录并能看到报销入口;主管能看到相应审批入口。
- 两个既有企微测试成员分别成功通过企微登录 OA;没有创建新的企微成员。
- 两个测试成员均通过普通浏览器账号密码登录并完成首次改密;企微 SSO 仍保留为人工确认项。
- 测试员工仅有
employee,测试主管仅有employee + manager,测试主管能看到测试员工提交的待办且执行“退回”。 - 每次受控验证最多产生一条带明确测试标识的报销和一张安全测试 PDF;所有批次均未审批通过、未进入财务或付款链路,并已逐批清理。
- 退回后的测试报销已删除,测试票据已解绑并归档,两个测试 OA 账号已停用且会话已撤销;企微测试成员未被修改或停用。
- 不持久化通讯录筛选文件,不导入杨俊及两个测试成员之外的其他成员,不产生测试付款。
- 生产已显式关闭 mock OCR;
off路径已用测试账号复验,空发票元数据仍可绑定、提交、主管退回和清理,真实使用暂由财务查看 PDF 原件并人工核对。 - 本轮没有调用企微成员写接口;企微成员资料未被 OA 反向修改。
- 生产审批规则已收敛为唯一全金额规则,499.99、500、5000 三个边界均解析为
department_manager → finance,且没有 CEO 重复节点或finance_mgr空节点。 - 移动审批任务详情中的报销摘要区提供明确的“查看完整报销单”入口,进入现有移动报销详情并能通过既有
state.from返回原审批任务。 - PC 审批任务详情提供对应的“查看报销单”入口;两端均不修改待办列表卡片的既有点击行为,不修改审批状态机、权限矩阵或后端数据合同。
- PC、移动报销详情和 PC 审批任务详情中的 ISO 时间按
Asia/Shanghai正确展示,UTC 样例不再直接显示原始小时;数据库与 API 时间合同不变。 - PC 报销详情合并重复概况,附件区不再出现“附件材料/补充附件”双标题;无关联、无预算/风险内容时不显示空辅助区块。
- 移动报销详情顶部不重复状态和教学文案;无实际操作时不显示仅含“当前状态不可编辑”的操作卡,编辑态上传与提交能力保持可用。
- 已登录页面从后台恢复到前台且前后端构建不一致时显示明确刷新提示;构建一致、检查失败或开发构建时不误提示,刷新动作复用缓存清理后重载能力。
- 移动企微报销详情中的发票和 PDF/图片附件均提供“查看原件”,通过官方 JS-SDK 原生预览打开;调用参数包含准确
size和带扩展名的name,不依赖异步弹窗或 WebView 原生 PDF 渲染。 - PC 报销详情中的发票和附件提供对应的“查看原件”,使用短时签名 URL 或现有认证下载能力;两端审批人均只能查看当前报销绑定材料,不能编辑、解绑、删除或获得票据池管理权限。
- 移动报销列表仅对具备
expense.view_all的用户显示“我的 / 全部”切换,默认“我的”;切换“全部”后能通过现有列表进入他人报销详情,普通员工始终只能查看本人列表。 - JS-SDK 签名接口只接受本站允许 origin 的无 fragment 页面 URL,不向客户端、日志或审计暴露 JSAPI ticket、企微 Secret 或 access token;签名失败和非企微环境安全降级。
- 发票/附件预览 URL 的过期、篡改、对象不匹配、缺少下载理由和未授权访问均被拒绝;实际文件响应保留审计,用户已确认能在企微查看当前真实报销材料。
- PC 与移动端费用明细不再展示或预览关联发票;
linkedItemId数据关系继续保留,仅不在费用明细 UI 重复呈现。 - PC 与移动端单一“报销材料”区显示发票与补充附件计数,并提供一个“查看材料合并预览”动作;企微调用一次原生
previewFile,PC 用浏览器内置阅读器打开同一份合并 PDF。 - 合并预览只包含当前有权查看的报销所绑定发票与补充附件,按“发票 → 补充附件、各自创建时间再按 ID、PDF 内原页序”生成;多页 PDF 不漏页,图片各占一页,短时授权、审计、全部上限和整包失败降级均有验证。
- 票据摘要按 OCR
documentCategory展示正确票种与适用字段;数电发票和电子火车票不再出现误导性的“无代码”,电子火车票不再出现“未识别销售方”。当前真实票据不重跑 OCR、不改原始识别数据。 - 移动端材料合并预览动作仅出现在“报销材料”区,不占用“报销明细”的主操作位。
- 合并在
worker_threads中受限执行;同样输入生成两次字节完全相同,签发fileSize等于 GET 实际字节,缓存丢失不返回漂移产物。 - 用无业务数据的多页 PDF 与 JPG/PNG/WebP 合成样本验证页数、顺序、25 页边界和企微一次
previewFile;加密、损坏或不可复制 PDF 必须整包失败并回退逐份原件。 - 存在差旅费用明细时,PC/移动详情首部均显示“出差事由、出差地点、起止日期”的轻量概要;草稿/驳回态可编辑且提交校验完整,审批中历史单不伪造缺失字段。
Out of Scope
- 不修改 CEO 本人无主管报销限制,不通过授予
finance_mgr或管理员代批绕过。 - 不重构报销状态机、审批引擎、企微 OAuth 或权限模型。
- 不从 OA 创建、更新或停用企微成员;需要修改企微成员资料时,由本人或企微管理员在企微侧处理。
- 不提前实现 R63–R66,不扩大为全员入职或组织架构治理。
- 不在未获单独批准时执行通讯录 apply、主管/法体写入、生产报销或付款操作。
- 不使用真实发票、真实金额、真实银行资料或真实员工个人资料作为测试材料;不让测试单进入“通过/待财务/付款”状态。
- 不把手机号缺失视为导入阻断项;该员工使用企微或企业邮箱登录,后续按需补手机号。
- 不在本轮顺带修复请假、采购、差旅等其他审批类型的同类“业务单据详情入口”缺口;将其记录为后续统一审批中心体验任务候选。
Test Plan
- Trellis task/governance、敏感扫描、流程与文档门禁、
git diff --check。 - 通讯录聚焦 dry-run 仅输出人数、计划、冲突、跳过和失败计数。
- 生产只读 SQL/Prisma 只返回布尔值和计数,不输出手机号、邮箱、企微 userid、完整账号或原始 payload。
- 使用既有报销 workflow/权限聚焦回归验证主管解析和
expense.approve,不写生产业务单据。 - 前端运行
cd client && npm run typecheck && npm run build,并用聚焦 Playwright 覆盖:移动审批任务详情进入完整报销单、返回原任务后审批动作仍可见,以及 PC 审批任务详情进入报销单。 - 用合成 UTC 时间在聚焦 Playwright 中验证附件时间转换为上海时间,并验证 PC/移动 KISS 信息层级、编辑态关键入口和无动作只读态;不读取生产真实报销内容。
- 用合成
/ready响应验证前台恢复时的构建不一致提示、同版本静默和检查失败静默;不依赖生产真机数据。 - 用合成企微 ticket、签名 URL 和 PDF/图片元数据验证:JS-SDK URL 签名、origin allowlist、原生
previewFile参数、PC fallback、审批人对象级只读授权、附件理由门禁、短时 token 过期/篡改拒绝和实际查看审计;不得使用真实发票或附件。 - 用合成管理员与普通员工权限验证移动报销范围:管理员默认请求
scope=own,切换后请求scope=all并显示他人报销;普通员工不显示“全部”且始终请求scope=own。 - 用合成普通增值税发票、数电发票、电子火车票、多页 PDF 与 JPG/PNG/WebP 补充附件验证 PC/移动一致性:费用明细无发票预览;票种标题不虚构缺失字段;统一材料区计数正确;合并 PDF 包含全部材料并保持顺序;异常/加密 PDF、超限和合并失败可安全降级;编辑态管理动作不回归。