diff --git a/internal/routes/refund.go b/internal/routes/refund.go index dd01380..81ca7b6 100644 --- a/internal/routes/refund.go +++ b/internal/routes/refund.go @@ -12,11 +12,13 @@ import ( ) // registerRefundRoutes 注册退款管理路由 -// 仅平台用户(超级管理员和平台用户)可访问 +// 平台和代理账号可访问,企业账号禁止访问 func registerRefundRoutes(router fiber.Router, handler *admin.RefundHandler, doc *openapi.Generator, basePath string) { refund := router.Group("/refunds", func(c *fiber.Ctx) error { userType := middleware.GetUserTypeFromContext(c.UserContext()) - if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform { + if userType != constants.UserTypeSuperAdmin && + userType != constants.UserTypePlatform && + userType != constants.UserTypeAgent { return errors.New(errors.CodeForbidden, "无权限访问退款管理功能") } return c.Next() diff --git a/internal/service/refund/service.go b/internal/service/refund/service.go index 8a937bc..cbabd85 100644 --- a/internal/service/refund/service.go +++ b/internal/service/refund/service.go @@ -193,6 +193,9 @@ func (s *Service) Approve(ctx context.Context, id uint, req *dto.ApproveRefundRe if userID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } + if err := ensureRefundProcessor(ctx); err != nil { + return err + } refund, err := s.refundStore.GetByID(ctx, id) if err != nil { @@ -267,6 +270,9 @@ func (s *Service) Reject(ctx context.Context, id uint, req *dto.RejectRefundRequ if userID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } + if err := ensureRefundProcessor(ctx); err != nil { + return err + } now := time.Now() result := s.db.WithContext(ctx). @@ -296,6 +302,9 @@ func (s *Service) Return(ctx context.Context, id uint, req *dto.ReturnRefundRequ if userID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } + if err := ensureRefundProcessor(ctx); err != nil { + return err + } now := time.Now() result := s.db.WithContext(ctx). @@ -318,6 +327,15 @@ func (s *Service) Return(ctx context.Context, id uint, req *dto.ReturnRefundRequ return nil } +// ensureRefundProcessor 确保只有平台侧账号可以处理审批类动作。 +func ensureRefundProcessor(ctx context.Context) error { + userType := middleware.GetUserTypeFromContext(ctx) + if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform { + return nil + } + return errors.New(errors.CodeForbidden, "无权限处理退款申请") +} + // Resubmit 重新提交退款申请 // 条件更新 WHERE status=4(已退回),修改部分字段后重新进入待审批状态 func (s *Service) Resubmit(ctx context.Context, id uint, req *dto.ResubmitRefundRequest) error { diff --git a/internal/store/postgres/refund_store.go b/internal/store/postgres/refund_store.go index d38354f..41932e3 100644 --- a/internal/store/postgres/refund_store.go +++ b/internal/store/postgres/refund_store.go @@ -40,7 +40,7 @@ func (s *RefundStore) GetByID(ctx context.Context, id uint) (*model.RefundReques Select("tb_refund_request.*, tb_shop.shop_name AS shop_name"). Joins("LEFT JOIN tb_shop ON tb_shop.id = tb_refund_request.shop_id AND tb_shop.deleted_at IS NULL"). Where("tb_refund_request.id = ?", id) - query = middleware.ApplyShopFilter(ctx, query) + query = applyRefundScope(ctx, query) if err := query.First(&req).Error; err != nil { return nil, err } @@ -69,7 +69,7 @@ func (s *RefundStore) List(ctx context.Context, opts *store.QueryOptions, filter Model(&model.RefundRequest{}). Select("tb_refund_request.*, tb_shop.shop_name AS shop_name"). Joins("LEFT JOIN tb_shop ON tb_shop.id = tb_refund_request.shop_id AND tb_shop.deleted_at IS NULL") - query = middleware.ApplyShopFilter(ctx, query) + query = applyRefundScope(ctx, query) if filters != nil { if filters.Status != nil { @@ -109,6 +109,23 @@ func (s *RefundStore) List(ctx context.Context, opts *store.QueryOptions, filter return requests, total, nil } +// applyRefundScope 应用退款单专属数据权限。 +// 退款申请对代理按创建人隔离,避免上级代理通过店铺层级看到下级申请。 +func applyRefundScope(ctx context.Context, query *gorm.DB) *gorm.DB { + switch middleware.GetUserTypeFromContext(ctx) { + case constants.UserTypeSuperAdmin, constants.UserTypePlatform: + return query + case constants.UserTypeAgent: + userID := middleware.GetUserIDFromContext(ctx) + if userID == 0 { + return query.Where("1 = 0") + } + return query.Where("tb_refund_request.creator = ?", userID) + default: + return query.Where("1 = 0") + } +} + // FindActiveByOrderID 查找订单关联的活跃退款申请(状态为待审批、已通过) func (s *RefundStore) FindActiveByOrderID(ctx context.Context, orderID uint) (*model.RefundRequest, error) { var req model.RefundRequest