Files
junhong_cmp_fiber/openspec/specs/business-user-group/spec.md
break c7f9e005af
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 1h43m42s
feat(业务用户组): AUG26-003 业务用户组与店铺负责人分组导入
- 迁移 000221:新增 tb_business_user_group、tb_business_user_group_member、tb_shop_business_owner_import_task,成员一账号一行由部分唯一索引保证,店铺所属组按当前负责人实时推导,不回填历史分组。
- 用户组 CRUD、成员改组/清空归属、店铺批量交接(原子失败不部分写入)。
- 店铺负责人 CSV 导入任务:逐行独立事务、逐行明细、任务级与行级失败分离。
- 读侧推导与筛选:未分组、业务线、停用组可筛出并带停用标记。
- 补齐操作审计动作与资源、openapi 清单、发布门禁巡检表清单。
- 归档 add-shop-salesperson-groups 变更并同步 openspec/specs/business-user-group,补齐 AUG26-003 验证证据链。
2026-09-14 16:51:44 +08:00

8.6 KiB
Raw Blame History

业务用户组与店铺负责人当前行为

Purpose

以不改变既有角色和数据范围的方式标记平台用户业务分类,并将店铺负责人和业务用户组的批量维护、推导展示与审计定义为一致的可观察行为。

Requirements

Requirement: 业务用户组生命周期与成员归属

系统 SHALL 允许超级管理员和平台用户维护业务用户组的名称、创建时必填且在未删除组内唯一的稳定编码、可选所属业务线、排序、启用状态和备注;编码创建后 MUST NOT 修改。所属业务线取值范围 MUST 为标品、智能产品、其他三项单值,且 MAY 为空。用户组不得设置上级、层级或组管理员。仅无成员用户组可由超级管理员或平台用户二次确认删除;有成员时只能停用或先移走成员。

每个启用平台用户最多属于一个启用业务用户组。超级管理员和平台用户可选择多个平台用户,批量设置至一个启用组或批量清空归属;设置直接替换原归属,停用组不得作为目标。业务用户组 MUST NOT 改变后台角色、登录、权限、数据范围或店铺具体负责人归属。停用后不得新增成员,已有成员关系保留并显示已停用,管理员仍可将成员改组或清空。平台账号被删除后其成员关系 MUST 保留并继续参与店铺推导。

Scenario: 批量替换平台用户分组

  • WHEN 管理员选择多个启用平台用户并指定一个启用业务用户组
  • THEN 系统将每个目标用户的原分组直接替换为目标组,不改变其角色、数据范围和登录状态,且每个用户至多保留一个分组

Scenario: 停用含成员用户组

  • WHEN 管理员停用仍含平台用户成员的业务用户组
  • THEN 系统保留成员关系并标记组已停用,拒绝新增成员和把该组作为批量目标,但允许后续改组或清空成员

Scenario: 维护用户组所属业务线

  • WHEN 管理员创建或更新业务用户组的所属业务线
  • THEN 系统按标品、智能产品、其他三项单值保存该字段,并允许清空为空值

Requirement: 店铺负责人和所属组实时推导

店铺 SHALL 以当前绑定的平台业务员作为负责人。店铺所属业务用户组及其业务线 MUST 实时由该负责人的当前用户组推导,不得把组 ID 或业务线冗余写入店铺;负责人变更、负责人改组或组停用后,店铺列表、详情和筛选的结果立即按新关系变化。店铺无负责人、负责人无分组时所属组为空;负责人所属组停用时仍返回该组并明确其已停用。

店铺列表与详情 SHALL 返回负责人账号标识、负责人名称、业务用户组标识、组编码、组名称、组启用状态与组业务线。店铺列表 SHALL 支持按业务用户组、按用户组业务线与按未分组筛选;未分组 MUST 包含无负责人与负责人无成员关系两种情形,停用组的负责人 MUST NOT 归入未分组,且停用组 MUST 可被筛出并携带已停用标记。

Scenario: 负责人改组改变店铺展示

  • WHEN 某平台业务员的业务用户组被替换或清空
  • THEN 该业务员当前负责的所有店铺在列表、详情和按组筛选中即时呈现新的组或空组,无需更新店铺记录

Scenario: 按未分组与业务线筛选店铺

  • WHEN 管理员按未分组或按某一用户组业务线筛选店铺列表
  • THEN 未分组结果包含无负责人与负责人无成员关系的店铺、且不含负责人属于停用组的店铺;业务线结果只包含负责人当前所属组业务线匹配的店铺

Scenario: 停用组仍可筛出

  • WHEN 某业务用户组被停用且其成员仍为部分店铺的负责人
  • THEN 系统仍按该组筛选出这些店铺,并在结果中标记该组已停用

