package service import ( "context" "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/query" "github.com/Caknoooo/go-gin-clean-starter/modules/client/repository" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/sirupsen/logrus" "gorm.io/gorm" ) type ClientService interface { Create(ctx context.Context, client dto.ClientCreateRequest) (dto.ClientResponse, error) GetById(ctx context.Context, clientId 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) 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 { db *gorm.DB clientRepo repository.ClientRepository log *logrus.Logger } 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) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() userID := utils.GetUserID(ctx) client := entities.M_Client{ Name: req.Name, PIC: req.PIC, Phone: req.Phone, Email: req.Email, Address: req.Address, Logo: req.Logo, FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE), } createdClient, err := s.clientRepo.Create(ctx, tx, client) if err != nil { tx.Rollback() return dto.ClientResponse{}, err } err = tx.Commit().Error if err != nil { tx.Rollback() return dto.ClientResponse{}, err } s.log.WithFields(logrus.Fields{ "user_id": userID, "action": "create", "entity": "client", "entity_id": createdClient.ID.String(), }).Info("Client created") result, err := s.GetById(ctx, createdClient.ID.String()) if err != nil { return dto.ClientResponse{}, err } return result, nil } func (s *clientService) GetById(ctx context.Context, clientId string) (dto.ClientResponse, error) { client, err := s.clientRepo.GetById(ctx, nil, clientId) if err != nil { return dto.ClientResponse{}, err } // logoBase64 := "" // if len(client.Logo) > 0 { // 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{ ID: client.ID.String(), Name: client.Name, PIC: client.PIC, Phone: client.Phone, Email: client.Email, Address: client.Address, Logo: client.Logo, Menus: menus, }, nil } func (s *clientService) GetByName(ctx context.Context, name string) (dto.ClientResponse, error) { client, err := s.clientRepo.GetByName(ctx, nil, name) if err != nil { return dto.ClientResponse{}, err } // logoBase64 := "" // if len(client.Logo) > 0 { // logoBase64 = base64.StdEncoding.EncodeToString(client.Logo) // } return dto.ClientResponse{ ID: client.ID.String(), Name: client.Name, PIC: client.PIC, Phone: client.Phone, Email: client.Email, Address: client.Address, Logo: client.Logo, }, nil } func (s *clientService) Update(ctx context.Context, req dto.ClientUpdateRequest, clientId string) (dto.ClientResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() client, err := s.clientRepo.GetById(ctx, tx, clientId) if err != nil { tx.Rollback() return dto.ClientResponse{}, err } if req.Name != nil { client.Name = *req.Name } if req.PIC != nil { client.PIC = *req.PIC } if req.Phone != nil { client.Phone = *req.Phone } if req.Email != nil { client.Email = *req.Email } if req.Address != nil { client.Address = *req.Address } if req.Logo != nil { client.Logo = *req.Logo } userID := utils.GetUserID(ctx) client.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE) updatedClient, err := s.clientRepo.Update(ctx, tx, client) if err != nil { tx.Rollback() return dto.ClientResponse{}, err } err = tx.Commit().Error if err != nil { tx.Rollback() return dto.ClientResponse{}, err } s.log.WithFields(logrus.Fields{ "user_id": userID, "action": "update", "entity": "client", "entity_id": clientId, }).Info("Client updated") result, err := s.GetById(ctx, updatedClient.ID.String()) if err != nil { return dto.ClientResponse{}, err } return result, nil } func (s *clientService) Delete(ctx context.Context, clientId string) error { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() client, err := s.clientRepo.GetById(ctx, tx, clientId) if err != nil { tx.Rollback() return err } userID := utils.GetUserID(ctx) client.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE) if _, err := s.clientRepo.Update(ctx, tx, client); err != nil { tx.Rollback() return err } err = s.clientRepo.Delete(ctx, tx, clientId) if err != nil { tx.Rollback() return err } err = tx.Commit().Error if err != nil { tx.Rollback() return err } s.log.WithFields(logrus.Fields{ "user_id": userID, "action": "delete", "entity": "client", "entity_id": clientId, }).Info("Client deleted") 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, log *logrus.Logger) ClientService { return &clientService{ clientRepo: clientRepo, db: db, log: log, } }