feat: Implement menu assignment and removal for clients with corresponding service and repository methods

This commit is contained in:
Habib Fatkhul Rohman 2025-10-28 13:55:33 +07:00
parent 4371103cc7
commit 1bfd4ff176
6 changed files with 285 additions and 140 deletions

View File

@ -10,9 +10,10 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/client/service" "github.com/Caknoooo/go-gin-clean-starter/modules/client/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/Caknoooo/go-pagination"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/samber/do" "github.com/samber/do"
// "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -23,6 +24,8 @@ type (
Delete(ctx *gin.Context) Delete(ctx *gin.Context)
GetById(ctx *gin.Context) GetById(ctx *gin.Context)
GetAll(ctx *gin.Context) GetAll(ctx *gin.Context)
AssignMenusToClient(ctx *gin.Context)
RemoveMenusFromClient(ctx *gin.Context)
} }
clientController struct { clientController struct {
@ -116,34 +119,69 @@ func (c *clientController) GetById(ctx *gin.Context) {
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_CLIENT, client) res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_CLIENT, client)
ctx.JSON(http.StatusOK, res) ctx.JSON(http.StatusOK, res)
} }
func (c *clientController) GetAll(ctx *gin.Context) { func (c *clientController) GetAll(ctx *gin.Context) {
// clientId := ctx.MustGet("client_id").(string) // Ambil filter dari query param
var filter = &query.ClientFilter{ var filter query.ClientFilter
Name: ctx.Query("name"), if err := ctx.ShouldBindQuery(&filter); err != nil {
PIC: ctx.Query("pic"), res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_CLIENT, err.Error(), nil)
Phone: ctx.Query("phone"), ctx.JSON(http.StatusBadRequest, res)
Email: ctx.Query("email"), return
Address: ctx.Query("address"),
// ClientID: clientId,
Includes: ctx.QueryArray("includes"),
} }
filter.BindPagination(ctx)
ctx.ShouldBindQuery(filter) // Ambil limit & offset dari query param (default: limit=10, offset=0)
groups, total, err := pagination.PaginatedQueryWithIncludableAndOptions[query.M_Client]( perPage := utils.ParseInt(ctx.DefaultQuery("per_page", "10"))
c.db, page := utils.ParseInt(ctx.DefaultQuery("page", "1"))
filter, filter.PerPage = perPage
pagination.PaginatedQueryOptions{ filter.Page = (page - 1) * perPage
EnableSoftDelete: true,
}, clients, total, err := c.clientService.GetAll(ctx, filter)
)
if err != nil { if err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_CLIENT, err.Error(), nil) res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_CLIENT, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res) ctx.JSON(http.StatusBadRequest, res)
return return
} }
paginationResponse := pagination.CalculatePagination(filter.Pagination, total)
response := pagination.NewPaginatedResponse(http.StatusOK, dto.MESSAGE_SUCCESS_GET_CLIENT, groups, paginationResponse) paginationResponse := utils.BuildPaginationResponse(perPage, page, total)
response := utils.BuildResponseSuccessWithPagination(http.StatusOK, dto.MESSAGE_SUCCESS_GET_CLIENT, clients, paginationResponse)
ctx.JSON(http.StatusOK, response) ctx.JSON(http.StatusOK, response)
} }
// AssignMenusToClient implements MenuController.
func (c *clientController) AssignMenusToClient(ctx *gin.Context) {
clientId := ctx.Param("id")
var req dto.AssignMenusToClientRequest
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
}
if err := c.clientService.AssignMenusToClient(ctx.Request.Context(), clientId, req.MenuIds); err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_ASSIGN_MENUS_TO_CLIENT, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_ASSIGN_MENUS_TO_CLIENT, nil)
ctx.JSON(http.StatusOK, resp)
}
// RemoveMenusFromClient implements MenuController.
func (c *clientController) RemoveMenusFromClient(ctx *gin.Context) {
clientId := ctx.Param("id")
var req dto.RemoveMenusFromClientRequest
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
}
if err := c.clientService.RemoveMenusFromClient(ctx.Request.Context(), clientId, req.MenuIds); err != nil {
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_REMOVE_MENUS_FROM_CLIENT, err.Error(), nil)
ctx.JSON(http.StatusBadRequest, res)
return
}
resp := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_REMOVE_MENUS_FROM_CLIENT, nil)
ctx.JSON(http.StatusOK, resp)
}

View File

