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" "github.com/google/uuid" "github.com/sirupsen/logrus" "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 log *logrus.Logger } // 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 { responses = append(responses, dto.ToMenuResponse(entity)) } 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 } res := dto.ToMenuResponse(created) 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 } return dto.ToMenuResponse(entity), 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.ToMenuResponse(entity) 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.ToMenuResponse(updated) return res, nil } func NewMenuService( menuRepo repository.MenuRepository, jwtService service.JWTService, db *gorm.DB, log *logrus.Logger, ) MenuService { return &menuService{ menuRepository: menuRepo, jwtService: jwtService, db: db, log: log, } }