wms-be/modules/maintenance_group/service/maintenance_group_service.go

398 lines
11 KiB
Go

package service
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group/repository"
staticDto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid"
"gorm.io/gorm"
)
type MaintenanceGroupService interface {
Create(ctx context.Context, maintGroup dto.MaintGroupCreateRequest) (dto.MaintGroupResponse, error)
GetById(ctx context.Context, maintGroupId string) (dto.MaintGroupResponse, error)
GetByName(ctx context.Context, name string) (dto.MaintGroupResponse, error)
GetByCode(ctx context.Context, code string) (dto.MaintGroupResponse, error)
// GetAll(ctx context.Context) ([]dto.MaintGroupResponse, error)
Update(ctx context.Context, maintGroup dto.MaintGroupUpdateRequest, maintGroupId string) (dto.MaintGroupResponse, error)
Delete(ctx context.Context, maintGroupId string) error
}
type maintenanceGroupService struct {
maintGroupRepo repository.MaintGroupRepository
maintGroupRoleRepo repository.MaintGroupRoleRepository
maintGroupRoleUserRepo repository.MaintGroupRoleUserRepository
db *gorm.DB
}
// Create implements MaintenanceGroupService.
func (m *maintenanceGroupService) Create(ctx context.Context, req dto.MaintGroupCreateRequest) (dto.MaintGroupResponse, error) {
tx := m.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
clientUUID, err := uuid.Parse(req.ClientID)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
maintGroup := entities.M_MaintenanceGroup{
Code: req.Code,
Name: req.Name,
Description: req.Description,
ClientID: clientUUID,
}
createdGroup, err := m.maintGroupRepo.Create(ctx, tx, maintGroup)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
for _, roleReq := range req.MaintenanceGroupRoles {
roleUUID, err := uuid.Parse(roleReq.RoleID)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
role := entities.M_MaintenanceGroupRole{
MaintenanceGroupID: createdGroup.ID,
RoleID: roleUUID,
Level: roleReq.Level,
}
createdRole, err := m.maintGroupRoleRepo.Create(ctx, tx, role)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
for _, userReq := range roleReq.MaintenanceGroupRoleUsers {
userUUID, err := uuid.Parse(userReq.UserID)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
user := entities.M_MaintenanceGroupRoleUser{
MaintenanceGroupRoleID: createdRole.ID,
UserID: userUUID,
}
_, err = m.maintGroupRoleUserRepo.Create(ctx, tx, user)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
}
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
result, err := m.GetById(ctx, createdGroup.ID.String())
if err != nil {
return dto.MaintGroupResponse{}, err
}
return result, nil
}
// Delete implements MaintenanceGroupService.
func (m *maintenanceGroupService) Delete(ctx context.Context, maintGroupId string) error {
tx := m.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 1. Ambil semua role dari group
roles, err := m.maintGroupRoleRepo.FindByMaintGroupId(ctx, tx, maintGroupId)
if err != nil {
tx.Rollback()
return err
}
// 2. Hapus semua user dari setiap role
for _, role := range roles {
err := m.maintGroupRoleUserRepo.DeleteByMaintGroupRoleID(ctx, tx, role.ID.String())
if err != nil {
tx.Rollback()
return err
}
}
// 3. Hapus semua role dari group
err = m.maintGroupRoleRepo.DeleteByMaintGroupId(ctx, tx, maintGroupId)
if err != nil {
tx.Rollback()
return err
}
// 4. Hapus group
err = m.maintGroupRepo.Delete(ctx, tx, maintGroupId)
if err != nil {
tx.Rollback()
return err
}
// 5. Commit
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return err
}
return nil
}
// GetAll implements MaintenanceGroupService.
// func (m *maintenanceGroupService) GetAll(ctx context.Context) ([]dto.MaintGroupResponse, error) {
// groups, err := m.maintGroupRepo.GetAll(ctx, m.db)
// if err != nil {
// return nil, err
// }
// var responses []dto.MaintGroupResponse
// for _, group := range groups {
// responses = append(responses, dto.MaintGroupResponse{
// ID: group.ID.String(),
// Code: group.Code,
// Name: group.Name,
// Description: group.Description,
// ClientID: group.ClientID.String(),
// // MaintenanceGroupRoles: ...
// })
// }
// return responses, nil
// }
// GetByCode implements MaintenanceGroupService.
func (m *maintenanceGroupService) GetByCode(ctx context.Context, code string) (dto.MaintGroupResponse, error) {
panic("unimplemented")
}
// GetById implements MaintenanceGroupService.
func (m *maintenanceGroupService) GetById(ctx context.Context, maintGroupId string) (dto.MaintGroupResponse, error) {
group, err := m.maintGroupRepo.GetById(ctx, m.db, maintGroupId)
if err != nil {
return dto.MaintGroupResponse{}, err
}
// Mapping client
client := staticDto.IdNameResponse{
ID: group.Client.ID.String(),
Name: group.Client.Name,
}
var roles []dto.MaintenanceGroupRoleResponse
for _, role := range group.MaintenanceGroupRoles {
// Mapping role
roleResp := staticDto.RoleResponse{
ID: role.RoleID.String(),
Name: role.Role.Name, // pastikan entity Role ada field Name
}
var users []dto.MaintenanceGroupRoleUserResponse
for _, user := range role.MaintenanceGroupRoleUsers {
userResp := staticDto.UserResponse{
ID: user.User.ID.String(),
Name: user.User.Name, // pastikan entity User ada field Name
}
users = append(users, dto.MaintenanceGroupRoleUserResponse{
ID: user.ID.String(),
User: userResp,
})
}
roles = append(roles, dto.MaintenanceGroupRoleResponse{
ID: role.ID.String(),
Role: roleResp,
Level: role.Level,
MaintenanceGroupRoleUsers: users,
})
}
return dto.MaintGroupResponse{
ID: group.ID.String(),
Code: group.Code,
Name: group.Name,
Description: group.Description,
Client: client,
MaintenanceGroupRoles: &roles,
}, nil
}
// GetByName implements MaintenanceGroupService.
func (m *maintenanceGroupService) GetByName(ctx context.Context, name string) (dto.MaintGroupResponse, error) {
panic("unimplemented")
}
// Update implements MaintenanceGroupService.
func (m *maintenanceGroupService) Update(ctx context.Context, req dto.MaintGroupUpdateRequest, maintGroupId string) (dto.MaintGroupResponse, error) {
tx := m.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
group, err := m.maintGroupRepo.GetById(ctx, tx, maintGroupId)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
if req.Code != nil {
group.Code = *req.Code
}
if req.Name != nil {
group.Name = *req.Name
}
if req.Description != nil {
group.Description = *req.Description
}
if req.ClientID != nil {
clientUUID, err := uuid.Parse(*req.ClientID)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
group.ClientID = clientUUID
}
updatedGroup, err := m.maintGroupRepo.Update(ctx, tx, group)
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
if req.MaintenanceGroupRoles != nil {
// 1. Ambil semua role lama via repo
oldRoles, err := m.maintGroupRoleRepo.FindByMaintGroupId(ctx, tx, group.ID.String())
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
oldRoleIDs := map[string]bool{}
for _, r := range oldRoles {
oldRoleIDs[r.ID.String()] = true
}
// 2. Upsert roles via repo
newRoleIDs := map[string]bool{}
for _, roleReq := range *req.MaintenanceGroupRoles {
if roleReq.ID != nil {
newRoleIDs[*roleReq.ID] = true
role := entities.M_MaintenanceGroupRole{
ID: uuid.MustParse(*roleReq.ID),
MaintenanceGroupID: group.ID,
RoleID: uuid.MustParse(*roleReq.RoleID),
Level: roleReq.Level,
}
if _, err := m.maintGroupRoleRepo.Update(ctx, tx, role); err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
} else {
role := entities.M_MaintenanceGroupRole{
MaintenanceGroupID: group.ID,
RoleID: uuid.MustParse(*roleReq.RoleID),
Level: roleReq.Level,
}
if _, err := m.maintGroupRoleRepo.Create(ctx, tx, role); err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
}
}
// 3. Hapus role lama yang tidak ada di request via repo
var toDelete []string
for oldID := range oldRoleIDs {
if !newRoleIDs[oldID] {
toDelete = append(toDelete, oldID)
}
}
if len(toDelete) > 0 {
if err := m.maintGroupRoleRepo.DeleteByIds(ctx, tx, toDelete); err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
}
// 4. Untuk setiap role, lakukan upsert pada users via repo
for _, roleReq := range *req.MaintenanceGroupRoles {
var roleID uuid.UUID
if roleReq.ID != nil {
roleID = uuid.MustParse(*roleReq.ID)
} else {
// Handle ambil ID role baru jika perlu
continue
}
oldUsers, err := m.maintGroupRoleUserRepo.FindByRoleId(ctx, tx, roleID.String())
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
oldUserIDs := map[string]bool{}
for _, u := range oldUsers {
oldUserIDs[u.UserID.String()] = true
}
newUserIDs := map[string]bool{}
if roleReq.MaintenanceGroupRoleUsers != nil {
for _, userReq := range *roleReq.MaintenanceGroupRoleUsers {
if userReq.UserID != "" {
newUserIDs[userReq.UserID] = true
userUUID := uuid.MustParse(userReq.UserID)
if !oldUserIDs[userReq.UserID] {
user := entities.M_MaintenanceGroupRoleUser{
MaintenanceGroupRoleID: roleID,
UserID: userUUID,
}
if _, err := m.maintGroupRoleUserRepo.Create(ctx, tx, user); err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
}
}
}
}
var toDeleteUser []string
for oldID := range oldUserIDs {
if !newUserIDs[oldID] {
toDeleteUser = append(toDeleteUser, oldID)
}
}
if len(toDeleteUser) > 0 {
if err := m.maintGroupRoleUserRepo.DeleteByRoleIdAndUserIds(ctx, tx, roleID.String(), toDeleteUser); err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
}
}
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return dto.MaintGroupResponse{}, err
}
result, err := m.GetById(ctx, updatedGroup.ID.String())
if err != nil {
return dto.MaintGroupResponse{}, err
}
return result, nil
}
func NewMaintenanceGroupService(maintGroupRepo repository.MaintGroupRepository, maintGroupRoleRepo repository.MaintGroupRoleRepository, maintGroupRoleUserRepo repository.MaintGroupRoleUserRepository, db *gorm.DB) MaintenanceGroupService {
return &maintenanceGroupService{
maintGroupRepo: maintGroupRepo,
maintGroupRoleRepo: maintGroupRoleRepo,
maintGroupRoleUserRepo: maintGroupRoleUserRepo,
db: db,
}
}