@ -10,10 +10,15 @@ const (
MESSAGE_FAILED_GET_CLIENT = "failed get client" MESSAGE_FAILED_GET_CLIENT = "failed get client"
MESSAGE_SUCCESS_GET_CLIENT = "success get client" MESSAGE_SUCCESS_GET_CLIENT = "success get client"
MESSAGE_FAILED_UPDATE_CLIENT = "failed update client" MESSAGE_FAILED_UPDATE_CLIENT = "failed update client"
MESSAGE_FAILED_PROSES_REQUEST = "failed proses request"
MESSAGE_SUCCESS_UPDATE_CLIENT = "success update client" MESSAGE_SUCCESS_UPDATE_CLIENT = "success update client"
MESSAGE_FAILED_DELETE_CLIENT = "failed delete client" MESSAGE_FAILED_DELETE_CLIENT = "failed delete client"
MESSAGE_SUCCESS_DELETE_CLIENT = "success delete client" MESSAGE_SUCCESS_DELETE_CLIENT = "success delete client"
MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body" MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body"
MESSAGE_SUCCESS_ASSIGN_MENUS_TO_CLIENT = "success assign menus to client"
MESSAGE_SUCCESS_REMOVE_MENUS_FROM_CLIENT = "success remove menus from client"
MESSAGE_FAILED_ASSIGN_MENUS_TO_CLIENT = "failed assign menus to client"
MESSAGE_FAILED_REMOVE_MENUS_FROM_CLIENT = "failed remove menus from client"
) )
var ( var (
@ -21,6 +26,7 @@ var (
ErrGetClientById = errors.New("failed to get client by id") ErrGetClientById = errors.New("failed to get client by id")
ErrUpdateClient = errors.New("failed to update client") ErrUpdateClient = errors.New("failed to update client")
ErrDeleteClient = errors.New("failed to delete client") ErrDeleteClient = errors.New("failed to delete client")
ErrMenuIdsAndClientIdEmpty = errors.New("menuIds and clientId must not be empty")
) )
type ( type (
@ -41,6 +47,12 @@ type (
Email string `json:"email"` Email string `json:"email"`
Address string `json:"address"` Address string `json:"address"`
Logo string `json:"logo"` Logo string `json:"logo"`
Menus []MenuResponse `json:"menus,omitempty"`
}
MenuResponse struct {
ID string `json:"id"`
Name string `json:"name"`
} }
ClientUpdateRequest struct { ClientUpdateRequest struct {
@ -51,4 +63,22 @@ type (
Address *string `json:"address" form:"address" binding:"omitempty"` Address *string `json:"address" form:"address" binding:"omitempty"`
Logo *string `form:"-"` // jika update logo, isi manual dari file Logo *string `form:"-"` // jika update logo, isi manual dari file
} }
AssignMenusToClientRequest struct {
MenuIds []string `json:"menu_ids" form:"menu_ids" binding:"required,dive,required,uuid4"`
}
RemoveMenusFromClientRequest struct {
MenuIds []string `json:"menu_ids" form:"menu_ids" binding:"required,dive,required,uuid4"`
}
ClientFilter struct {
Name string
PIC string
Phone string
Email string
Address string
PerPage int
Page int
}
) )

View File

@ -1,96 +1,45 @@
package query package query
import ( import (
"github.com/Caknoooo/go-pagination"
"gorm.io/gorm" "gorm.io/gorm"
) )
type M_Client struct {
ID string `json:"id"`
Name string `json:"name"`
PIC string `json:"pic"`
Phone string `json:"phone"`
Email string `json:"email"`
Address string `json:"address"`
Logo string `json:"logo"`
}
type ClientFilter struct { type ClientFilter struct {
pagination.BaseFilter Name string `form:"name"`
Name string `form:"name"` // tambahkan ini PIC string `form:"pic"`
PIC string `form:"pic"` // tambahkan ini Phone string `form:"phone"`
Phone string `form:"phone"` // tambahkan ini Email string `form:"email"`
Email string `form:"email"` // tambahkan ini Address string `form:"address"`
Address string `form:"address"` // tambahkan ini MenuID string `form:"menu_id"` // tambahkan field ini
ClientID string `form:"client_id"` // tambahkan ini MenuName string `form:"menu_name"` // tambahkan field ini
Includes []string `form:"includes"` // tambahkan ini PerPage int `form:"per_page"`
Page int `form:"page"`
} }
func (f *ClientFilter) ApplyFilters(query *gorm.DB) *gorm.DB { func ApplyClientFilters(db *gorm.DB, filter ClientFilter) *gorm.DB {
// Apply your filters here if filter.Name != "" {
if f.Name != "" { db = db.Where("name ILIKE ?", "%"+filter.Name+"%")
query = query.Where("name ILIKE ?", "%"+f.Name+"%")
} }
if f.ClientID != "" { if filter.PIC != "" {
query = query.Where("client_id = ?", f.ClientID) db = db.Where("pic ILIKE ?", "%"+filter.PIC+"%")
} }
if f.PIC != "" { if filter.Phone != "" {
query = query.Where("pic ILIKE ?", "%"+f.PIC+"%") db = db.Where("phone ILIKE ?", "%"+filter.Phone+"%")
} }
if f.Phone != "" { if filter.Email != "" {
query = query.Where("phone ILIKE ?", "%"+f.Phone+"%") db = db.Where("email ILIKE ?", "%"+filter.Email+"%")
} }
if f.Email != "" { if filter.Address != "" {
query = query.Where("email ILIKE ?", "%"+f.Email+"%") db = db.Where("address ILIKE ?", "%"+filter.Address+"%")
} }
if f.Address != "" { if filter.MenuName != "" {
query = query.Where("address ILIKE ?", "%"+f.Address+"%") db = db.Joins("JOIN m_menu_clients ON m_menu_clients.client_id = m_clients.id").
} Joins("JOIN m_menus ON m_menus.id = m_menu_clients.menu_id").
Where("m_menus.name ILIKE ?", "%"+filter.MenuName+"%")
// Manual preload untuk roles dengan field terbatas
// for _, include := range f.Includes {
// if include == "Roles" {
// query = query.Preload("Roles", func(db *gorm.DB) *gorm.DB {
// return db.Select("id", "name") // Hanya ambil id dan name
// })
// }
// }
return query
}
func (f *ClientFilter) GetTableName() string {
return "m_clients"
}
func (f *ClientFilter) GetSearchFields() []string {
return []string{"name"}
}
func (f *ClientFilter) GetDefaultSort() string {
return "id asc"
}
func (f *ClientFilter) GetIncludes() []string {
return f.Includes
}
func (f *ClientFilter) GetPagination() pagination.PaginationRequest {
return f.Pagination
}
func (f *ClientFilter) Validate() {
var validIncludes []string
allowedIncludes := f.GetAllowedIncludes()
for _, include := range f.Includes {
if allowedIncludes[include] {
validIncludes = append(validIncludes, include)
}
}
f.Includes = validIncludes
}
func (f *ClientFilter) GetAllowedIncludes() map[string]bool {
return map[string]bool{
// "Roles": true,
} }
if filter.MenuID != "" {
db = db.Joins("JOIN m_menu_clients ON m_menu_clients.client_id = m_clients.id").
Where("m_menu_clients.menu_id = ?", filter.MenuID)
}
return db
} }

