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