feat: Add maintenance group management with CRUD operations and routing

This commit is contained in:
Habib Fatkhul Rohman 2025-10-25 01:35:45 +07:00
parent 1cf875d13c
commit b533554f98
8 changed files with 1013 additions and 0 deletions

View File

@ -0,0 +1,161 @@
package controller
import (
"net/http"
"github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/gin-gonic/gin"
"github.com/samber/do"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
type (
MaintenanceGroupController interface {
Create(ctx *gin.Context)
Update(ctx *gin.Context)
Delete(ctx *gin.Context)
GetById(ctx *gin.Context)
GetAll(ctx *gin.Context)
}
maintenanceGroupController struct {
maintGroupService service.MaintenanceGroupService
db *gorm.DB
logger *logrus.Logger
}
)
func NewMaintenanceGroupController(i *do.Injector, maintGroupService service.MaintenanceGroupService) MaintenanceGroupController {
db := do.MustInvokeNamed[*gorm.DB](i, constants.DB)
logger := do.MustInvokeNamed[*logrus.Logger](i, constants.LOGGER)
return &maintenanceGroupController{
maintGroupService: maintGroupService,
db: db,
logger: logger,
}
}
// Create godoc
// @Summary Create a new maintenance group
// @Description Create a new maintenance group
// @Tags MaintenanceGroup
// @Accept json
// @Produce json
// @Param body body dto.MaintGroupCreateRequest true "Create payload"
// @Success 200 {object} dto.MaintGroupResponse
// @Failure 400 {object} map[string]interface{}
// @Router /maintenance-groups [post]
func (c *maintenanceGroupController) Create(ctx *gin.Context) {
var req dto.MaintGroupCreateRequest
if err := ctx.ShouldBind(&req); err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
ctx.AbortWithStatusJSON(http.StatusBadRequest, res)
return
}
result, err := c.maintGroupService.Create(ctx.Request.Context(), req)
if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_REGISTER_MG, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_REGISTER_MG, result)
ctx.JSON(http.StatusOK, res)
}
// Update godoc
// @Summary Update maintenance group
// @Description Update maintenance group
// @Tags MaintenanceGroup
// @Accept json
// @Produce json
// @Param body body dto.MaintGroupUpdateRequest true "Update payload"
// @Success 200 {object} dto.MaintGroupResponse
// @Failure 400 {object} map[string]interface{}
// @Router /maintenance-groups [put]
func (c *maintenanceGroupController) Update(ctx *gin.Context) {
var req dto.MaintGroupUpdateRequest
if err := ctx.ShouldBind(&req); err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
ctx.AbortWithStatusJSON(http.StatusBadRequest, res)
return
}
id := ctx.Param("id")
result, err := c.maintGroupService.Update(ctx.Request.Context(), req, id)
if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_MG, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_MG, result)
ctx.JSON(http.StatusOK, res)
}
// Delete godoc
// @Summary Delete maintenance group
// @Description Delete maintenance group
// @Tags MaintenanceGroup
// @Accept json
// @Produce json
// @Param id path string true "MaintenanceGroup ID"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Router /maintenance-groups/{id} [delete]
func (c *maintenanceGroupController) Delete(ctx *gin.Context) {
id := ctx.Param("id")
if err := c.maintGroupService.Delete(ctx.Request.Context(), id); err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_MG, err.Error(), nil)
ctx.AbortWithStatusJSON(http.StatusBadRequest, res)
return
}
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_MG, nil)
ctx.JSON(http.StatusOK, res)
}
// GetById godoc
// @Summary Get maintenance group by ID
// @Description Get maintenance group by ID
// @Tags MaintenanceGroup
// @Accept json
// @Produce json
// @Param id path string true "MaintenanceGroup ID"
// @Success 200 {object} dto.MaintGroupResponse
// @Failure 400 {object} map[string]interface{}
// @Router /maintenance-groups/{id} [get]
func (c *maintenanceGroupController) GetById(ctx *gin.Context) {
id := ctx.Param("id")
result, err := c.maintGroupService.GetById(ctx.Request.Context(), id)
if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_MG, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_MG, result)
ctx.JSON(http.StatusOK, res)
}
// GetAll godoc
// @Summary Get all maintenance groups
// @Description Get all maintenance groups
// @Tags MaintenanceGroup
// @Accept json
// @Produce json
// @Success 200 {array} dto.MaintGroupResponse
// @Failure 400 {object} map[string]interface{}
// @Router /maintenance-groups [get]
func (c *maintenanceGroupController) GetAll(ctx *gin.Context) {
// result, err := c.maintGroupService.GetAll(ctx.Request.Context())
// if err != nil {
// res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_LIST_MG, err.Error(), nil)
// ctx.JSON(http.StatusBadRequest, res)
// return
// }
// res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_LIST_MG, result)
// ctx.JSON(http.StatusOK, res)
}

