// Package role 提供角色默认信用模板的应用用例。 package role import ( "context" stdErrors "errors" accessauditapp "github.com/break/junhong_cmp_fiber/internal/application/accessaudit" "github.com/break/junhong_cmp_fiber/internal/model" "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" ) // PermissionChecker 检查平台账号是否拥有独立信用模板权限。 type PermissionChecker interface { CheckPermission(ctx context.Context, userID uint, permCode string, platform string) (bool, error) } // DefaultCreditService 更新客户角色的新建代理默认信用模板。 type DefaultCreditService struct { db *gorm.DB permissionChecker PermissionChecker accessAudit accessauditapp.Writer } // NewDefaultCreditService 创建角色默认信用模板服务。 func NewDefaultCreditService(db *gorm.DB, permissionChecker PermissionChecker, accessAudit accessauditapp.Writer) *DefaultCreditService { return &DefaultCreditService{db: db, permissionChecker: permissionChecker, accessAudit: accessAudit} } // Update 更新模板;该操作不扫描或修改任何既有钱包。 func (s *DefaultCreditService) Update(ctx context.Context, roleID uint, enabled bool, limit int64) (*model.Role, error) { operatorID := middleware.GetUserIDFromContext(ctx) if operatorID == 0 { return nil, errors.New(errors.CodeUnauthorized) } if err := s.authorize(ctx, operatorID); err != nil { return nil, err } if err := validateDefaultCredit(enabled, limit); err != nil { return nil, err } var role model.Role var beforeData map[string]any err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Clauses().First(&role, roleID).Error; err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodeRoleNotFound) } return errors.Wrap(errors.CodeInternalError, err, "读取角色失败") } beforeData = defaultCreditAuditData(&role) if role.RoleType != constants.RoleTypeCustomer { return errors.New(errors.CodeInvalidParam, "只有客户角色可以配置新建代理默认信用") } result := tx.Model(&model.Role{}). Where("id = ? AND role_type = ?", roleID, constants.RoleTypeCustomer). Updates(map[string]any{ "default_credit_enabled": enabled, "default_credit_limit": limit, "updater": operatorID, }) if result.Error != nil { return errors.Wrap(errors.CodeInternalError, result.Error, "更新角色默认信用失败") } if result.RowsAffected != 1 { return errors.New(errors.CodeConflict, "角色默认信用已发生变化,请刷新后重试") } role.DefaultCreditEnabled = enabled role.DefaultCreditLimit = limit role.Updater = operatorID if s.accessAudit == nil { return errors.New(errors.CodeInvalidStatus, "角色默认信用审计接缝未配置") } return s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{ ActionCode: constants.AuditActionRoleDefaultCreditUpdated, Summary: "更新角色默认信用模板", Result: constants.AuditResultSuccess, OperatorID: operatorID, Role: &role, BeforeData: beforeData, AfterData: defaultCreditAuditData(&role), }) }) if err != nil { if role.ID != 0 { accessauditapp.RecordFailure(ctx, s.db, s.accessAudit, accessauditapp.ChangeAudit{ ActionCode: constants.AuditActionRoleDefaultCreditUpdated, Summary: "更新角色默认信用模板失败", Result: defaultCreditAuditResult(err), OperatorID: operatorID, Role: &role, BeforeData: beforeData, }, err) } return nil, err } return &role, nil } func defaultCreditAuditData(role *model.Role) map[string]any { return map[string]any{ "role_name": role.RoleName, "role_type": role.RoleType, "default_credit_enabled": role.DefaultCreditEnabled, "default_credit_limit": role.DefaultCreditLimit, } } func defaultCreditAuditResult(err error) string { var appErr *errors.AppError if !stdErrors.As(err, &appErr) { return constants.AuditResultFailed } switch appErr.Code { case errors.CodeInternalError, errors.CodeDatabaseError, errors.CodeRedisError: return constants.AuditResultFailed default: return constants.AuditResultDenied } } func (s *DefaultCreditService) authorize(ctx context.Context, operatorID uint) error { userType := middleware.GetUserTypeFromContext(ctx) if userType == constants.UserTypeSuperAdmin { return nil } if userType != constants.UserTypePlatform || s.permissionChecker == nil { return errors.New(errors.CodeForbidden, "无权限配置角色默认信用") } hasPermission, err := s.permissionChecker.CheckPermission(ctx, operatorID, constants.PermissionRoleDefaultCreditManage, constants.PlatformWeb) if err != nil { return errors.Wrap(errors.CodeInternalError, err, "检查角色默认信用权限失败") } if !hasPermission { return errors.New(errors.CodeForbidden, "无权限配置角色默认信用") } return nil } func validateDefaultCredit(enabled bool, limit int64) error { if limit < 0 { return errors.New(errors.CodeInvalidParam, "默认信用额度不能为负数") } if enabled && limit == 0 { return errors.New(errors.CodeInvalidParam, "启用默认信用时额度必须大于零") } if !enabled && limit != 0 { return errors.New(errors.CodeInvalidParam, "关闭默认信用时额度必须为零") } return nil }