wms-be/modules/menu/service/menu_service.go

286 lines
7.2 KiB
Go

package service
import (
"context"
"errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/modules/auth/service"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/repository"
staticDto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid"
"gorm.io/gorm"
)
type MenuService interface {
Create(ctx context.Context, menu dto.MenuResponse) (dto.MenuResponse, error)
GetById(ctx context.Context, menuId string) (dto.MenuResponse, error)
GetByName(ctx context.Context, name string) (dto.MenuResponse, error)
Update(ctx context.Context, menuId string, menu dto.MenuUpdateRequest) (dto.MenuResponse, error)
GetAll(ctx context.Context) ([]dto.MenuResponse, error)
Delete(ctx context.Context, menuId string) error
}
type menuService struct {
menuRepository repository.MenuRepository
jwtService service.JWTService
db *gorm.DB
}
// GetAll implements MenuService.
func (m *menuService) GetAll(ctx context.Context) ([]dto.MenuResponse, error) {
entities, err := m.menuRepository.GetAll(ctx, m.db)
if err != nil {
return nil, err
}
responses := make([]dto.MenuResponse, 0, len(entities))
for _, entity := range entities {
res := dto.MenuResponse{
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
if len(entity.Permissions) > 0 {
res.Permissions = make([]staticDto.PermissionResponse, 0, len(entity.Permissions))
for _, perm := range entity.Permissions {
res.Permissions = append(res.Permissions, staticDto.PermissionResponse{
ID: perm.ID.String(),
Name: perm.Name,
})
}
}
responses = append(responses, res)
}
return responses, nil
}
// Create implements MenuService.
func (m *menuService) Create(ctx context.Context, menu dto.MenuResponse) (dto.MenuResponse, error) {
var entity entities.M_Menu
// ID: use provided or generate new
if menu.ID != "" {
id, err := uuid.Parse(menu.ID)
if err != nil {
return dto.MenuResponse{}, err
}
entity.ID = id
} else {
entity.ID = uuid.New()
}
// map simple fields
entity.Name = menu.Name
entity.IconUrl = menu.IconUrl
entity.Url = menu.Url
entity.Sequence = menu.Sequence
entity.Mode = menu.Mode
entity.Status = menu.Status
// ParentID if provided
if menu.Parent != nil && menu.Parent.ID != "" {
pid, err := uuid.Parse(menu.Parent.ID)
if err != nil {
return dto.MenuResponse{}, err
}
entity.ParentID = &pid
} else {
entity.ParentID = nil
}
created, err := m.menuRepository.Create(ctx, m.db, entity)
if err != nil {
return dto.MenuResponse{}, err
}
// map back to DTO
res := dto.MenuResponse{
ID: created.ID.String(),
Name: created.Name,
IconUrl: created.IconUrl,
Url: created.Url,
Sequence: created.Sequence,
Mode: created.Mode,
Status: created.Status,
}
if created.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: created.Parent.ID.String(),
Name: created.Parent.Name,
}
} else if created.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: created.ParentID.String()}
}
return res, nil
}
// Delete implements MenuService.
func (m *menuService) Delete(ctx context.Context, menuId string) error {
return m.menuRepository.Delete(ctx, m.db, menuId)
}
// GetById implements MenuService.
func (m *menuService) GetById(ctx context.Context, menuId string) (dto.MenuResponse, error) {
entity, err := m.menuRepository.GetById(ctx, m.db, menuId)
if err != nil {
return dto.MenuResponse{}, err
}
res := dto.MenuResponse{
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
if len(entity.Permissions) > 0 {
res.Permissions = make([]staticDto.PermissionResponse, 0, len(entity.Permissions))
for _, perm := range entity.Permissions {
res.Permissions = append(res.Permissions, staticDto.PermissionResponse{
ID: perm.ID.String(),
Name: perm.Name,
// Description: perm.Description,
// Code: perm.Code,
})
}
}
return res, nil
}
// GetByName implements MenuService.
func (m *menuService) GetByName(ctx context.Context, name string) (dto.MenuResponse, error) {
entity, err := m.menuRepository.GetByName(ctx, m.db, name)
if err != nil {
return dto.MenuResponse{}, err
}
res := dto.MenuResponse{
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
return res, nil
}
// Update implements MenuService.
func (m *menuService) Update(ctx context.Context, menuId string, menu dto.MenuUpdateRequest) (dto.MenuResponse, error) {
existing, err := m.menuRepository.GetById(ctx, m.db, menuId)
if err != nil {
return dto.MenuResponse{}, dto.ErrMenuNotFound
}
if menu.Name != "" {
menuByName, err := m.menuRepository.GetByName(ctx, m.db, menu.Name)
if err == nil && menuByName.ID != existing.ID {
return dto.MenuResponse{}, errors.New("menu name already exists")
}
existing.Name = menu.Name
}
if menu.IconUrl != "" {
existing.IconUrl = menu.IconUrl
}
if menu.Url != "" {
existing.Url = menu.Url
}
if menu.Mode != "" {
existing.Mode = menu.Mode
}
if menu.Status != "" {
existing.Status = menu.Status
}
if menu.Sequence != 0 {
existing.Sequence = menu.Sequence
}
if menu.ParentID != nil {
pid := *menu.ParentID
existing.ParentID = &pid
} else {
existing.ParentID = nil
}
updated, err := m.menuRepository.Update(ctx, m.db, existing)
if err != nil {
return dto.MenuResponse{}, err
}
res := dto.MenuResponse{
ID: updated.ID.String(),
Name: updated.Name,
IconUrl: updated.IconUrl,
Url: updated.Url,
Sequence: updated.Sequence,
Mode: updated.Mode,
Status: updated.Status,
}
if updated.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: updated.Parent.ID.String(),
Name: updated.Parent.Name,
}
} else if updated.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: updated.ParentID.String()}
}
return res, nil
}
func NewMenuService(
menuRepo repository.MenuRepository,
jwtService service.JWTService,
db *gorm.DB,
) MenuService {
return &menuService{
menuRepository: menuRepo,
jwtService: jwtService,
db: db,
}
}