From 28be209696a8d8dc02ce1c4643c5ba627bacbe18 Mon Sep 17 00:00:00 2001 From: shunli Date: Sat, 9 May 2026 23:56:44 +0800 Subject: [PATCH] =?UTF-8?q?A2=20=E9=97=AD=E7=8E=AF=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E5=9B=9E=E5=BD=92=E5=B9=B6=E6=B2=BB=E7=90=86=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=BA=93=E6=BC=82=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ client/tests/e2e/workflow-quick-approve.spec.ts | 7 +++++-- issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv | 2 +- ...5-09_22-20-03-db-migration-drift-unblock-regression.csv | 6 +++--- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 619e0377..d394f45e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ .env **/.env +.env.bak-* +**/.env.bak-* server/generated/prisma diff --git a/client/tests/e2e/workflow-quick-approve.spec.ts b/client/tests/e2e/workflow-quick-approve.spec.ts index 64934e69..ce8dbddf 100644 --- a/client/tests/e2e/workflow-quick-approve.spec.ts +++ b/client/tests/e2e/workflow-quick-approve.spec.ts @@ -68,7 +68,7 @@ async function submitLeave(api: Awaited { const employeeClient = await createAuthenticatedApiClient(EMPLOYEE); - const startDate = formatDate(190 + (Date.now() % 40)); + const startDate = formatDate(400 + (Date.now() % 3000)); const reason = `Playwright 快捷通过 ${Date.now()}`; try { @@ -85,9 +85,12 @@ test("E2E 审批列表快捷通过:经理可在待办列表行内直接通过 await (await openNavLink(page, "待我处理")).click(); await expect(page.getByTestId(TEST_IDS.workflow.tasksTable)).toBeVisible(); - const taskRows = page.getByTestId(TEST_IDS.workflow.taskRow).filter({ hasText: submitResult.currentTaskId }); + const taskRows = page.locator( + `[data-testid="${TEST_IDS.workflow.taskRow}"]:has(a[href="/workflow/tasks/${submitResult.currentTaskId}"])`, + ); await expect(taskRows).toHaveCount(1, { timeout: 30_000 }); const taskRow = taskRows.first(); + await expect(taskRow).not.toContainText(submitResult.currentTaskId); await expect(taskRow.getByTestId(TEST_IDS.workflow.quickApprove)).toBeVisible(); await expect(taskRow.getByTestId(TEST_IDS.workflow.detailLink)).toBeVisible(); diff --git a/issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv b/issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv index 78f9fec6..d260108b 100644 --- a/issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv +++ b/issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv @@ -1,6 +1,6 @@ ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes A1,MVP主线代码差距盘点,"对照当前 PRD 和 7 份模块规约,盘点 workflow、reimbursements、invoicePool、wecomAuth、leave、purchaseRequests、contractsRegistry、projects 等现有实现、页面、回归脚本和缺口;本 Issue 不改业务代码。","1) 形成可复用实现、待修缺口和不重复造轮子的清单;2) 明确 A2-A8 的实际改动边界;3) 确认首轮默认不新增公共 API、不新增数据库表;4) 若发现必须新增接口、字段或迁移,拆独立后续 Issue。","流程级验证:按 PRD 的审批、报销、企业微信入口、请假、采购、合同、项目七条主线逐项映射到现有 server/client/tests 文件;命令:rg 检索关键路由、页面和测试;命令:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv。","ripgrep|manual|python3",DONE,DONE,DONE,"server/src/routes/*|client/src/pages/*|client/src/api/*|client/tests/e2e/*|docs/*.md","[]","A1 已完成只读差距盘点,不改业务代码;盘点文档:docs/MVP主线代码差距盘点.md;如后续发现需迁移或新增 API,必须另拆 Issue 并写回滚策略。" -A2,统一审批中心入口与状态收口,"收口 PC /workflow/tasks、移动 /mobile/approvals、业务详情页审批历史和通知 deeplink 的一致性,确保正式审批动作回到 OA 完成。","1) 待办、已办、业务详情页状态一致;2) 审批动作通过、驳回、退回、撤回、转审仍写入 OA 工作流历史;3) 企业微信消息只 deeplink 回 OA,不出现企业微信原生审批入口;4) 并发或已处理任务有明确提示。","流程级验证:提交一条报销或请假审批 -> PC 待办处理 -> 移动待办同步消失或进入已办 -> 业务详情审批历史一致;命令:cd server && ./scripts/regression-workflow-actions.sh;命令:cd client && npm run test:e2e -- workflow-quick-approve.spec.ts mobile-approvals-offline.spec.ts。","bash|npm|playwright|manual",DONE,TODO,TODO,"server/src/routes/workflow.js|server/src/utils/workflow.js|client/src/pages/WorkflowTasksPage.tsx|client/src/pages/MobileApprovalsPage.tsx|client/src/pages/WorkflowTaskDetailPage.tsx","[""A1""]","A2 开发完成且 A2.1 已修正详情页 pending 文案;静态检查通过;回归仍被本地 DB 漂移阻断,已拆数据库治理合同 issues/2026-05-09_22-20-03-db-migration-drift-unblock-regression.csv。" +A2,统一审批中心入口与状态收口,"收口 PC /workflow/tasks、移动 /mobile/approvals、业务详情页审批历史和通知 deeplink 的一致性,确保正式审批动作回到 OA 完成。","1) 待办、已办、业务详情页状态一致;2) 审批动作通过、驳回、退回、撤回、转审仍写入 OA 工作流历史;3) 企业微信消息只 deeplink 回 OA,不出现企业微信原生审批入口;4) 并发或已处理任务有明确提示。","流程级验证:提交一条报销或请假审批 -> PC 待办处理 -> 移动待办同步消失或进入已办 -> 业务详情审批历史一致;命令:cd server && ./scripts/regression-workflow-actions.sh;命令:cd client && npm run test:e2e -- workflow-quick-approve.spec.ts mobile-approvals-offline.spec.ts。","bash|npm|playwright|manual",DONE,DONE,DONE,"server/src/routes/workflow.js|server/src/utils/workflow.js|client/src/pages/WorkflowTasksPage.tsx|client/src/pages/MobileApprovalsPage.tsx|client/src/pages/WorkflowTaskDetailPage.tsx","[""A1""]","A2 开发、审查和回归已完成;A2.1 修正详情页 pending 文案;本地 DB 漂移已通过 hyb_oa_regression 隔离库解阻;workflow 后端回归、PC 快捷审批 E2E、移动审批 E2E、client typecheck/build 均通过。" A3,报销发票OCR主链路收口,"收口上传、OCR 状态、查重、绑定明细、提交审批、付款标记和导出中的体验或状态缺口,优先复用现有 reimbursement 与 invoicePool 实现。","1) 员工能完成报销主流程:上传发票/附件 -> OCR/查重 -> 绑定明细 -> 提交审批;2) 财务能处理重复、付款标记和导出;3) 普通用户页面不出现内部状态码、发票池、绑定整单等不应见文案;4) OCR 失败、重复、附件缺失有业务提示。","流程级验证:创建报销草稿 -> 上传票据 -> OCR 进入终态 -> 绑定明细 -> 提交审批 -> 审批通过 -> 财务付款/导出;命令:cd server && ./scripts/regression-dedup.sh && ./scripts/regression-ocr.sh;命令:cd client && npm run test:e2e -- r102-reimbursement-main-flow.spec.ts invoice-ocr-flow.spec.ts。","bash|npm|playwright|manual",TODO,TODO,TODO,"server/src/routes/reimbursements.js|server/src/routes/invoicePool.js|server/src/routes/invoicePool/*|client/src/pages/ReimbursementDetailPage.tsx|client/src/pages/InvoicePoolPage.tsx|client/src/pages/reimbursement-detail/*|client/src/pages/invoice-pool/*","[""A1"",""A2""]","涉及报销和发票状态;默认不改 OCR provider 和数据库结构,若需 schema/API 变更另拆 Issue。" A4,企业微信入口绑定通知回OA,"收口企业微信 config、登录/绑定、移动落点、通知 deeplink 和脱敏消息,企业微信只作为入口、身份、通知和打卡原始采集边界。","1) 企业微信手机入口默认进入 /mobile;2) 已绑定用户直达,未绑定可回退账号密码;3) 停用员工不得从企业微信进入业务系统;4) 通知内容脱敏且 deeplink 回 OA;5) 通知失败不阻断主业务。","流程级验证:模拟企业微信 UA 访问入口 -> 已绑定进入移动工作台 -> 未绑定回退账号密码 -> 通知 deeplink 打开 OA 审批页;命令:cd client && npm run test:e2e -- wecom-entry.spec.ts wecom-first-bind.spec.ts r124-mobile-entry-matrix.spec.ts;后端补 node --check src/routes/wecomAuth.js。","npm|playwright|node|manual",TODO,TODO,TODO,"server/src/routes/wecomAuth.js|server/src/services/notifications/*|client/src/lib/wecomEntry.ts|client/src/lib/runtimeContext.ts|client/src/lib/notificationLinks.ts","[""A1"",""A2""]","不接企业微信原生审批、不接飞书;涉及真实企业微信凭据时 live smoke 缺配置必须标 SKIP。" A5,请假补卡外出加班审批与考勤口径,"优先收口现有请假审批、团队状态、日历展示和考勤解释边界;首轮不做企业微信打卡 API 同步,不重造定位、人脸、Wi-Fi 或排班。","1) 请假审批状态正确;2) 已批准请假影响团队状态或日历展示;3) 补卡、外出、加班若现有实现不足,先记录缺口或做最小入口收口;4) 文案不引导员工去企业微信原生审批。","流程级验证:员工提交请假 -> 主管/HR 在 OA 审批 -> 团队状态或日历体现结果 -> 驳回/撤回后状态正确;命令:cd client && npm run test:e2e -- leave-flow.spec.ts leave-team-calendar.spec.ts;命令:cd server && node --check src/routes/leave.js。","npm|playwright|node|manual",TODO,TODO,TODO,"server/src/routes/leave.js|server/src/services/leave.js|client/src/pages/LeaveRequestPage.tsx|client/src/pages/MobileLeavePage.tsx|client/src/pages/TeamPresencePage.tsx","[""A1"",""A2""]","首轮不接企业微信打卡同步;若补卡/外出/加班缺运行时能力,A1 后先拆最小 Issue,不扩大到完整考勤系统。" diff --git a/issues/2026-05-09_22-20-03-db-migration-drift-unblock-regression.csv b/issues/2026-05-09_22-20-03-db-migration-drift-unblock-regression.csv index 39dd5f93..b1c8e2a7 100644 --- a/issues/2026-05-09_22-20-03-db-migration-drift-unblock-regression.csv +++ b/issues/2026-05-09_22-20-03-db-migration-drift-unblock-regression.csv @@ -1,5 +1,5 @@ ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes A1,本地测试库迁移漂移事实确认,"只读确认 A2 回归登录 500 的数据库原因,识别 DATABASE_URL 指向、Prisma migrate status、employees 头像列和对应迁移记录。","1) 不输出数据库密码;2) 确认目标库不是生产库;3) 记录是否为单一缺列或更大范围 drift;4) 不修改数据库。","流程级验证:读取脱敏 DATABASE_URL host/db/user;执行 cd server && set -a; . ./.env; set +a; npx prisma migrate status;只读查询 information_schema.columns 和 _prisma_migrations。","node|npx prisma|manual",DONE,DONE,DONE,"server/.env|server/prisma/schema.prisma|server/prisma/migrations/*","[]","已确认 DATABASE_URL 指向 localhost:5432/hyb_oa;employees.avatar_path 缺失且迁移 20260329194000_r43_employee_avatar_contracts 未记录;同时存在多条未应用本地迁移和一个数据库内本地缺失迁移,不能在 A2 内硬修。" -A2,数据库漂移治理方案确认,"为本地/测试库选择安全治理方式:修复当前库迁移历史,或新建干净测试库并重播迁移/种子;禁止碰生产库。","1) 明确治理对象为本地/测试库;2) 明确是否保留当前 hyb_oa 数据;3) 明确回滚方式;4) 方案经人工确认后再执行。","人工确认治理方案;如需保留数据,先导出备份;如切换干净库,确认新 DATABASE_URL 和种子步骤。","manual",TODO,TODO,TODO,"server/.env|server/prisma/migrations/*|server/src/scripts/seed-dev.js","[""A1""]","推荐默认新建干净测试库,避免编辑迁移历史;若必须保留当前库,需单独备份并审查缺失迁移。" -A3,执行本地测试库治理,"按 A2 已确认方案修复本地/测试数据库,使登录和 A2 回归可运行;不修改应用业务代码。","1) /ready 正常;2) baseline 用户可登录;3) prisma migrate status 不再阻塞本地回归;4) 不修改生产配置。","执行已批准的治理命令;验证 cd server && npm run prisma:validate;curl 本地 /ready;调用 /api/auth/login 验证 baseline 用户。","bash|npm|curl|manual",TODO,TODO,TODO,"server/.env|server/prisma/migrations/*|server/src/scripts/seed-dev.js","[""A2""]","涉及数据库变更,执行前必须确认不是生产库;如使用干净测试库,回滚为切回旧 DATABASE_URL。" -A4,A2 回归解阻复跑,"数据库治理后重跑 A2 指定回归,并回填主线开发 CSV 中 A2 的 Review1_Status 和 Regression_Status。","1) workflow 后端回归通过;2) 审批 PC/移动 E2E 通过;3) client typecheck/build 通过;4) 主线 CSV A2 更新为 DONE/DONE/DONE。","cd server && ./scripts/regression-workflow-actions.sh;cd client && npm run test:e2e -- workflow-quick-approve.spec.ts mobile-approvals-offline.spec.ts;cd client && npm run typecheck && npm run build。","bash|npm|playwright|manual",TODO,TODO,TODO,"issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv|server/scripts/regression-workflow-actions.sh|client/tests/e2e/*","[""A3""]","完成后才能继续 A4 企业微信入口/通知收口;未通过前不部署、不通知真机测试。" +A2,数据库漂移治理方案确认,"为本地/测试库选择安全治理方式:修复当前库迁移历史,或新建干净测试库并重播迁移/种子;禁止碰生产库。","1) 明确治理对象为本地/测试库;2) 明确是否保留当前 hyb_oa 数据;3) 明确回滚方式;4) 方案经人工确认后再执行。","人工确认治理方案;如需保留数据,先导出备份;如切换干净库,确认新 DATABASE_URL 和种子步骤。","manual",DONE,DONE,DONE,"server/.env|server/prisma/migrations/*|server/src/scripts/seed-dev.js","[""A1""]","已确认采用新建本地回归库 hyb_oa_regression;旧 hyb_oa 保留不动;回滚为恢复 server/.env.bak-20260509153053 或把 DATABASE_URL 数据库名改回 hyb_oa。" +A3,执行本地测试库治理,"按 A2 已确认方案修复本地/测试数据库,使登录和 A2 回归可运行;不修改应用业务代码。","1) /ready 正常;2) baseline 用户可登录;3) prisma migrate status 不再阻塞本地回归;4) 不修改生产配置。","执行已批准的治理命令;验证 cd server && npm run prisma:validate;curl 本地 /ready;调用 /api/auth/login 验证 baseline 用户。","bash|npm|curl|manual",DONE,DONE,DONE,"server/.env|server/prisma/migrations/*|server/src/scripts/seed-dev.js","[""A2""]","hyb_oa_regression 已应用 46 个迁移并完成 seed:dev;migrate status up to date;/ready 正常;employee baseline 登录返回 access token;未修改生产配置。" +A4,A2 回归解阻复跑,"数据库治理后重跑 A2 指定回归,并回填主线开发 CSV 中 A2 的 Review1_Status 和 Regression_Status。","1) workflow 后端回归通过;2) 审批 PC/移动 E2E 通过;3) client typecheck/build 通过;4) 主线 CSV A2 更新为 DONE/DONE/DONE。","cd server && ./scripts/regression-workflow-actions.sh;cd client && npm run test:e2e -- workflow-quick-approve.spec.ts mobile-approvals-offline.spec.ts;cd client && npm run typecheck && npm run build。","bash|npm|playwright|manual",DONE,DONE,DONE,"issues/2026-05-09_20-57-19-mvp-mainline-dev-kickoff.csv|server/scripts/regression-workflow-actions.sh|client/tests/e2e/*","[""A3""]","A2 workflow 后端回归通过;PC 快捷审批和移动审批 E2E 3 passed;已同步主线 CSV A2 为 DONE/DONE/DONE;仍未部署或进行公网/真机测试。"