Requirement: 店铺负责人批量交接

超级管理员和平台用户 SHALL 勾选多家店铺,批量设置为一个有效平台业务员或批量清空负责人。批量操作 MUST 在提交前校验全部目标店铺均存在、未删除且可管理,并校验目标业务员为启用平台用户;任一项失败时整批不修改并返回统一失败结果,且 MUST NOT 形成无权、不存在与已删除之间的可枚举差异。成功时必须为每家店铺记录负责人前后值、操作者、时间和入口审计,并同时保留批次汇总结果。

Scenario: 勾选批量包含越权或不存在店铺

  • WHEN 管理员提交的店铺集合中任一店铺不在其可管理范围、已删除或不存在
  • THEN 系统不修改集合中任何店铺负责人,并返回统一失败结果且不泄露该店铺存在性

Scenario: 勾选批量清空负责人

  • WHEN 管理员对多家店铺提交清空负责人的批量请求且全部校验通过
  • THEN 系统在同一事务内清空全部目标店铺负责人,为每家店铺记录负责人前后值审计,店铺所属组随之推导为空

Requirement: 店铺负责人 CSV 导入

超级管理员和平台用户 SHALL 通过 CSV 导入批量设置或清空店铺负责人;导入 MUST 异步执行并返回成功数、失败数与逐行明细。导入入口仅限超级管理员与平台用户,故导入失败原因不含数据范围无权。

导入文件 MUST 为 CSV编码 MUST 为 UTF-8 且 MAY 带 BOM非 UTF-8 时系统 SHALL 按既有 GBK 转换能力尝试解码,仍失败时按任务级失败并给出明确原因。文件首行表头 MUST 与固定列序「店铺编码、操作类型、业务员登录账号、备注」完全一致,不一致时为任务级失败。操作类型 MUST 为「换绑」或「清空」;换绑 MUST 填写业务员登录账号,清空 MUST NOT 填写业务员登录账号。备注可选,填写时 MUST 写入该行审计。店铺 MUST 以店铺编码唯一定位,业务员 MUST 以登录账号唯一定位。

每行 MUST 独立校验与执行:有效行成功更新,失败行 MUST 保留原值且不影响其他已成功行;结果 MUST 保存行号(自数据首行起计,表头不计入)、成功或失败状态与失败原因。任务级失败与行级失败 MUST 分开记录,任务级失败不产生行明细。导入 MUST NOT 设置行数硬上限。所有实际变更 MUST 记录店铺负责人前后值与行备注审计。

行级失败原因 MUST 限定为:店铺编码不存在或已删除、操作类型非法、换绑未填写业务员登录账号、清空却填写了业务员登录账号、业务员登录账号不存在或非启用平台用户、行格式错误。任务级失败原因 MUST 覆盖:文件格式或表头不符、编码无法解码、文件无数据行。

Scenario: 导入包含有效和无效行

  • WHEN 店铺负责人 CSV 导入同时包含可成功换绑或清空的行与校验失败的行
  • THEN 系统更新每个有效行、保留失败行原值,并返回逐行行号、失败原因及成功与失败汇总

Scenario: 表头或编码不符整批失败

  • WHEN 上传文件的表头与固定列序不一致,或文件既非合法 UTF-8 又无法按既有 GBK 转换能力解码
  • THEN 系统不处理任何行、不产生行明细,并返回明确的任务级失败原因

Scenario: 换绑与清空字段互斥

  • WHEN 某行操作类型为换绑但业务员登录账号为空,或操作类型为清空但填写了业务员登录账号
  • THEN 该行失败并保留店铺原负责人,其他行照常处理

可达操作索引

本节只用于入口导航,不是行为 Requirement业务义务以上述 Requirements 为准。

业务用户组维护

POST /api/admin/business-user-groups(新增业务用户组);GET /api/admin/business-user-groups(业务用户组列表);GET /api/admin/business-user-groups/{id}(业务用户组详情);PUT /api/admin/business-user-groups/{id}(修改业务用户组);DELETE /api/admin/business-user-groups/{id}(删除无成员业务用户组)。

业务用户组成员归属

PUT /api/admin/business-user-groups/{id}/members(批量设置平台用户业务用户组归属);DELETE /api/admin/business-user-groups/members(批量清空平台用户业务用户组归属)。

店铺负责人批量交接

PUT /api/admin/shops/business-owner/batch(批量设置或清空店铺负责人)。

店铺负责人 CSV 导入

POST /api/admin/shops/business-owner-imports(创建店铺负责人 CSV 导入任务);GET /api/admin/shops/business-owner-imports(查询店铺负责人导入任务列表);GET /api/admin/shops/business-owner-imports/{id}(查询店铺负责人导入任务详情)。