Files
junhong_cmp_fiber/internal/handler/admin/business_user_group.go
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

232 lines
7.5 KiB
Go

package admin
import (
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
businessusergroupApp "github.com/break/junhong_cmp_fiber/internal/application/businessusergroup"
shopApp "github.com/break/junhong_cmp_fiber/internal/application/shop"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
businessusergroupQuery "github.com/break/junhong_cmp_fiber/internal/query/businessusergroup"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/response"
)
// BusinessUserGroupHandler 业务用户组与店铺负责人批量交接处理器。
type BusinessUserGroupHandler struct {
service *businessusergroupApp.Service
query *businessusergroupQuery.Query
batchService *shopApp.BatchBusinessOwnerService
validator *validator.Validate
}
// NewBusinessUserGroupHandler 创建业务用户组处理器。
func NewBusinessUserGroupHandler(service *businessusergroupApp.Service, validator *validator.Validate) *BusinessUserGroupHandler {
return &BusinessUserGroupHandler{service: service, validator: validator}
}
// SetQuery 注入业务用户组读取投影。
func (h *BusinessUserGroupHandler) SetQuery(query *businessusergroupQuery.Query) {
h.query = query
}
// SetBatchService 注入店铺负责人批量交接事务脚本。
func (h *BusinessUserGroupHandler) SetBatchService(service *shopApp.BatchBusinessOwnerService) {
h.batchService = service
}
// Create 创建业务用户组。
// POST /api/admin/business-user-groups
func (h *BusinessUserGroupHandler) Create(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
var request dto.CreateBusinessUserGroupRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
result, err := h.service.Create(c.UserContext(), &request)
if err != nil {
return err
}
return response.Success(c, result)
}
// List 查询业务用户组列表。
// GET /api/admin/business-user-groups
func (h *BusinessUserGroupHandler) List(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
var request dto.BusinessUserGroupListRequest
if err := c.QueryParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if h.query == nil {
return errors.New(errors.CodeInternalError, "业务用户组查询尚未配置")
}
result, err := h.query.List(c.UserContext(), request)
if err != nil {
return err
}
return response.SuccessWithPagination(c, result.Items, result.Total, result.Page, result.Size)
}
// Detail 查询业务用户组详情。
// GET /api/admin/business-user-groups/:id
func (h *BusinessUserGroupHandler) Detail(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
id, err := pathID(c)
if err != nil {
return err
}
if h.query == nil {
return errors.New(errors.CodeInternalError, "业务用户组查询尚未配置")
}
result, err := h.query.Detail(c.UserContext(), id)
if err != nil {
return err
}
return response.Success(c, result)
}
// Update 更新业务用户组的名称、业务线、排序、启停与备注;编码不可修改。
// PUT /api/admin/business-user-groups/:id
func (h *BusinessUserGroupHandler) Update(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
id, err := pathID(c)
if err != nil {
return err
}
var request dto.UpdateBusinessUserGroupRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
result, err := h.service.Update(c.UserContext(), id, &request)
if err != nil {
return err
}
return response.Success(c, result)
}
// Delete 二次确认删除无成员的业务用户组。
// DELETE /api/admin/business-user-groups/:id
func (h *BusinessUserGroupHandler) Delete(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
id, err := pathID(c)
if err != nil {
return err
}
var request dto.BusinessUserGroupDeleteRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if !request.Confirm {
return errors.New(errors.CodeInvalidParam, "删除业务用户组必须二次确认")
}
if err := h.service.Delete(c.UserContext(), id); err != nil {
return err
}
return response.Success(c, nil)
}
// SetMembers 批量设置平台用户的业务用户组归属,直接替换原归属。
// PUT /api/admin/business-user-groups/:id/members
func (h *BusinessUserGroupHandler) SetMembers(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
id, err := pathID(c)
if err != nil {
return err
}
var request dto.SetBusinessUserGroupMembersRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
result, err := h.service.SetMembers(c.UserContext(), id, &request)
if err != nil {
return err
}
return response.Success(c, result)
}
// ClearMembers 批量清空平台用户的业务用户组归属。
// DELETE /api/admin/business-user-groups/members
func (h *BusinessUserGroupHandler) ClearMembers(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
var request dto.ClearBusinessUserGroupMembersRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
result, err := h.service.ClearMembers(c.UserContext(), &request)
if err != nil {
return err
}
return response.Success(c, result)
}
// BatchUpdateShopBusinessOwner 勾选店铺批量设置或清空平台业务员负责人。
// PUT /api/admin/shops/business-owner/batch
func (h *BusinessUserGroupHandler) BatchUpdateShopBusinessOwner(c *fiber.Ctx) error {
if err := requirePlatformManagement(c); err != nil {
return err
}
var request dto.BatchUpdateShopBusinessOwnerRequest
if err := c.BodyParser(&request); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
if err := h.validate(&request); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if h.batchService == nil {
return errors.New(errors.CodeInternalError, "店铺负责人批量交接服务尚未配置")
}
result, err := h.batchService.Execute(c.UserContext(), &request)
if err != nil {
return err
}
return response.Success(c, result)
}
func (h *BusinessUserGroupHandler) validate(request any) error {
if h.validator == nil {
return errors.New(errors.CodeInternalError)
}
return h.validator.Struct(request)
}
// requirePlatformManagement 校验调用者仅限超级管理员与平台账号,代理与企业统一返回 403。
func requirePlatformManagement(c *fiber.Ctx) error {
userType := middleware.GetUserTypeFromContext(c.UserContext())
if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
return errors.New(errors.CodeForbidden, constants.PlatformManagementForbiddenMessage)
}
return nil
}