package device import ( "context" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "gorm.io/gorm" "gorm.io/gorm/clause" ) // BatchUpdateRealnamePolicy 批量更新设备实名认证策略,整批校验后在单事务内全成全败。 func (s *Service) BatchUpdateRealnamePolicy(ctx context.Context, req *dto.BatchUpdateAssetRealnamePolicyRequest) (*dto.BatchUpdateAssetRealnamePolicyResponse, error) { if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeEnterprise { return nil, errors.New(errors.CodeForbidden, "企业账号无权修改设备实名认证策略") } ids, err := validateBatchRealnamePolicyRequest(req) if err != nil { return nil, err } var devices []*model.Device err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { query := middleware.ApplyShopFilter(ctx, tx.Model(&model.Device{})).Clauses(clause.Locking{Strength: "UPDATE"}) if err := query.Where("id IN ?", ids).Find(&devices).Error; err != nil { return errors.Wrap(errors.CodeDatabaseError, err, "查询批量设备资产失败") } if len(devices) != len(ids) { return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在") } changedIDs := make([]uint, 0, len(devices)) for _, device := range devices { if device != nil && device.RealnamePolicy != req.RealnamePolicy { changedIDs = append(changedIDs, device.ID) } } if len(changedIDs) > 0 { result := tx.Model(&model.Device{}).Where("id IN ?", changedIDs).Update("realname_policy", req.RealnamePolicy) if result.Error != nil { return errors.Wrap(errors.CodeDatabaseError, result.Error, "批量更新设备实名认证策略失败") } if result.RowsAffected != int64(len(changedIDs)) { return errors.New(errors.CodeConflict, "设备资产状态已变化,请刷新后重试") } } return s.appendDeviceRealnamePolicyBatchAudit(ctx, tx, devices, req.RealnamePolicy) }) if err != nil { result := constants.AuditResultFailed if appErr, ok := err.(*errors.AppError); ok && appErr.Code == errors.CodeForbidden { result = constants.AuditResultDenied } s.recordDeviceRealnamePolicyBatchFailure(ctx, devices, req.RealnamePolicy, result, err) return nil, err } return &dto.BatchUpdateAssetRealnamePolicyResponse{SuccessCount: len(ids), RealnamePolicy: req.RealnamePolicy}, nil } func validateBatchRealnamePolicyRequest(req *dto.BatchUpdateAssetRealnamePolicyRequest) ([]uint, error) { if req == nil || len(req.AssetIDs) == 0 || len(req.AssetIDs) > 500 || !isValidRealnamePolicy(req.RealnamePolicy) { return nil, errors.New(errors.CodeInvalidParam) } seen := make(map[uint]struct{}, len(req.AssetIDs)) ids := make([]uint, 0, len(req.AssetIDs)) for _, id := range req.AssetIDs { if id == 0 { return nil, errors.New(errors.CodeInvalidParam) } if _, exists := seen[id]; exists { return nil, errors.New(errors.CodeInvalidParam, "资产ID不能重复") } seen[id] = struct{}{} ids = append(ids, id) } return ids, nil } func isValidRealnamePolicy(policy string) bool { return policy == constants.RealnamePolicyNone || policy == constants.RealnamePolicyBeforeOrder || policy == constants.RealnamePolicyAfterOrder }