backend/tmp/reborn/repository/user_role_repository.go

173 lines
4.6 KiB
Go

package repository
import (
"context"
"permission/reborn/domain/entity"
"permission/reborn/domain/errors"
"permission/reborn/domain/repository"
"gorm.io/gorm"
)
type userRoleRepository struct {
db *gorm.DB
}
// NewUserRoleRepository 建立使用者角色 Repository
func NewUserRoleRepository(db *gorm.DB) repository.UserRoleRepository {
return &userRoleRepository{db: db}
}
func (r *userRoleRepository) Create(ctx context.Context, userRole *entity.UserRole) error {
if err := userRole.Validate(); err != nil {
return errors.Wrap(errors.ErrCodeInvalidInput, "invalid user role data", err)
}
if err := r.db.WithContext(ctx).Create(userRole).Error; err != nil {
return errors.Wrap(errors.ErrCodeDBQuery, "failed to create user role", err)
}
return nil
}
func (r *userRoleRepository) Update(ctx context.Context, uid, roleID string) (*entity.UserRole, error) {
var userRole entity.UserRole
result := r.db.WithContext(ctx).
Model(&userRole).
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
Update("role_id", roleID)
if result.Error != nil {
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to update user role", result.Error)
}
if result.RowsAffected == 0 {
return nil, errors.ErrUserRoleNotFound
}
// 重新查詢更新後的資料
if err := r.db.WithContext(ctx).Where("uid = ?", uid).First(&userRole).Error; err != nil {
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get updated user role", err)
}
return &userRole, nil
}
func (r *userRoleRepository) Delete(ctx context.Context, uid string) error {
result := r.db.WithContext(ctx).
Model(&entity.UserRole{}).
Where("uid = ?", uid).
Update("status", entity.StatusDeleted)
if result.Error != nil {
return errors.Wrap(errors.ErrCodeDBQuery, "failed to delete user role", result.Error)
}
if result.RowsAffected == 0 {
return errors.ErrUserRoleNotFound
}
return nil
}
func (r *userRoleRepository) Get(ctx context.Context, uid string) (*entity.UserRole, error) {
var userRole entity.UserRole
err := r.db.WithContext(ctx).
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
First(&userRole).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, errors.ErrUserRoleNotFound
}
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get user role", err)
}
return &userRole, nil
}
func (r *userRoleRepository) GetByRoleID(ctx context.Context, roleID string) ([]*entity.UserRole, error) {
var userRoles []*entity.UserRole
err := r.db.WithContext(ctx).
Where("role_id = ? AND status != ?", roleID, entity.StatusDeleted).
Find(&userRoles).Error
if err != nil {
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get user roles by role id", err)
}
return userRoles, nil
}
func (r *userRoleRepository) List(ctx context.Context, filter repository.UserRoleFilter) ([]*entity.UserRole, error) {
query := r.buildQuery(ctx, filter)
var userRoles []*entity.UserRole
if err := query.Find(&userRoles).Error; err != nil {
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to list user roles", err)
}
return userRoles, nil
}
// CountByRoleID 統計每個角色的使用者數量 (批量查詢,避免 N+1)
func (r *userRoleRepository) CountByRoleID(ctx context.Context, roleIDs []string) (map[string]int, error) {
if len(roleIDs) == 0 {
return make(map[string]int), nil
}
var counts []entity.RoleUserCount
err := r.db.WithContext(ctx).
Model(&entity.UserRole{}).
Select("role_id, COUNT(*) as count").
Where("role_id IN ? AND status != ?", roleIDs, entity.StatusDeleted).
Group("role_id").
Find(&counts).Error
if err != nil {
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to count users by role id", err)
}
result := make(map[string]int)
for _, c := range counts {
result[c.RoleID] = c.Count
}
return result, nil
}
func (r *userRoleRepository) Exists(ctx context.Context, uid string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).
Model(&entity.UserRole{}).
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
Count(&count).Error
if err != nil {
return false, errors.Wrap(errors.ErrCodeDBQuery, "failed to check user role exists", err)
}
return count > 0, nil
}
func (r *userRoleRepository) buildQuery(ctx context.Context, filter repository.UserRoleFilter) *gorm.DB {
query := r.db.WithContext(ctx).
Model(&entity.UserRole{}).
Where("status != ?", entity.StatusDeleted)
if filter.Brand != "" {
query = query.Where("brand = ?", filter.Brand)
}
if filter.RoleID != "" {
query = query.Where("role_id = ?", filter.RoleID)
}
if filter.Status != nil {
query = query.Where("status = ?", *filter.Status)
}
return query
}