wms-be/modules/user/repository/user_repository.go

443 lines
12 KiB
Go

package repository
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/google/uuid"
"gorm.io/gorm"
)
type (
UserRepository interface {
Register(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error)
GetUserById(ctx context.Context, tx *gorm.DB, userId string) (entities.M_User, error)
GetUserByEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, error)
GetUserByUsername(ctx context.Context, tx *gorm.DB, username string) (entities.M_User, error)
CheckEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, bool, error)
CheckUsername(ctx context.Context, tx *gorm.DB, username string) (entities.M_User, bool, error)
Update(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error)
Delete(ctx context.Context, tx *gorm.DB, userId string) error
SwitchRole(ctx context.Context, tx *gorm.DB, userId string, roleId string) (entities.M_User, error)
GetAll(ctx context.Context, tx *gorm.DB) ([]entities.M_User, error)
GetUserWarehouses(ctx context.Context, tx *gorm.DB, userId string) ([]entities.MWarehouseEntity, error)
SwitchWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) (entities.M_User, error)
AssignWarehousesToUser(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) (entities.M_User, error)
RemoveWarehousesFromUser(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) (entities.M_User, error)
ClearUserWarehouses(ctx context.Context, tx *gorm.DB, userId string) error
AddUserWarehouses(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) error
AddUserWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) error
RemoveUserWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) error
BulkCreate(ctx context.Context, tx *gorm.DB, users []entities.M_User) error
}
userRepository struct {
db *gorm.DB
}
)
// BulkCreate implements UserRepository.
func (r *userRepository) BulkCreate(ctx context.Context, tx *gorm.DB, users []entities.M_User) error {
if tx == nil {
tx = r.db
}
if err := tx.WithContext(ctx).Create(&users).Error; err != nil {
return err
}
return nil
}
// GetUserWarehouses implements UserRepository.
func (r *userRepository) GetUserWarehouses(ctx context.Context, tx *gorm.DB, userId string) ([]entities.MWarehouseEntity, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
// Preload relasi UserWarehouses dan Warehouse
if err := tx.WithContext(ctx).
Preload("UserWarehouses.Warehouse").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return nil, err
}
var warehouses []entities.MWarehouseEntity
for _, uw := range user.UserWarehouses {
warehouses = append(warehouses, uw.Warehouse)
}
return warehouses, nil
}
// AddUserWarehouse implements UserRepository.
func (r *userRepository) AddUserWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) error {
if tx == nil {
tx = r.db
}
uid := uuid.MustParse(userId)
wid := uuid.MustParse(warehouseId)
// Hapus dulu relasi yang sama jika ada
if err := tx.WithContext(ctx).
Where("user_id = ? AND warehouse_id = ?", uid, wid).
Delete(&entities.MUserWarehouseEntity{}).Error; err != nil {
return err
}
// Insert relasi baru
entity := entities.MUserWarehouseEntity{
ID: uuid.New(),
UserID: uid,
WarehouseID: wid,
}
if err := tx.WithContext(ctx).Create(&entity).Error; err != nil {
return err
}
return nil
}
// RemoveUserWarehouse implements UserRepository.
func (r *userRepository) RemoveUserWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) error {
if tx == nil {
tx = r.db
}
// Delete specific warehouse relation
if err := tx.WithContext(ctx).
Where("user_id = ? AND warehouse_id = ?", userId, warehouseId).
Delete(&entities.MUserWarehouseEntity{}).Error; err != nil {
return err
}
return nil
}
func (r *userRepository) ClearUserWarehouses(ctx context.Context, tx *gorm.DB, userId string) error {
return tx.WithContext(ctx).
Where("user_id = ?", userId).
Delete(&entities.MUserWarehouseEntity{}).Error
}
func (r *userRepository) AddUserWarehouses(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) error {
assignments := make([]entities.MUserWarehouseEntity, 0, len(warehouseIds))
uid := uuid.MustParse(userId)
for _, wid := range warehouseIds {
assignments = append(assignments, entities.MUserWarehouseEntity{
ID: uuid.New(),
UserID: uid,
WarehouseID: uuid.MustParse(wid),
})
}
return tx.WithContext(ctx).Create(&assignments).Error
}
// AssignWarehousesToUser implements UserRepository.
func (r *userRepository) AssignWarehousesToUser(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
// Remove duplicates
warehouseMap := make(map[string]struct{})
for _, wid := range warehouseIds {
warehouseMap[wid] = struct{}{}
}
var uniqueWarehouseIds []string
for wid := range warehouseMap {
uniqueWarehouseIds = append(uniqueWarehouseIds, wid)
}
// Prepare assignments
var assignments []entities.MUserWarehouseEntity
for _, wid := range uniqueWarehouseIds {
assignments = append(assignments, entities.MUserWarehouseEntity{
ID: uuid.New(),
UserID: uuid.MustParse(userId),
WarehouseID: uuid.MustParse(wid),
})
}
// Insert assignments, ignore duplicates due to unique index
if err := tx.WithContext(ctx).Create(&assignments).Error; err != nil {
return entities.M_User{}, err
}
// Reload user with updated warehouses
var user entities.M_User
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Roles").
Preload("Warehouses").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
// RemoveWarehousesFromUser implements UserRepository.
func (r *userRepository) RemoveWarehousesFromUser(ctx context.Context, tx *gorm.DB, userId string, warehouseIds []string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
// Remove assignments
if err := tx.WithContext(ctx).
Where("user_id = ? AND warehouse_id IN ?", userId, warehouseIds).
Delete(&entities.MUserWarehouseEntity{}).Error; err != nil {
return entities.M_User{}, err
}
// Reload user with updated warehouses
var user entities.M_User
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Roles").
Preload("Warehouses").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
// SwitchWarehouse implements UserRepository.
func (r *userRepository) SwitchWarehouse(ctx context.Context, tx *gorm.DB, userId string, warehouseId string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
// Get user with warehouses
if err := tx.WithContext(ctx).
Preload("Warehouses").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
var warehouse entities.MWarehouseEntity
if err := tx.WithContext(ctx).
Where("id = ?", warehouseId).
Take(&warehouse).Error; err != nil {
return entities.M_User{}, err
}
// Remove all existing warehouse relations for this user
if err := tx.WithContext(ctx).
Where("user_id = ?", userId).
Delete(&entities.MUserWarehouseEntity{}).Error; err != nil {
return entities.M_User{}, err
}
// Add new warehouse relation
newUserWarehouse := entities.MUserWarehouseEntity{
UserID: user.ID,
WarehouseID: warehouse.ID,
}
if err := tx.WithContext(ctx).Create(&newUserWarehouse).Error; err != nil {
return entities.M_User{}, err
}
// Reload user with updated warehouses
if err := tx.WithContext(ctx).
Preload("Warehouses").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
// GetAll implements UserRepository.
func (r *userRepository) GetAll(ctx context.Context, tx *gorm.DB) ([]entities.M_User, error) {
if tx == nil {
tx = r.db
}
var users []entities.M_User
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Roles").
Find(&users).Error; err != nil {
return nil, err
}
return users, nil
}
// CheckUsername implements UserRepository.
func (r *userRepository) CheckUsername(ctx context.Context, tx *gorm.DB, username string) (entities.M_User, bool, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
if err := tx.WithContext(ctx).Where("username = ?", username).Take(&user).Error; err != nil {
return entities.M_User{}, false, err
}
return user, true, nil
}
// GetUserByUsername implements UserRepository.
func (r *userRepository) GetUserByUsername(ctx context.Context, tx *gorm.DB, username string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
if err := tx.WithContext(ctx).
Preload("Roles").
Preload("Client").
Preload("Warehouses").
Where("username = ?", username).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
// SwitchRole implements UserRepository.
func (r *userRepository) SwitchRole(ctx context.Context, tx *gorm.DB, userId string, roleId string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
// Preload UserRoles dan Role di dalamnya
if err := tx.WithContext(ctx).
Where("id = ?", userId).
Preload("UserRoles.Role").
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
var role entities.M_Role
if err := tx.WithContext(ctx).Where("id = ?", roleId).Take(&role).Error; err != nil {
return entities.M_User{}, err
}
// Ganti semua role user dengan role baru (hapus yang lama, insert yang baru)
if err := tx.WithContext(ctx).
Where("user_id = ?", userId).
Delete(&entities.M_User_Role{}).Error; err != nil {
return entities.M_User{}, err
}
newUserRole := entities.M_User_Role{
UserID: user.ID,
RoleID: role.ID,
}
if err := tx.WithContext(ctx).Create(&newUserRole).Error; err != nil {
return entities.M_User{}, err
}
// Ambil ulang user beserta roles-nya
if err := tx.WithContext(ctx).
Where("id = ?", userId).
Preload("UserRoles.Role").
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
func (r *userRepository) Register(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
if err := tx.WithContext(ctx).Create(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
func (r *userRepository) GetUserById(ctx context.Context, tx *gorm.DB, userId string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Roles").
Preload("Warehouses").
Where("id = ?", userId).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
func (r *userRepository) GetUserByEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Roles").
Preload("Warehouses").
Where("email = ?", email).
Take(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
func (r *userRepository) CheckEmail(ctx context.Context, tx *gorm.DB, email string) (entities.M_User, bool, error) {
if tx == nil {
tx = r.db
}
var user entities.M_User
if err := tx.WithContext(ctx).Where("email = ?", email).Take(&user).Error; err != nil {
return entities.M_User{}, false, err
}
return user, true, nil
}
func (r *userRepository) Update(ctx context.Context, tx *gorm.DB, user entities.M_User) (entities.M_User, error) {
if tx == nil {
tx = r.db
}
if err := tx.WithContext(ctx).Updates(&user).Error; err != nil {
return entities.M_User{}, err
}
return user, nil
}
func (r *userRepository) Delete(ctx context.Context, tx *gorm.DB, userId string) error {
if tx == nil {
tx = r.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_User{}, "id = ?", userId).Error; err != nil {
return err
}
return nil
}
func NewUserRepository(db *gorm.DB) UserRepository {
return &userRepository{
db: db,
}
}