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

94 lines
8.6 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.
# 业务用户组与店铺负责人当前行为
## 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}`(查询店铺负责人导入任务详情)。