Files
qipai/docs/devlogs/2026-06-25-M08-B-保洁端.md
T
2026-06-30 17:22:31 +08:00

206 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M08-B 保洁端
## 本次工程增量
- 新增 `2026062525_m08b_cleaner_tasks` 迁移,建立 `qipai_cleaning_tasks``qipai_cleaning_task_events`,覆盖 WAITING、CLAIMED、STARTED、SUBMITTED、COMPLETED、REJECTED、EXEMPT、SETTLED、CANCELLED 状态和事件追踪。
- 权限补齐 `cleaning.task.write``cleaning.statistics.read``CLEANER`、门店管理员、租户管理员和平台管理员可获得保洁任务读写与统计能力。
- 新增 `CleaningTaskRepository``/app-api/cleaning/*` 路由:任务大厅、我的任务、接单、开始、提交验收和个人统计均要求登录态与保洁权限。
- 生产 `server.ts` 注入真实保洁仓储,迁移 runner 纳入 M08-B 数据库迁移。
- 小程序新增 `pages/cleaner/tasks`,调用真实 app-api 展示任务大厅、我的任务、待结算统计,并支持接单、开始和提交照片 URL 验收。
- `scripts/check-miniapp-m08-a.mjs` 扩展为同时检查 M08-A 顾客端与 M08-B 保洁端页面注册和真实接口调用。
## 2026-06-26 增量
- `/app-api/cleaning/tasks/:taskId/photos` 接入受控图片上传:保洁员必须登录且拥有当前任务,任务状态必须为 `STARTED``REJECTED`,上传后复用 `MediaStorage` 压缩为 WebP 并返回固定 `https://api.txyundm.cn/uploads/...` URL。
- `/app-api/cleaning/tasks/:taskId/submit` 改为必须提交至少一张照片;`REJECTED` 任务允许再次提交,提交后清空驳回原因并记录事件。
- 新增 `/app-api/cleaning/tasks/:taskId/rework`,保洁员可将本人 `REJECTED` 任务重新转为 `STARTED`,清空旧照片和驳回原因,进入补做流程。
- `OrderStateRepository` 在订单状态进入 `FINISHED` 时通过同一事务调用 `CleaningTaskRepository.createForFinishedOrder`,按 `order_id` 唯一键幂等创建 `WAITING` 保洁任务并写入 `AUTO_CREATE` 事件。
- 小程序保洁端将手工照片 URL 文本框改为相机/相册选择图片,上传成功后再提交验收;驳回任务显示原因并提供“重做”入口。
- 修复 `marketing-benefit-service.test.mjs` 中固定订单时间导致 2026-06-26 后自然过期的问题,改为相对未来时间,避免测试随日期漂移失效。
## 2026-06-26 继续增量
- 新增管理侧保洁任务查询 `/admin-api/cleaning/tasks`,按管理员门店范围和状态筛选任务。
- 新增管理侧指派 `/admin-api/cleaning/tasks/:taskId/assign`,指派前校验被指派用户为有效 `CLEANER` 且拥有任务门店范围。
- 新增管理侧验收 `/admin-api/cleaning/tasks/:taskId/complete`,将 `SUBMITTED` 任务转为 `COMPLETED` 并记录事件。
- 新增管理侧驳回 `/admin-api/cleaning/tasks/:taskId/reject`,写入驳回原因并允许保洁端进入补做链路。
- 新增 `/admin-api/cleaning/settlement-candidates`,返回 `COMPLETED` 且未结算的任务,作为后续结算单生成前置。
## 2026-06-26 结算增量
- 新增 `2026062626_m08b_cleaning_settlements` 迁移,建立保洁结算单主表和明细表,任务明细唯一进入一个结算单。
- 新增 `cleaning.settlement.read``cleaning.settlement.write` 权限,保洁员可读本人结算相关能力,门店/租户/平台管理员可生成和确认结算。
- 新增 `GET /admin-api/cleaning/settlements``POST /admin-api/cleaning/settlements``POST /admin-api/cleaning/settlements/:id/confirm`,支持从已完成未结算任务生成 `DRAFT` 结算单并确认到 `CONFIRMED`
- 结算生成会锁定当前候选任务,写入结算明细,固化任务奖励金额,并把任务转为 `SETTLED`,避免同一任务重复结算。
- 新增 `POST /admin-api/cleaning/reclaim-timeouts`,可按分钟阈值和数量限制回收超时停留在 `CLAIMED`/`STARTED` 的任务,恢复到任务大厅。
## 2026-06-26 多人协作增量
- 新增 `2026062627_m08b_cleaning_collaboration` 迁移,建立 `qipai_cleaning_task_members`,支持 `LEAD` 负责人和 `ASSIST` 协作者、成员分账金额、移除和成员维度结算时间。
- 调整 `qipai_cleaning_settlement_items`,新增 `cleaner_user_id`,唯一键从“任务唯一”升级为“任务 + 保洁员唯一”,允许同一协作任务按成员分别进入不同保洁员结算单。
- `CleaningTaskRepository` 在接单、指派和验收时自动维护负责人成员;重新指派会撤掉旧未结算负责人,避免同一任务出现多个有效 `LEAD`
- 新增管理侧成员接口:查看成员、添加/更新协作者、移除未结算协作者。协作者必须拥有 `CLEANER` 角色和任务门店范围,协作者分账总额不能超过任务奖励。
- `GET /app-api/cleaning/tasks/mine``GET /app-api/cleaning/stats` 扩展为负责人/协作者视角;待结算金额按成员分账金额统计。
- 结算生成改为按成员 `reward_cents` 生成明细,单个成员结算后只标记该成员 `settled_at`;所有有效成员均结清后任务才整体转为 `SETTLED`
## 2026-06-27 发放闭环增量
- 新增 `2026062728_m08b_cleaning_payouts` 迁移,为 `qipai_cleaning_settlements` 增加 `paid_by``payout_channel``payout_reference``payout_error`,记录保洁结算发放操作人、渠道、外部流水号和失败原因。
- 新增 `POST /admin-api/cleaning/settlements/:settlementId/paid`,仅允许管理员将 `CONFIRMED` 结算单标记为 `PAID`,写入发放渠道、流水号、发放人和 `paid_at`,并清空旧失败原因。
- 新增 `POST /admin-api/cleaning/settlements/:settlementId/payout-failure`,仅允许对 `CONFIRMED` 结算单记录发放失败原因,保留 `CONFIRMED` 状态,支持修复外部付款后重试。
- 结算单查询返回新增发放字段,管理端后续可以直接展示发放状态、渠道流水和失败原因。
## 2026-06-27 微信转账适配增量
- `WechatPayClient` 新增微信支付商家转账请求能力,按商户转账单号、转账场景、openid、金额、备注、通知地址和场景报备信息发起 `POST /v3/fund-app/mch-transfer/transfer-bills`,并解析微信转账单号、状态、失败原因和 `package_info`
- 新增 `CleaningPayoutService`,从结算单解析租户、门店、保洁员、金额和状态,复用门店/全局微信收款账户与环境凭据,校验商户号一致、收款账户已授权、保洁员存在微信 openid,再执行真实微信转账或测试 Mock。
- 新增 `QIPAI_CLEANING_PAYOUT_MOCK_ENABLED`,仅非生产环境允许 Mock 发放;生产环境不会因为误配打开 Mock。
- 新增 `2026062729_m08b_cleaning_transfer_state` 迁移,为保洁结算单增加 `payout_state``payout_package_info`,记录 `SUCCESS``FAIL``WAIT_USER_CONFIRM``PROCESSING` 等微信转账中间态。
- 新增 `POST /admin-api/cleaning/settlements/:settlementId/wechat-transfer`,管理员可对 `CONFIRMED` 结算单发起微信转账;成功直接落 `PAID`,失败记录失败原因,待用户确认/处理中则保留 `CONFIRMED` 并写入中间态和微信 package 信息,便于后续查询或回调闭环。
## 2026-06-29 微信转账回调与轮询增量
- `WechatPayClient` 新增商户单号查询微信商家转账接口,按 `out_bill_no` 调用微信查询 API 并解析商户号、微信转账单号、状态、失败原因和转账金额。
- `CleaningPayoutService.syncWechatTransfer` 新增主动轮询闭环:管理员可对已发起微信转账的 `CONFIRMED` 结算单同步微信状态;`SUCCESS` 自动标记 `PAID``FAIL` 记录失败原因,其它中间态继续保留 `CONFIRMED` 并更新 `payout_state`
- `CleaningPayoutService.processWechatTransferNotification` 新增微信转账通知处理:按微信平台证书序列号选择凭据、验签解密原始通知、校验商户号,再通过商户单号或微信转账单号定位结算单并写回成功、失败或中间态。
- 新增 `POST /admin-api/cleaning/settlements/:settlementId/wechat-transfer/sync`,用于后台手动同步或后续定时轮询调用。
- 新增 `POST /app-api/cleaning/wechat-transfer/notify`,免登录接收微信转账回调,使用流式 `preParsing` 捕获原始 body,避免验签因 JSON 重序列化失效。
## 2026-06-29 保洁管理后台增量
- `admin/` 从空目录升级为 Vue3 + Vite + TypeScript + Element Plus 后台工程,构建基址固定为 `/admin/`,生产后台 API 固定为 `https://api.txyundm.cn/admin-api`
- 新增保洁运营首屏,支持后台访问令牌本地保存、任务/结算双标签、待验收/完成/待发放/本页金额概览,并适配桌面、平板和手机浏览器。
- 新增保洁任务管理面板:按状态筛选任务,查看门店/房间/保洁员/成员/奖励/照片数量,支持指派、验收、驳回和超时回收。
- 新增保洁结算管理面板:按状态筛选结算单,支持生成结算单、确认结算、发起微信转账、同步微信转账状态和记录发放失败。
- 新增 `scripts/check-admin-m08-b.mjs` 并接入 Windows `test-all.ps1`,静态检查后台依赖、固定域名、构建基址、M08-B API 封装和关键控件。
## 2026-06-29 微信转账预检增量
- `CleaningPayoutService` 新增 `preflightWechatTransfer`,不触发真实转账,仅读取结算单、收款账户、微信支付凭据元数据和保洁员 openid,返回脱敏商户号、凭据引用、场景 ID、报备项数量、通知地址、平台证书数量和逐项 PASS/WARN/FAIL。
- 新增 `GET /admin-api/cleaning/settlements/:settlementId/wechat-transfer/preflight`,管理员可在真实商户转账前检查结算单状态、金额、收款账户授权、商户号匹配、场景报备配置、通知证书和保洁员 openid。
- 后台结算面板新增“预检”操作和结果弹窗,展示真实转账前置条件是否满足,帮助现场联调前明确缺失项。
- `scripts/check-admin-m08-b.mjs` 扩展检查微信转账预检 API 封装和后台控件。
## 2026-06-30 后台协作与结算详情增量
- 新增 `GET /admin-api/cleaning/settlements/:settlementId`,按租户和门店数据范围返回结算单主信息与固化结算明细,包含任务号、订单号、门店、房间、保洁员、成员分账金额和完成时间。
- 后台任务面板新增“成员”入口,可查看负责人/协作者、分账金额和结算状态,并支持添加/更新协作者与移除未结算协作者。
- 后台结算面板新增“详情”入口,可查看结算单任务明细、转账状态、外部流水、失败原因和备注,避免管理员只能从列表猜测结算口径。
- `scripts/check-admin-m08-b.mjs` 扩展检查协作者管理、结算详情和对应 API 封装。
## 2026-06-30 统计明细增量
- 新增 `GET /admin-api/cleaning/statistics`,支持按开始日期、结束日期和门店 ID 筛选,按登录管理员的租户与门店数据范围裁剪统计。
- 管理侧统计返回任务状态分布、门店任务明细、结算状态金额和成员分账排行,明确待验收、待结算、待发放、已发放和成员分账口径。
- 后台新增“统计”标签页,展示任务状态、结算口径、门店明细和成员分账;首屏四个指标改为使用管理侧统计接口,不再依赖当前分页粗略汇总。
- `scripts/check-admin-m08-b.mjs` 扩展检查统计标签页、统计 API 封装和关键统计展示控件。
## 2026-06-30 保洁员资料管理增量
- `/admin-api/users` 新增 `role` 查询参数,支持后台按 `CLEANER``STAFF``STORE_ADMIN``TENANT_ADMIN` 筛选员工,继续复用员工管理权限和门店数据范围。
- 后台统计页新增“今日/近7天/本月”快捷周期,自动生成闭区间起始日和次日/次月结束日并刷新管理统计。
- 后台新增“保洁员”标签页,支持按状态和关键词筛选保洁员,查看门店范围、备注、最近登录和脱敏 IP。
- 后台保洁员资料管理接入已有员工 API,支持创建 `CLEANER`、编辑姓名/门店范围/备注、启用/停用和重置会话。
## 2026-06-30 统计趋势增量
- 管理侧 `GET /admin-api/cleaning/statistics` 在原有状态分布、门店明细、结算口径和成员分账排行基础上追加 `trend`,按任务创建日期聚合每日任务总数、待验收、完成、驳回、奖励和已发放金额。
- 后台统计页新增“每日趋势”区块,使用响应式条形行展示每日任务量,并并列呈现待验、完成、驳回、奖励和发放金额,方便运营按周期筛选后查看波动。
- `scripts/check-admin-m08-b.mjs` 扩展检查每日趋势控件和发放金额字段,避免后续后台改动丢失趋势展示。
## 2026-06-30 保洁员资料细节增量
- `/admin-api/users` 列表返回新增 `avatarUrl``wechatMiniappBound`,后台可判断保洁员是否已绑定微信小程序 openid,为真实微信转账资料预检提供更直观的人员资料状态。
- 后台“保洁员”列表新增资料标签,展示“已绑微信/未绑微信”和“资料完整/待补资料”,资料完整度按微信绑定、门店范围和姓名综合判断。
- 后台保洁员编辑弹窗补手机号维护,提交时透传 `phone` 到既有员工更新接口,继续保留 `CLEANER` 角色和门店范围约束。
- `scripts/check-admin-m08-b.mjs` 扩展检查微信绑定、资料完整度和保洁员资料标签,`backend/tests/user-management.test.mjs` 覆盖手机号更新透传。
## 2026-06-30 保洁员选择器增量
- 后台任务指派弹窗从手填“保洁员用户 ID”升级为可搜索保洁员选择器,选项展示姓名、用户 ID、脱敏手机号、门店范围和微信绑定状态,降低现场运营输错 ID 的风险。
- 后台任务协作者管理同样接入保洁员选择器,添加/更新协作者前先拦截空选择,并继续保留成员分账金额和备注录入。
- 后台生成保洁结算单接入保洁员选择器,管理员从已加载的 `CLEANER` 列表选择人员后生成结算单,门店 ID 仍作为可选过滤条件。
- `scripts/check-admin-m08-b.mjs` 扩展检查任务、结算组件中的 `el-select``cleanerLabel` 以及选择器样式,避免后续回退到纯 ID 输入。
## 验收结果
- `npm run build``backend/`):PASS。
- `node scripts/check-miniapp-m08-a.mjs`PASS。
- `node tests/cleaning-route.test.mjs`PASS。
- `node tests/migration-contract.test.mjs`PASS。
- `node tests/migration-runner.test.mjs`PASS。
- `npm test``backend/`):PASS。
- 2026-06-26 追加验证:
- `node tests/cleaning-route.test.mjs`PASS,覆盖 `rework` 和照片上传路由。
- `npm test -- --runInBand``backend/`):PASS。
- `node scripts/check-miniapp-m08-a.mjs`PASS。
- 继续增量后 `npm test -- --runInBand``backend/`):PASS,覆盖管理侧指派、验收、驳回和待结算候选路由。
- 结算增量后 `npm test -- --runInBand``backend/`):PASS,覆盖结算迁移、结算单路由和超时回收路由。
- 结算增量后 `node scripts/check-miniapp-m08-a.mjs`PASS。
- 多人协作增量后 `npm run build``backend/`):PASS。
- 多人协作增量后 `node tests/migration-contract.test.mjs`PASS。
- 多人协作增量后 `node tests/migration-runner.test.mjs`PASS。
- 多人协作增量后 `node tests/cleaning-route.test.mjs`:PASS,覆盖成员查看、添加和移除路由。
- 发放闭环增量后 `npm run build``backend/`):PASS。
- 发放闭环增量后 `node tests/migration-contract.test.mjs`PASS。
- 发放闭环增量后 `node tests/migration-runner.test.mjs`PASS。
- 发放闭环增量后 `node tests/cleaning-route.test.mjs`:PASS,覆盖结算发放成功和发放失败记录路由。
- 微信转账适配增量后 `npm run build``backend/`):PASS。
- 微信转账适配增量后 `node tests/wechat-pay.test.mjs`:PASS,覆盖商家转账请求签名与载荷。
- 微信转账适配增量后 `node tests/cleaning-payout-service.test.mjs`:PASS,覆盖真实 API 成功、失败、待确认和 Mock 门禁。
- 微信转账适配增量后 `node tests/cleaning-route.test.mjs`PASS,覆盖微信转账路由。
- 微信转账适配增量后 `node tests/migration-contract.test.mjs`PASS。
- 微信转账适配增量后 `node tests/migration-runner.test.mjs`PASS。
- 微信转账适配增量后 `node scripts/check-miniapp-m08-a.mjs`PASS。
- 微信转账适配增量后 `npm test``backend/`):PASS。
- 微信转账回调与轮询增量后 `npm run build``backend/`):PASS。
- 微信转账回调与轮询增量后 `node tests/wechat-pay.test.mjs`:PASS,覆盖商户单号查询转账单请求。
- 微信转账回调与轮询增量后 `node tests/cleaning-payout-service.test.mjs`:PASS,覆盖主动同步成功/失败/处理中和微信通知成功落库。
- 微信转账回调与轮询增量后 `node tests/cleaning-route.test.mjs`:PASS,覆盖后台同步路由和免登录微信通知路由。
- 微信转账回调与轮询增量后 `npm test``backend/`):PASS。
- 保洁管理后台增量后 `npm run build``admin/`):PASS。
- 保洁管理后台增量后 `npm audit --omit=dev``admin/`):PASS0 vulnerabilities。
- 保洁管理后台增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 微信转账预检增量后 `npm run build``backend/`):PASS。
- 微信转账预检增量后 `node tests/cleaning-payout-service.test.mjs`:PASS,覆盖配置齐全、缺场景报备和缺 openid 的预检结果。
- 微信转账预检增量后 `node tests/cleaning-route.test.mjs`PASS,覆盖后台预检路由。
- 微信转账预检增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 微信转账预检增量后 `npm run build``admin/`):PASS。
- 后台协作与结算详情增量后 `npm run build``backend/`):PASS。
- 后台协作与结算详情增量后 `npm run build``admin/`):PASS。
- 后台协作与结算详情增量后 `node tests/cleaning-route.test.mjs`PASS,覆盖结算单详情路由。
- 后台协作与结算详情增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 后台协作与结算详情增量后 `npm test``backend/`):PASS。
- 统计明细增量后 `npm run build``backend/`):PASS。
- 统计明细增量后 `npm run build``admin/`):PASS。
- 统计明细增量后 `node tests/cleaning-route.test.mjs`PASS,覆盖管理侧统计路由。
- 统计明细增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 统计明细增量后 `npm test``backend/`):PASS。
- 保洁员资料管理增量后 `npm run build``backend/`):PASS。
- 保洁员资料管理增量后 `npm run build``admin/`):PASS。
- 保洁员资料管理增量后 `node tests/user-management.test.mjs`PASS,覆盖 `role=CLEANER` 员工筛选。
- 保洁员资料管理增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 统计趋势增量后 `npm run build``backend/`):PASS。
- 统计趋势增量后 `npm run build``admin/`):PASS。
- 统计趋势增量后 `node tests/cleaning-route.test.mjs`:PASS,覆盖管理统计趋势字段透传。
- 统计趋势增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 保洁员资料细节增量后 `npm run build``backend/`):PASS。
- 保洁员资料细节增量后 `npm run build``admin/`):PASS。
- 保洁员资料细节增量后 `node tests/user-management.test.mjs`PASS,覆盖手机号更新透传。
- 保洁员资料细节增量后 `node scripts/check-admin-m08-b.mjs`PASS。
- 保洁员选择器增量后 `npm run build``admin/`):PASS。
- 保洁员选择器增量后 `node scripts/check-admin-m08-b.mjs`PASS。
## 状态
M08-B 保持 `PARTIAL`。当前已完成保洁端任务大厅、我的任务、接单、开始、照片上传、提交验收、驳回补做、订单结束自动建任务、统计、管理员任务查询、指派、验收、驳回、超时回收、多人协作分账、待结算候选、正式结算单生成、确认、发放成功标记、发放失败记录、微信商家转账 API 适配、转账中间态落库、主动轮询同步、微信转账通知回调、微信转账预检、非生产 Mock 门禁、后台任务成员协作管理、结算单详情、统计明细、保洁员资料管理界面、手机号维护、微信绑定状态、每日统计趋势和任务/协作者/结算保洁员选择器;真实商户现场联调和更完整的后台/小程序管理界面仍待继续。M08-A 的真机合法域名、真实微信支付和实物开门验证按外部条件阻塞保留,不阻断 M08-B 工程推进。
## 提交
- 工程提交:`M08-B保洁员选择器增量`
- 远端校验:待本轮 push 后执行 `HEAD == origin/main`