View File

@ -4,8 +4,10 @@ import (
"context" "context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/query"
"github.com/google/uuid" "github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause"
) )
type ( type (
@ -13,8 +15,11 @@ type (
Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error)
GetById(ctx context.Context, tx *gorm.DB, clientId string) (entities.M_Client, error) GetById(ctx context.Context, tx *gorm.DB, clientId string) (entities.M_Client, error)
GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Client, error) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Client, error)
GetAll(ctx context.Context, filter query.ClientFilter) ([]entities.M_Client, int64, error)
Update(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) Update(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error)
Delete(ctx context.Context, tx *gorm.DB, clientId string) error Delete(ctx context.Context, tx *gorm.DB, clientId string) error
AssignMenusToClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error
RemoveMenusFromClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error
} }
clientRepository struct { clientRepository struct {
@ -22,6 +27,28 @@ type (
} }
) )
func (r *clientRepository) GetAll(ctx context.Context, filter query.ClientFilter) ([]entities.M_Client, int64, error) {
var clients []entities.M_Client
var total int64
db := r.db.Model(&entities.M_Client{})
db = query.ApplyClientFilters(db, filter)
// Hitung total data
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
// Ambil data dengan pagination dan preload menus
err := db.
Preload("Menus").
Limit(filter.PerPage).
Offset(filter.Page).
Find(&clients).Error
return clients, total, err
}
func (r *clientRepository) Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) { func (r *clientRepository) Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) {
if tx == nil { if tx == nil {
tx = r.db tx = r.db
@ -40,7 +67,9 @@ func (r *clientRepository) GetById(ctx context.Context, tx *gorm.DB, clientId st
tx = r.db tx = r.db
} }
var client entities.M_Client var client entities.M_Client
if err := tx.WithContext(ctx).First(&client, "id = ?", clientId).Error; err != nil { if err := tx.WithContext(ctx).
Preload("Menus").
First(&client, "id = ?", clientId).Error; err != nil {
return entities.M_Client{}, err return entities.M_Client{}, err
} }
return client, nil return client, nil
@ -77,6 +106,48 @@ func (r *clientRepository) Delete(ctx context.Context, tx *gorm.DB, clientId str
return nil return nil
} }
// AssignMenusToClient implements MenuRepository.
func (c *clientRepository) AssignMenusToClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error {
if tx == nil {
tx = c.db
}
var menuClients []entities.M_Menu_Client
for _, menuId := range menuIds {
menuClient := entities.M_Menu_Client{}
if err := menuClient.MenuID.UnmarshalText([]byte(menuId)); err != nil {
return err
}
if err := menuClient.ClientID.UnmarshalText([]byte(clientId)); err != nil {
return err
}
menuClients = append(menuClients, menuClient)
}
// Use Create with OnConflict to ignore duplicates
if err := tx.WithContext(ctx).Clauses(
// Only insert if not exists (Postgres syntax, adjust if needed)
clause.OnConflict{DoNothing: true},
).Create(&menuClients).Error; err != nil {
return err
}
return nil
}
// RemoveMenusFromClient implements MenuRepository.
func (c *clientRepository) RemoveMenusFromClient(ctx context.Context, tx *gorm.DB, clientId string, menuIds []string) error {
if tx == nil {
tx = c.db
}
if err := tx.WithContext(ctx).
Where("menu_id IN ? AND client_id = ?", menuIds, clientId).
Delete(&entities.M_Menu_Client{}).Error; err != nil {
return err
}
return nil
}
func NewClientRepository(db *gorm.DB) ClientRepository { func NewClientRepository(db *gorm.DB) ClientRepository {
return &clientRepository{db: db} return &clientRepository{db: db}
} }

View File

@ -20,5 +20,7 @@ func RegisterRoutes(server *gin.Engine, injector *do.Injector) {
clientRoutes.PUT("/:id", middlewares.Authenticate(jwtService), clientController.Update) clientRoutes.PUT("/:id", middlewares.Authenticate(jwtService), clientController.Update)
clientRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), clientController.Delete) clientRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), clientController.Delete)
clientRoutes.GET("", middlewares.Authenticate(jwtService), clientController.GetAll) clientRoutes.GET("", middlewares.Authenticate(jwtService), clientController.GetAll)
clientRoutes.POST("/:id/assign-menus", middlewares.Authenticate(jwtService), clientController.AssignMenusToClient)
clientRoutes.POST("/:id/remove-menus", middlewares.Authenticate(jwtService), clientController.RemoveMenusFromClient)
} }
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/client/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/client/repository"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -13,8 +14,11 @@ type ClientService interface {
Create(ctx context.Context, client dto.ClientCreateRequest) (dto.ClientResponse, error) Create(ctx context.Context, client dto.ClientCreateRequest) (dto.ClientResponse, error)
GetById(ctx context.Context, clientId string) (dto.ClientResponse, error) GetById(ctx context.Context, clientId string) (dto.ClientResponse, error)
GetByName(ctx context.Context, name string) (dto.ClientResponse, error) GetByName(ctx context.Context, name string) (dto.ClientResponse, error)
GetAll(ctx context.Context, filter query.ClientFilter) ([]dto.ClientResponse, int64, error)
Update(ctx context.Context, client dto.ClientUpdateRequest, clientId string) (dto.ClientResponse, error) Update(ctx context.Context, client dto.ClientUpdateRequest, clientId string) (dto.ClientResponse, error)
Delete(ctx context.Context, clientId string) error Delete(ctx context.Context, clientId string) error
AssignMenusToClient(ctx context.Context, clientId string, menuIds []string) error
RemoveMenusFromClient(ctx context.Context, clientId string, menuIds []string) error
} }
type clientService struct { type clientService struct {
@ -22,6 +26,35 @@ type clientService struct {
clientRepo repository.ClientRepository clientRepo repository.ClientRepository
} }
func (s *clientService) GetAll(ctx context.Context, filter query.ClientFilter) ([]dto.ClientResponse, int64, error) {
clients, total, err := s.clientRepo.GetAll(ctx, filter)
if err != nil {
return nil, 0, err
}
var responses []dto.ClientResponse
for _, c := range clients {
var menus []dto.MenuResponse
for _, m := range c.Menus {
menus = append(menus, dto.MenuResponse{
ID: m.ID.String(),
Name: m.Name,
})
}
responses = append(responses, dto.ClientResponse{
ID: c.ID.String(),
Name: c.Name,
PIC: c.PIC,
Phone: c.Phone,
Email: c.Email,
Address: c.Address,
Logo: c.Logo,
Menus: menus,
})
}
return responses, total, nil
}
func (s *clientService) Create(ctx context.Context, req dto.ClientCreateRequest) (dto.ClientResponse, error) { func (s *clientService) Create(ctx context.Context, req dto.ClientCreateRequest) (dto.ClientResponse, error) {
tx := s.db.Begin() tx := s.db.Begin()
defer func() { defer func() {
@ -56,15 +89,11 @@ func (s *clientService) Create(ctx context.Context, req dto.ClientCreateRequest)
// logoBase64 = base64.StdEncoding.EncodeToString(createdClient.Logo) // logoBase64 = base64.StdEncoding.EncodeToString(createdClient.Logo)
// } // }
return dto.ClientResponse{ result, err := s.GetById(ctx, createdClient.ID.String())
ID: createdClient.ID.String(), if err != nil {
Name: createdClient.Name, return dto.ClientResponse{}, err
PIC: createdClient.PIC, }
Phone: createdClient.Phone, return result, nil
Email: createdClient.Email,
Address: createdClient.Address,
Logo: req.Logo,
}, nil
} }
func (s *clientService) GetById(ctx context.Context, clientId string) (dto.ClientResponse, error) { func (s *clientService) GetById(ctx context.Context, clientId string) (dto.ClientResponse, error) {
@ -76,6 +105,16 @@ func (s *clientService) GetById(ctx context.Context, clientId string) (dto.Clien
// if len(client.Logo) > 0 { // if len(client.Logo) > 0 {
// logoBase64 = base64.StdEncoding.EncodeToString(client.Logo) // logoBase64 = base64.StdEncoding.EncodeToString(client.Logo)
// } // }
// Mapping menus ke DTO
var menus []dto.MenuResponse
for _, m := range client.Menus {
menus = append(menus, dto.MenuResponse{
ID: m.ID.String(),
Name: m.Name,
})
}
return dto.ClientResponse{ return dto.ClientResponse{
ID: client.ID.String(), ID: client.ID.String(),
Name: client.Name, Name: client.Name,
@ -84,6 +123,7 @@ func (s *clientService) GetById(ctx context.Context, clientId string) (dto.Clien
Email: client.Email, Email: client.Email,
Address: client.Address, Address: client.Address,
Logo: client.Logo, Logo: client.Logo,
Menus: menus,
}, nil }, nil
} }
@ -151,15 +191,12 @@ func (s *clientService) Update(ctx context.Context, req dto.ClientUpdateRequest,
// if len(updatedClient.Logo) > 0 { // if len(updatedClient.Logo) > 0 {
// logoBase64 = base64.StdEncoding.EncodeToString(updatedClient.Logo) // logoBase64 = base64.StdEncoding.EncodeToString(updatedClient.Logo)
// } // }
return dto.ClientResponse{
ID: updatedClient.ID.String(), result, err := s.GetById(ctx, updatedClient.ID.String())
Name: updatedClient.Name, if err != nil {
PIC: updatedClient.PIC, return dto.ClientResponse{}, err
Phone: updatedClient.Phone, }
Email: updatedClient.Email, return result, nil
Address: updatedClient.Address,
Logo: updatedClient.Logo,
}, nil
} }
func (s *clientService) Delete(ctx context.Context, clientId string) error { func (s *clientService) Delete(ctx context.Context, clientId string) error {
@ -182,6 +219,24 @@ func (s *clientService) Delete(ctx context.Context, clientId string) error {
return nil return nil
} }
// AssignMenusToClient implements MenuService.
func (s *clientService) AssignMenusToClient(ctx context.Context, clientId string, menuIds []string) error {
if len(menuIds) == 0 || clientId == "" {
return dto.ErrMenuIdsAndClientIdEmpty
}
return s.clientRepo.AssignMenusToClient(ctx, s.db, clientId, menuIds)
}
// RemoveMenusFromClient implements MenuService.
func (s *clientService) RemoveMenusFromClient(ctx context.Context, clientId string, menuIds []string) error {
if len(menuIds) == 0 || clientId == "" {
return dto.ErrMenuIdsAndClientIdEmpty
}
return s.clientRepo.RemoveMenusFromClient(ctx, s.db, clientId, menuIds)
}
func NewClientService(clientRepo repository.ClientRepository, db *gorm.DB) ClientService { func NewClientService(clientRepo repository.ClientRepository, db *gorm.DB) ClientService {
return &clientService{ return &clientService{
clientRepo: clientRepo, clientRepo: clientRepo,