wms-be/modules/menu/controller/menu_controller.go

212 lines
6.0 KiB
Go

package controller
import (
"errors"
"net/http"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/Caknoooo/go-pagination"
"github.com/gin-gonic/gin"
"github.com/samber/do"
"gorm.io/gorm"
)
type (
MenuController interface {
CreateMenu(ctx *gin.Context)
GetMenuByID(ctx *gin.Context)
GetMenuByName(ctx *gin.Context)
GetMenus(ctx *gin.Context)
UpdateMenu(ctx *gin.Context)
DeleteMenu(ctx *gin.Context)
}
menuController struct {
menuService service.MenuService
db *gorm.DB
}
)
// CreateMenu implements MenuController.
func (m *menuController) CreateMenu(ctx *gin.Context) {
var req dto.MenuCreateRequest
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
}
in := dto.MenuResponse{
Name: req.Name,
IconUrl: req.IconUrl,
Url: req.Url,
Sequence: req.Sequence,
Mode: req.Mode,
Status: req.Status,
}
if req.ParentID != nil {
in.Parent = &dto.MenuParentResponse{ID: req.ParentID.String()}
}
res, err := m.menuService.Create(ctx.Request.Context(), in)
if err != nil {
resp := utils.BuildResponseFailed(dto.MESSAGE_FAILED_CREATE_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, resp)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_CREATE_MENU, res)
ctx.JSON(http.StatusOK, resp)
}
// GetMenus implements MenuController.
func (m *menuController) GetMenus(ctx *gin.Context) {
_ = ctx.MustGet("client_id").(string)
var filter = &query.MenuFilter{
// ClientID: clientId,
Name: ctx.Query("name"),
ParentID: ctx.Query("parent_id"),
Includes: ctx.QueryArray("includes"),
}
filter.BindPagination(ctx)
ctx.ShouldBindQuery(filter)
menus, total, err := pagination.PaginatedQueryWithIncludable[query.M_Menu](m.db, filter)
if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_LIST_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
menuResponses := ToMenuResponses(menus)
paginationResponse := pagination.CalculatePagination(filter.Pagination, total)
response := pagination.NewPaginatedResponse(http.StatusOK, dto.MESSAGE_SUCCESS_GET_LIST_MENU, menuResponses, paginationResponse)
ctx.JSON(http.StatusOK, response)
}
// GetMenuByID implements MenuController.
func (m *menuController) GetMenuByID(ctx *gin.Context) {
id := ctx.Param("id")
if id == "" {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_MENU, "id is required", nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
res, err := m.menuService.GetById(ctx.Request.Context(), id)
if err != nil {
resErr := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, resErr)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_MENU, res)
ctx.JSON(http.StatusOK, resp)
}
// GetMenuByName implements MenuController.
func (m *menuController) GetMenuByName(ctx *gin.Context) {
name := ctx.Query("name")
if name == "" {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_MENU, "name query is required", nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
res, err := m.menuService.GetByName(ctx.Request.Context(), name)
if err != nil {
resErr := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, resErr)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_MENU, res)
ctx.JSON(http.StatusOK, resp)
}
// UpdateMenu implements MenuController.
func (m *menuController) UpdateMenu(ctx *gin.Context) {
var req dto.MenuUpdateRequest
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
}
menuId := ctx.Param("id")
result, err := m.menuService.Update(ctx.Request.Context(), menuId, req)
if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_MENU, result)
ctx.JSON(http.StatusOK, resp)
}
// DeleteMenu implements MenuController.
func (m *menuController) DeleteMenu(ctx *gin.Context) {
id := ctx.Param("id")
if id == "" {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_MENU, "id is required", nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
if err := m.menuService.Delete(ctx.Request.Context(), id); err != nil {
// if record not found, return 404
if errors.Is(err, gorm.ErrRecordNotFound) {
ctx.JSON(http.StatusNotFound, gin.H{"error": "menu not found"})
return
}
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_MENU, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_MENU, nil)
ctx.JSON(http.StatusOK, resp)
}
func NewMenuController(i *do.Injector, ms service.MenuService) MenuController {
db := do.MustInvokeNamed[*gorm.DB](i, constants.DB)
return &menuController{
menuService: ms,
db: db,
}
}
// Fungsi transform dari entities ke DTO
func ToMenuResponse(menu query.M_Menu) dto.MenuResponse {
response := dto.MenuResponse{
ID: menu.ID.String(),
Name: menu.Name,
IconUrl: menu.IconUrl,
Url: menu.Url,
Sequence: menu.Sequence,
Mode: menu.Mode,
Status: menu.Status,
}
// Handle parent jika ada
if menu.Parent != nil {
response.Parent = &dto.MenuParentResponse{
ID: menu.Parent.ID.String(),
Name: menu.Parent.Name,
}
}
return response
}
func ToMenuResponses(menus []query.M_Menu) []dto.MenuResponse {
responses := make([]dto.MenuResponse, len(menus))
for i, menu := range menus {
responses[i] = ToMenuResponse(menu)
}
return responses
}