View File

@ -0,0 +1,118 @@
package dto
import (
"errors"
"github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
)
const (
// Failed
MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body"
MESSAGE_FAILED_REGISTER_MG = "failed create maintenance group"
MESSAGE_FAILED_GET_LIST_MG = "failed get list maintenance group"
MESSAGE_FAILED_TOKEN_NOT_VALID = "token not valid"
MESSAGE_FAILED_TOKEN_NOT_FOUND = "token not found"
MESSAGE_FAILED_GET_MG = "failed get maintenance group"
MESSAGE_FAILED_LOGIN = "failed login"
MESSAGE_FAILED_UPDATE_MG = "failed update maintenance group"
MESSAGE_FAILED_DELETE_MG = "failed delete maintenance group"
MESSAGE_FAILED_PROSES_REQUEST = "failed proses request"
MESSAGE_FAILED_DENIED_ACCESS = "denied access"
MESSAGE_FAILED_VERIFY_EMAIL = "failed verify email"
MESSAGE_FAILED_CREATE_MG = "failed create maintenance group"
// Success
MESSAGE_SUCCESS_REGISTER_MG = "success create maintenance group"
MESSAGE_SUCCESS_GET_LIST_MG = "success get list maintenance group"
MESSAGE_SUCCESS_GET_MG = "success get maintenance group"
MESSAGE_SUCCESS_LOGIN = "success login"
MESSAGE_SUCCESS_UPDATE_MG = "success update maintenance group"
MESSAGE_SUCCESS_DELETE_MG = "success delete maintenance group"
MESSAGE_SEND_VERIFICATION_EMAIL_SUCCESS = "success send verification email"
MESSAGE_SUCCESS_VERIFY_EMAIL = "success verify email"
MESSAGE_SUCCESS_CREATE_MENU = "success create menu"
)
var (
ErrInteralServer = errors.New("internal server error")
ErrCreateMG = errors.New("failed to create maintenance group")
ErrGetMGById = errors.New("failed to get maintenance group by id")
ErrGetMGByEmail = errors.New("failed to get maintenance group by email")
ErrEmailAlreadyExists = errors.New("email already exist")
ErrUpdateMG = errors.New("failed to update maintenance group")
ErrMGNotFound = errors.New("maintenance group not found")
ErrEmailNotFound = errors.New("email not found")
ErrDeleteMG = errors.New("failed to delete maintenance group")
ErrTokenInvalid = errors.New("token invalid")
ErrTokenExpired = errors.New("token expired")
ErrAccountAlreadyVerified = errors.New("account already verified")
ErrCodeCodeExists = errors.New("code already exists")
ErrNameAlreadyExists = errors.New("name already exists")
)
type (
MaintGroupCreateRequest struct {
Code string `json:"code" form:"code" binding:"required,min=2,max=50"`
Name string `json:"name" form:"name" binding:"required,min=2,max=100"`
Description string `json:"description" form:"description" binding:"omitempty"`
ClientID string `json:"client_id" form:"client_id" binding:"required,uuid4"`
MaintenanceGroupRoles []MaintenanceGroupRole `json:"maintenance_group_roles" form:"maintenance_group_roles" binding:"required,dive,required"`
}
MaintenanceGroupRole struct {
RoleID string `json:"role_id" form:"role_id" binding:"required,uuid4"`
Level *int `json:"level" form:"level" binding:"required"`
MaintenanceGroupRoleUsers []MaintenanceGroupRoleUser `json:"maintenance_group_role_users" form:"maintenance_group_role_users" binding:"required,dive,required"`
}
MaintenanceGroupRoleUser struct {
UserID string `json:"user_id" form:"user_id" binding:"required,uuid4"`
}
MaintGroupResponse struct {
ID string `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
Description string `json:"description"`
Client dto.ClientResponse `json:"client"`
MaintenanceGroupRoles *[]MaintenanceGroupRoleResponse `json:"maintenance_group_roles"`
}
MaintenanceGroupRoleResponse struct {
ID string `json:"id"`
Role dto.RoleResponse `json:"role"`
Level *int `json:"level"`
MaintenanceGroupRoleUsers []MaintenanceGroupRoleUserResponse `json:"maintenance_group_role_users"`
}
MaintenanceGroupRoleUserResponse struct {
ID string `json:"id"`
User dto.UserResponse `json:"user"`
}
GetAllMaintenanceGroupResponse struct {
MaintenanceGroups []MaintGroupResponse `json:"maintenance_groups"`
dto.PaginationResponse
}
MaintGroupUpdateRequest struct {
Code *string `json:"code" form:"code" binding:"omitempty,min=2,max=50"`
Name *string `json:"name" form:"name" binding:"omitempty,min=2,max=100"`
Description *string `json:"description" form:"description" binding:"omitempty"`
ClientID *string `json:"client_id" form:"client_id" binding:"omitempty,uuid4"`
MaintenanceGroupRoles *[]MaintenanceGroupRoleUpdate `json:"maintenance_group_roles" form:"maintenance_group_roles" binding:"omitempty,dive"`
}
MaintenanceGroupRoleUpdate struct {
ID *string `json:"id" form:"id" binding:"omitempty,uuid4"`
RoleID *string `json:"role_id" form:"role_id" binding:"omitempty,uuid4"`
MaintenanceGroupRoleUsers *[]MaintenanceGroupRoleUser `json:"maintenance_group_role_users" form:"maintenance_group_role_users" binding:"omitempty,dive"`
Level *int `json:"level" form:"level" binding:"omitempty"`
}
MaintenanceGroupRoleUserUpdate struct {
ID *string `json:"id" form:"id" binding:"omitempty,uuid4"`
UserID *string `json:"user_id" form:"user_id" binding:"omitempty,uuid4"`
}
)

View File

@ -0,0 +1 @@
package query

View File

@ -0,0 +1,106 @@
package repository
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"gorm.io/gorm"
)
type (
MaintGroupRepository interface {
Create(ctx context.Context, tx *gorm.DB, maintGroup entities.M_MaintenanceGroup) (entities.M_MaintenanceGroup, error)
GetById(ctx context.Context, tx *gorm.DB, maintGroupId string) (entities.M_MaintenanceGroup, error)
GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_MaintenanceGroup, error)
GetByCode(ctx context.Context, tx *gorm.DB, code string) (entities.M_MaintenanceGroup, error)
Update(ctx context.Context, tx *gorm.DB, maintGroup entities.M_MaintenanceGroup) (entities.M_MaintenanceGroup, error)
Delete(ctx context.Context, tx *gorm.DB, maintGroupId string) error
}
maintGroupRepository struct {
db *gorm.DB
}
)
// GetByCode implements MaintGroupRepository.
func (m *maintGroupRepository) GetByCode(ctx context.Context, tx *gorm.DB, code string) (entities.M_MaintenanceGroup, error) {
if tx == nil {
tx = m.db
}
var maintGroup entities.M_MaintenanceGroup
if err := tx.WithContext(ctx).Where("code = ?", code).First(&maintGroup).Error; err != nil {
return entities.M_MaintenanceGroup{}, err
}
return maintGroup, nil
}
// Create implements MaintGroupRepository.
func (m *maintGroupRepository) Create(ctx context.Context, tx *gorm.DB, maintGroup entities.M_MaintenanceGroup) (entities.M_MaintenanceGroup, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Create(&maintGroup).Error; err != nil {
return entities.M_MaintenanceGroup{}, err
}
return maintGroup, nil
}
// Delete implements MaintGroupRepository.
func (m *maintGroupRepository) Delete(ctx context.Context, tx *gorm.DB, maintGroupId string) error {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_MaintenanceGroup{}, "id = ?", maintGroupId).Error; err != nil {
return err
}
return nil
}
// GetById implements MaintGroupRepository.
func (m *maintGroupRepository) GetById(ctx context.Context, tx *gorm.DB, maintGroupId string) (entities.M_MaintenanceGroup, error) {
if tx == nil {
tx = m.db
}
var maintGroup entities.M_MaintenanceGroup
if err := tx.WithContext(ctx).
Preload("Client").
Preload("MaintenanceGroupRoles").
Preload("MaintenanceGroupRoles.Role").
Preload("MaintenanceGroupRoles.MaintenanceGroupRoleUsers").
Preload("MaintenanceGroupRoles.MaintenanceGroupRoleUsers.User").
First(&maintGroup, "id = ?", maintGroupId).Error; err != nil {
return entities.M_MaintenanceGroup{}, err
}
return maintGroup, nil
}
// GetByName implements MaintGroupRepository.
func (m *maintGroupRepository) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_MaintenanceGroup, error) {
if tx == nil {
tx = m.db
}
var maintGroup entities.M_MaintenanceGroup
if err := tx.WithContext(ctx).Where("name = ?", name).First(&maintGroup).Error; err != nil {
return entities.M_MaintenanceGroup{}, err
}
return maintGroup, nil
}
// Update implements MaintGroupRepository.
func (m *maintGroupRepository) Update(ctx context.Context, tx *gorm.DB, maintGroup entities.M_MaintenanceGroup) (entities.M_MaintenanceGroup, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Updates(&maintGroup).Error; err != nil {
return entities.M_MaintenanceGroup{}, err
}
return maintGroup, nil
}
func NewMaintGroupRepository(db *gorm.DB) MaintGroupRepository {
return &maintGroupRepository{
db: db,
}
}

View File

@ -0,0 +1,119 @@
package repository
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"gorm.io/gorm"
)
type (
MaintGroupRoleRepository interface {
Create(ctx context.Context, tx *gorm.DB, maintGroupRole entities.M_MaintenanceGroupRole) (entities.M_MaintenanceGroupRole, error)
GetById(ctx context.Context, tx *gorm.DB, maintGroupId string) (entities.M_MaintenanceGroupRole, error)
FindByMaintGroupId(ctx context.Context, tx *gorm.DB, maintGroupId string) ([]entities.M_MaintenanceGroupRole, error)
Update(ctx context.Context, tx *gorm.DB, maintGroupRole entities.M_MaintenanceGroupRole) (entities.M_MaintenanceGroupRole, error)
Delete(ctx context.Context, tx *gorm.DB, maintGroupRoleId string) error
DeleteByIds(ctx context.Context, tx *gorm.DB, maintGroupRoleIds []string) error
DeleteByMaintGroupId(ctx context.Context, tx *gorm.DB, maintGroupId string) error
}
maintGroupRoleRepository struct {
db *gorm.DB
}
)
// DeleteByIds implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) DeleteByIds(ctx context.Context, tx *gorm.DB, maintGroupRoleIds []string) error {
if tx == nil {
tx = m.db
}
if len(maintGroupRoleIds) == 0 {
return nil // Tidak ada data yang perlu dihapus
}
if err := tx.WithContext(ctx).
Where("id IN ?", maintGroupRoleIds).
Delete(&entities.M_MaintenanceGroupRole{}).Error; err != nil {
return err
}
return nil
}
// FindByMaintGroupId implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) FindByMaintGroupId(ctx context.Context, tx *gorm.DB, maintGroupId string) ([]entities.M_MaintenanceGroupRole, error) {
if tx == nil {
tx = m.db
}
var maintGroupRoles []entities.M_MaintenanceGroupRole
if err := tx.Where("maintenance_group_id = ?", maintGroupId).Find(&maintGroupRoles).Error; err != nil {
tx.Rollback()
return nil, err
}
return maintGroupRoles, nil
}
// DeleteByMaintGroupId implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) DeleteByMaintGroupId(ctx context.Context, tx *gorm.DB, maintGroupId string) error {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_MaintenanceGroupRole{}, "maintenance_group_id = ?", maintGroupId).Error; err != nil {
return err
}
return nil
}
// Create implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) Create(ctx context.Context, tx *gorm.DB, maintGroupRole entities.M_MaintenanceGroupRole) (entities.M_MaintenanceGroupRole, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Create(&maintGroupRole).Error; err != nil {
return entities.M_MaintenanceGroupRole{}, err
}
return maintGroupRole, nil
}
// Delete implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) Delete(ctx context.Context, tx *gorm.DB, maintGroupRoleId string) error {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_MaintenanceGroupRole{}, "id = ?", maintGroupRoleId).Error; err != nil {
return err
}
return nil
}
// GetById implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) GetById(ctx context.Context, tx *gorm.DB, maintGroupRoleId string) (entities.M_MaintenanceGroupRole, error) {
if tx == nil {
tx = m.db
}
var maintGroupRole entities.M_MaintenanceGroupRole
if err := tx.WithContext(ctx).First(&maintGroupRole, "id = ?", maintGroupRoleId).Error; err != nil {
return entities.M_MaintenanceGroupRole{}, err
}
return maintGroupRole, nil
}
// Update implements MaintGroupRoleRepository.
func (m *maintGroupRoleRepository) Update(ctx context.Context, tx *gorm.DB, maintGroupRole entities.M_MaintenanceGroupRole) (entities.M_MaintenanceGroupRole, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Updates(&maintGroupRole).Error; err != nil {
return entities.M_MaintenanceGroupRole{}, err
}
return maintGroupRole, nil
}
func NewMaintGroupRoleRepository(db *gorm.DB) MaintGroupRoleRepository {
return &maintGroupRoleRepository{
db: db,
}
}

View File

@ -0,0 +1,119 @@
package repository
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"gorm.io/gorm"
)
type (
MaintGroupRoleUserRepository interface {
Create(ctx context.Context, tx *gorm.DB, maintGroupRoleUser entities.M_MaintenanceGroupRoleUser) (entities.M_MaintenanceGroupRoleUser, error)
GetById(ctx context.Context, tx *gorm.DB, maintGroupId string) (entities.M_MaintenanceGroupRoleUser, error)
FindByRoleId(ctx context.Context, tx *gorm.DB, maintGroupId string) ([]entities.M_MaintenanceGroupRoleUser, error)
Update(ctx context.Context, tx *gorm.DB, maintGroupRoleUser entities.M_MaintenanceGroupRoleUser) (entities.M_MaintenanceGroupRoleUser, error)
Delete(ctx context.Context, tx *gorm.DB, maintGroupId string) error
DeleteByMaintGroupRoleID(ctx context.Context, tx *gorm.DB, maintGroupRoleId string) error
DeleteByRoleIdAndUserIds(ctx context.Context, tx *gorm.DB, maintGroupRoleId string, userIds []string) error
}
maintGroupRoleUserRepository struct {
db *gorm.DB
}
)
// DeleteByRoleIdAndUserIds implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) DeleteByRoleIdAndUserIds(ctx context.Context, tx *gorm.DB, maintGroupRoleId string, userIds []string) error {
if tx == nil {
tx = m.db
}
if len(userIds) == 0 {
return nil // Tidak ada data yang perlu dihapus
}
if err := tx.WithContext(ctx).
Where("maintenance_group_role_id = ? AND user_id IN ?", maintGroupRoleId, userIds).
Delete(&entities.M_MaintenanceGroupRoleUser{}).Error; err != nil {
return err
}
return nil
}
// FindByRoleId implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) FindByRoleId(ctx context.Context, tx *gorm.DB, maintGroupId string) ([]entities.M_MaintenanceGroupRoleUser, error) {
if tx == nil {
tx = m.db
}
var maintGroupRoleUsers []entities.M_MaintenanceGroupRoleUser
if err := tx.Where("maintenance_group_role_id = ?", maintGroupId).Find(&maintGroupRoleUsers).Error; err != nil {
tx.Rollback()
return nil, err
}
return maintGroupRoleUsers, nil
}
// DeleteByMaintGroupRoleID implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) DeleteByMaintGroupRoleID(ctx context.Context, tx *gorm.DB, maintGroupRoleId string) error {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_MaintenanceGroupRoleUser{}, "maintenance_group_role_id = ?", maintGroupRoleId).Error; err != nil {
return err
}
return nil
}
// Create implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) Create(ctx context.Context, tx *gorm.DB, maintGroupRoleUser entities.M_MaintenanceGroupRoleUser) (entities.M_MaintenanceGroupRoleUser, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Create(&maintGroupRoleUser).Error; err != nil {
return entities.M_MaintenanceGroupRoleUser{}, err
}
return maintGroupRoleUser, nil
}
// Delete implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) Delete(ctx context.Context, tx *gorm.DB, maintGroupId string) error {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Delete(&entities.M_MaintenanceGroupRoleUser{}, "id = ?", maintGroupId).Error; err != nil {
return err
}
return nil
}
// GetById implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) GetById(ctx context.Context, tx *gorm.DB, maintGroupId string) (entities.M_MaintenanceGroupRoleUser, error) {
if tx == nil {
tx = m.db
}
var maintGroupRoleUser entities.M_MaintenanceGroupRoleUser
if err := tx.WithContext(ctx).First(&maintGroupRoleUser, "id = ?", maintGroupId).Error; err != nil {
return entities.M_MaintenanceGroupRoleUser{}, err
}
return maintGroupRoleUser, nil
}
// Update implements MaintGroupRoleUserRepository.
func (m *maintGroupRoleUserRepository) Update(ctx context.Context, tx *gorm.DB, maintGroup entities.M_MaintenanceGroupRoleUser) (entities.M_MaintenanceGroupRoleUser, error) {
if tx == nil {
tx = m.db
}
if err := tx.WithContext(ctx).Updates(&maintGroup).Error; err != nil {
return entities.M_MaintenanceGroupRoleUser{}, err
}
return maintGroup, nil
}
func NewMaintGroupRoleUserRepository(db *gorm.DB) MaintGroupRoleUserRepository {
return &maintGroupRoleUserRepository{
db: db,
}
}

View File

@ -0,0 +1,24 @@
package maintenancegroup
import (
"github.com/Caknoooo/go-gin-clean-starter/middlewares"
"github.com/Caknoooo/go-gin-clean-starter/modules/auth/service"
"github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group/controller"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/gin-gonic/gin"
"github.com/samber/do"
)
func RegisterRoutes(server *gin.Engine, injector *do.Injector) {
maintenanceGroupController := do.MustInvoke[controller.MaintenanceGroupController](injector)
jwtService := do.MustInvokeNamed[service.JWTService](injector, constants.JWTService)
maintenanceGroupRoutes := server.Group("/api/v1/maintenance-groups")
{
maintenanceGroupRoutes.POST("", middlewares.Authenticate(jwtService), maintenanceGroupController.Create)
maintenanceGroupRoutes.GET("", middlewares.Authenticate(jwtService), maintenanceGroupController.GetAll)
maintenanceGroupRoutes.GET("/:id", middlewares.Authenticate(jwtService), maintenanceGroupController.GetById)
maintenanceGroupRoutes.PUT("/:id", middlewares.Authenticate(jwtService), maintenanceGroupController.Update)
maintenanceGroupRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), maintenanceGroupController.Delete)
}
}

View File

@ -0,0 +1,365 @@
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.MaintGroupCreateRequest, 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.MaintGroupCreateRequest, 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.MaintGroupCreateRequest{}, 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.MaintGroupCreateRequest{}, err
}
for _, roleReq := range req.MaintenanceGroupRoles {
roleUUID, err := uuid.Parse(roleReq.RoleID)
if err != nil {
tx.Rollback()
return dto.MaintGroupCreateRequest{}, 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.MaintGroupCreateRequest{}, err
}
for _, userReq := range roleReq.MaintenanceGroupRoleUsers {
userUUID, err := uuid.Parse(userReq.UserID)
if err != nil {
tx.Rollback()
return dto.MaintGroupCreateRequest{}, err
}
user := entities.M_MaintenanceGroupRoleUser{
MaintenanceGroupRoleID: createdRole.ID,
UserID: userUUID,
}
_, err = m.maintGroupRoleUserRepo.Create(ctx, tx, user)
if err != nil {
tx.Rollback()
return dto.MaintGroupCreateRequest{}, err
}
}
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return dto.MaintGroupCreateRequest{}, err
}
return req, 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()
}
}()
err := m.maintGroupRepo.Delete(ctx, tx, maintGroupId)
if err != nil {
tx.Rollback()
return err
}
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.ClientResponse{
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,
}
}