All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m49s
3.9 KiB
3.9 KiB
Context
现有店铺已存在负责人候选和数据范围能力;用户组是新的业务分类,不能复用 RBAC 角色或代理店铺层级。推导关系必须保持实时,避免负责人改组后大量回写店铺造成不一致。
Decisions
- 新增业务用户组表和平台用户—组关联(用户唯一)表;组编码唯一且不可改,停用不删除既有成员关联。
- 店铺不保存组 ID。列表/详情以店铺负责人关联平台用户,再左连接用户组得到组及停用状态;按组筛选同样使用该关系。
- 勾选批量交接采用一次事务:先按操作者数据范围锁定/校验全量店铺及目标用户,再统一更新和写审计。任何校验失败不写入。
- Excel 使用既有异步导入模式逐行事务;每行在数据范围内查询,统一拒绝文案不区分无权与不存在,并持久化任务明细。
- 用户组成员批量设置直接替换关联;不引入组管理员、层级、额外权限或数据范围计算。
管理动作契约
用户组及成员
POST /business-user-groups:超级管理员、平台用户提交code(1~64 字符,未删除组内唯一)、name(1~100 字符)、sort(非负整数)、enabled、remark(最多 500 字符)。成功返回组 ID 与字段;重复编码返回“业务用户组编码已存在”。PUT /business-user-groups/:id:允许更新名称、排序、启停、备注;code永不允许修改。不存在/已删除返回既有资源不存在。DELETE /business-user-groups/:id:请求须带二次确认;存在成员时返回“用户组仍有成员,只能停用或先移走成员”,不物理删除。PUT /business-user-groups/:id/members:请求account_ids非空数组;所有账号必须是启用平台用户且目标组启用。事务内替换每个账号旧组关系,任一账号无效则全量回滚。DELETE /business-user-groups/members使用同一校验清空指定账号归属。成功操作写成员前后审计。
店铺负责人批量交接
PUT /shops/business-owner/batch:请求shop_ids(非空、去重)及business_owner_account_id(有效平台业务员)或显式null(清空)。先按操作者数据范围锁定并校验所有店铺,再统一更新tb_shop.business_owner_account_id并逐店写审计;任何目标无权、不存在、已删除或负责人无效时,返回统一失败且整批无写入。- Excel 导入使用既有异步导入任务;每行提供店铺标识及负责人账号标识或清空标识。每行独立授权、存在性、负责人有效性校验和事务更新;结果保存行号、成功/失败、失败原因、变更前后负责人及汇总。无权和不存在对调用方使用同一错误文案。
读侧投影
- 扩展既有店铺列表、详情、筛选与导出:返回
business_owner_account_id、负责人名称、business_user_group_id、组编码、组名称、组启用状态;组字段从当前负责人—成员关系实时左连接。 - 组筛选只匹配当前负责人所属组;负责人为空或无成员关系时归入“未分组”。历史店铺不回填;负责人改组/停用后下一次读立即反映变化。
Risks / Trade-offs
- 实时 join 增加列表复杂度 → 为负责人和成员关联建立查询索引,不以冗余字段换一致性风险。
- 负责人/分组并发更新 → 店铺交接和用户改组均使用事务与受影响行检查;读取接受当前已提交快照。
- 导入部分成功 → 明确为逐行语义,任务明细是唯一结果来源。
Migration Plan
- 新增成对迁移创建用户组、成员关联和导入/查询索引,不回填历史组归属。
- 部署读侧空组兼容,再启用维护、批量和导入入口。
- 隔离库验证成员唯一、停用保留、实时推导、批量原子失败、导入逐行结果及迁移 up/down/up。