From 2db31dc017c98089dc2fdad6f1a97f1135c0c8e6 Mon Sep 17 00:00:00 2001 From: Habib Fatkhul Rohman Date: Tue, 28 Oct 2025 10:09:31 +0700 Subject: [PATCH] feat: Add client module with CRUD operations, DTOs, repository, and service layers --- cmd/main.go | 2 + database/entities/m_client_entity.go | 2 +- database/seeders/seeds/client_seed.go | 2 +- .../client/controller/client_controller.go | 149 ++++++++++++++ modules/client/dto/client_dto.go | 54 +++++ modules/client/query/client_query.go | 96 +++++++++ .../client/repository/client_repository.go | 82 ++++++++ modules/client/routes.go | 24 +++ modules/client/service/client_service.go | 190 ++++++++++++++++++ providers/core.go | 12 +- 10 files changed, 610 insertions(+), 3 deletions(-) create mode 100644 modules/client/controller/client_controller.go create mode 100644 modules/client/dto/client_dto.go create mode 100644 modules/client/query/client_query.go create mode 100644 modules/client/repository/client_repository.go create mode 100644 modules/client/routes.go create mode 100644 modules/client/service/client_service.go diff --git a/cmd/main.go b/cmd/main.go index 31f6962..2446d33 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -8,6 +8,7 @@ import ( "github.com/Caknoooo/go-gin-clean-starter/docs" "github.com/Caknoooo/go-gin-clean-starter/middlewares" "github.com/Caknoooo/go-gin-clean-starter/modules/auth" + "github.com/Caknoooo/go-gin-clean-starter/modules/client" maintenancegroup "github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group" "github.com/Caknoooo/go-gin-clean-starter/modules/menu" "github.com/Caknoooo/go-gin-clean-starter/modules/role" @@ -124,6 +125,7 @@ func main() { logs.RegisterRoutes(server, injector) menu.RegisterRoutes(server, injector) maintenancegroup.RegisterRoutes(server, injector) + client.RegisterRoutes(server, injector) // register swagger route server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) diff --git a/database/entities/m_client_entity.go b/database/entities/m_client_entity.go index 5eb3b49..aa850c5 100644 --- a/database/entities/m_client_entity.go +++ b/database/entities/m_client_entity.go @@ -9,7 +9,7 @@ type M_Client struct { Phone string `gorm:"type:varchar(20)" json:"phone"` Email string `gorm:"type:varchar(100)" json:"email"` Address string `gorm:"type:text" json:"address"` - LogoUrl string `gorm:"type:varchar(255)" json:"logo_url"` + Logo string `gorm:"type:text" json:"logo"` // simpan base64 string hasil konversi file gambar Users []M_User `gorm:"foreignKey:ClientID;references:ID" json:"users"` MaintenanceGroups []M_MaintenanceGroup `gorm:"foreignKey:ClientID;references:ID" json:"maintenance_groups"` diff --git a/database/seeders/seeds/client_seed.go b/database/seeders/seeds/client_seed.go index b017fee..b0b0231 100644 --- a/database/seeders/seeds/client_seed.go +++ b/database/seeders/seeds/client_seed.go @@ -62,7 +62,7 @@ func ListClientSeeder(db *gorm.DB) error { Phone: data.Phone, Email: data.Email, Address: data.Address, - LogoUrl: data.LogoUrl, + // Logo: data.LogoUrl, }).Error; err != nil { fmt.Println("Error seeding client:", err) return err diff --git a/modules/client/controller/client_controller.go b/modules/client/controller/client_controller.go new file mode 100644 index 0000000..5dd28c3 --- /dev/null +++ b/modules/client/controller/client_controller.go @@ -0,0 +1,149 @@ +package controller + +import ( + "encoding/base64" + "io" + "net/http" + + "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/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 ( + ClientController interface { + Create(ctx *gin.Context) + Update(ctx *gin.Context) + Delete(ctx *gin.Context) + GetById(ctx *gin.Context) + GetAll(ctx *gin.Context) + } + + clientController struct { + clientService service.ClientService + db *gorm.DB + } +) + +func NewClientController(i *do.Injector, clientService service.ClientService) ClientController { + db := do.MustInvokeNamed[*gorm.DB](i, constants.DB) + return &clientController{ + clientService: clientService, + db: db, + } +} + +func (c *clientController) Create(ctx *gin.Context) { + var req dto.ClientCreateRequest + if err := ctx.ShouldBind(&req); err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) + ctx.JSON(http.StatusBadRequest, res) + return + } + + // Ambil file logo (opsional) + file, _, err := ctx.Request.FormFile("logo") + if err == nil && file != nil { + fileBytes, _ := io.ReadAll(file) + base64Str := base64.StdEncoding.EncodeToString(fileBytes) + req.Logo = base64Str + } + + created, err := c.clientService.Create(ctx, req) + if err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_CREATE_CLIENT, err.Error(), nil) + ctx.JSON(http.StatusInternalServerError, res) + return + } + + res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_CREATE_CLIENT, created) + ctx.JSON(http.StatusOK, res) +} + +func (c *clientController) Update(ctx *gin.Context) { + id := ctx.Param("id") + var req dto.ClientUpdateRequest + if err := ctx.ShouldBind(&req); err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) + ctx.JSON(http.StatusBadRequest, res) + return + } + + // Ambil file logo (opsional, untuk update) + file, _, err := ctx.Request.FormFile("logo") + if err == nil && file != nil { + fileBytes, _ := io.ReadAll(file) + base64Str := base64.StdEncoding.EncodeToString(fileBytes) + req.Logo = &base64Str + } + + client, err := c.clientService.Update(ctx, req, id) + if err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_CLIENT, err.Error(), nil) + ctx.JSON(http.StatusInternalServerError, res) + return + } + + res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_CLIENT, client) + ctx.JSON(http.StatusOK, res) +} + +func (c *clientController) Delete(ctx *gin.Context) { + id := ctx.Param("id") + if err := c.clientService.Delete(ctx, id); err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_CLIENT, err.Error(), nil) + ctx.JSON(http.StatusInternalServerError, res) + return + } + res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_CLIENT, nil) + ctx.JSON(http.StatusOK, res) +} + +func (c *clientController) GetById(ctx *gin.Context) { + id := ctx.Param("id") + client, err := c.clientService.GetById(ctx, id) + if err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_CLIENT, err.Error(), nil) + ctx.JSON(http.StatusNotFound, res) + return + } + res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_CLIENT, client) + ctx.JSON(http.StatusOK, res) +} + +func (c *clientController) GetAll(ctx *gin.Context) { + // clientId := ctx.MustGet("client_id").(string) + var filter = &query.ClientFilter{ + Name: ctx.Query("name"), + PIC: ctx.Query("pic"), + Phone: ctx.Query("phone"), + Email: ctx.Query("email"), + Address: ctx.Query("address"), + // ClientID: clientId, + Includes: ctx.QueryArray("includes"), + } + filter.BindPagination(ctx) + ctx.ShouldBindQuery(filter) + groups, total, err := pagination.PaginatedQueryWithIncludableAndOptions[query.M_Client]( + c.db, + filter, + pagination.PaginatedQueryOptions{ + EnableSoftDelete: true, + }, + ) + if err != nil { + res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_CLIENT, err.Error(), nil) + ctx.JSON(http.StatusBadRequest, res) + return + } + paginationResponse := pagination.CalculatePagination(filter.Pagination, total) + + response := pagination.NewPaginatedResponse(http.StatusOK, dto.MESSAGE_SUCCESS_GET_CLIENT, groups, paginationResponse) + ctx.JSON(http.StatusOK, response) +} diff --git a/modules/client/dto/client_dto.go b/modules/client/dto/client_dto.go new file mode 100644 index 0000000..a6bd4bc --- /dev/null +++ b/modules/client/dto/client_dto.go @@ -0,0 +1,54 @@ +package dto + +import ( + "errors" +) + +const ( + MESSAGE_FAILED_CREATE_CLIENT = "failed create client" + MESSAGE_SUCCESS_CREATE_CLIENT = "success create client" + MESSAGE_FAILED_GET_CLIENT = "failed get client" + MESSAGE_SUCCESS_GET_CLIENT = "success get client" + MESSAGE_FAILED_UPDATE_CLIENT = "failed update client" + MESSAGE_SUCCESS_UPDATE_CLIENT = "success update client" + MESSAGE_FAILED_DELETE_CLIENT = "failed delete client" + MESSAGE_SUCCESS_DELETE_CLIENT = "success delete client" + MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body" +) + +var ( + ErrCreateClient = errors.New("failed to create client") + ErrGetClientById = errors.New("failed to get client by id") + ErrUpdateClient = errors.New("failed to update client") + ErrDeleteClient = errors.New("failed to delete client") +) + +type ( + ClientCreateRequest struct { + Name string `json:"name" form:"name" binding:"required,min=2,max=100"` + PIC string `json:"pic" form:"pic" binding:"omitempty,min=2,max=100"` + Phone string `json:"phone" form:"phone" binding:"omitempty,min=6,max=20"` + Email string `json:"email" form:"email" binding:"omitempty,email,max=100"` + Address string `json:"address" form:"address" binding:"omitempty"` + Logo string `form:"-"` // diisi manual dari file, tidak di-bind otomatis + } + + ClientResponse 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"` + } + + ClientUpdateRequest struct { + Name *string `json:"name" form:"name" binding:"omitempty,min=2,max=100"` + PIC *string `json:"pic" form:"pic" binding:"omitempty,min=2,max=100"` + Phone *string `json:"phone" form:"phone" binding:"omitempty,min=6,max=20"` + Email *string `json:"email" form:"email" binding:"omitempty,email,max=100"` + Address *string `json:"address" form:"address" binding:"omitempty"` + Logo *string `form:"-"` // jika update logo, isi manual dari file + } +) diff --git a/modules/client/query/client_query.go b/modules/client/query/client_query.go new file mode 100644 index 0000000..d2bf1b2 --- /dev/null +++ b/modules/client/query/client_query.go @@ -0,0 +1,96 @@ +package query + +import ( + "github.com/Caknoooo/go-pagination" + "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 { + pagination.BaseFilter + Name string `form:"name"` // tambahkan ini + PIC string `form:"pic"` // tambahkan ini + Phone string `form:"phone"` // tambahkan ini + Email string `form:"email"` // tambahkan ini + Address string `form:"address"` // tambahkan ini + ClientID string `form:"client_id"` // tambahkan ini + Includes []string `form:"includes"` // tambahkan ini +} + +func (f *ClientFilter) ApplyFilters(query *gorm.DB) *gorm.DB { + // Apply your filters here + if f.Name != "" { + query = query.Where("name ILIKE ?", "%"+f.Name+"%") + } + if f.ClientID != "" { + query = query.Where("client_id = ?", f.ClientID) + } + if f.PIC != "" { + query = query.Where("pic ILIKE ?", "%"+f.PIC+"%") + } + if f.Phone != "" { + query = query.Where("phone ILIKE ?", "%"+f.Phone+"%") + } + if f.Email != "" { + query = query.Where("email ILIKE ?", "%"+f.Email+"%") + } + if f.Address != "" { + query = query.Where("address ILIKE ?", "%"+f.Address+"%") + } + + // 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, + } +} diff --git a/modules/client/repository/client_repository.go b/modules/client/repository/client_repository.go new file mode 100644 index 0000000..5431881 --- /dev/null +++ b/modules/client/repository/client_repository.go @@ -0,0 +1,82 @@ +package repository + +import ( + "context" + + "github.com/Caknoooo/go-gin-clean-starter/database/entities" + "github.com/google/uuid" + "gorm.io/gorm" +) + +type ( + ClientRepository interface { + 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) + GetByName(ctx context.Context, tx *gorm.DB, name string) (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 + } + + clientRepository struct { + db *gorm.DB + } +) + +func (r *clientRepository) Create(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) { + if tx == nil { + tx = r.db + } + if client.ID == uuid.Nil { + client.ID = uuid.New() + } + if err := tx.WithContext(ctx).Create(&client).Error; err != nil { + return entities.M_Client{}, err + } + return client, nil +} + +func (r *clientRepository) GetById(ctx context.Context, tx *gorm.DB, clientId string) (entities.M_Client, error) { + if tx == nil { + tx = r.db + } + var client entities.M_Client + if err := tx.WithContext(ctx).First(&client, "id = ?", clientId).Error; err != nil { + return entities.M_Client{}, err + } + return client, nil +} + +func (r *clientRepository) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.M_Client, error) { + if tx == nil { + tx = r.db + } + var client entities.M_Client + if err := tx.WithContext(ctx).Where("name = ?", name).First(&client).Error; err != nil { + return entities.M_Client{}, err + } + return client, nil +} + +func (r *clientRepository) Update(ctx context.Context, tx *gorm.DB, client entities.M_Client) (entities.M_Client, error) { + if tx == nil { + tx = r.db + } + if err := tx.WithContext(ctx).Updates(&client).Error; err != nil { + return entities.M_Client{}, err + } + return client, nil +} + +func (r *clientRepository) Delete(ctx context.Context, tx *gorm.DB, clientId string) error { + if tx == nil { + tx = r.db + } + if err := tx.WithContext(ctx).Delete(&entities.M_Client{}, "id = ?", clientId).Error; err != nil { + return err + } + return nil +} + +func NewClientRepository(db *gorm.DB) ClientRepository { + return &clientRepository{db: db} +} diff --git a/modules/client/routes.go b/modules/client/routes.go new file mode 100644 index 0000000..82e9457 --- /dev/null +++ b/modules/client/routes.go @@ -0,0 +1,24 @@ +package client + +import ( + "github.com/Caknoooo/go-gin-clean-starter/middlewares" + "github.com/Caknoooo/go-gin-clean-starter/modules/auth/service" + "github.com/Caknoooo/go-gin-clean-starter/modules/client/controller" + "github.com/Caknoooo/go-gin-clean-starter/pkg/constants" + "github.com/gin-gonic/gin" + "github.com/samber/do" +) + +func RegisterRoutes(server *gin.Engine, injector *do.Injector) { + clientController := do.MustInvoke[controller.ClientController](injector) + jwtService := do.MustInvokeNamed[service.JWTService](injector, constants.JWTService) + + clientRoutes := server.Group("/api/v1/clients") + { + clientRoutes.POST("", middlewares.Authenticate(jwtService), clientController.Create) + clientRoutes.GET("/:id", middlewares.Authenticate(jwtService), clientController.GetById) + clientRoutes.PUT("/:id", middlewares.Authenticate(jwtService), clientController.Update) + clientRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), clientController.Delete) + clientRoutes.GET("", middlewares.Authenticate(jwtService), clientController.GetAll) + } +} diff --git a/modules/client/service/client_service.go b/modules/client/service/client_service.go new file mode 100644 index 0000000..4c55be7 --- /dev/null +++ b/modules/client/service/client_service.go @@ -0,0 +1,190 @@ +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/repository" + "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) + Update(ctx context.Context, client dto.ClientUpdateRequest, clientId string) (dto.ClientResponse, error) + Delete(ctx context.Context, clientId string) error +} + +type clientService struct { + db *gorm.DB + clientRepo repository.ClientRepository +} + +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() + } + }() + + client := entities.M_Client{ + Name: req.Name, + PIC: req.PIC, + Phone: req.Phone, + Email: req.Email, + Address: req.Address, + Logo: req.Logo, // []byte, sudah benar untuk simpan file + } + + 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 + } + + // Mapping entity ke response (Logo bisa dikonversi ke base64 jika perlu) + // logoBase64 := "" + // if len(createdClient.Logo) > 0 { + // logoBase64 = base64.StdEncoding.EncodeToString(createdClient.Logo) + // } + + return dto.ClientResponse{ + ID: createdClient.ID.String(), + Name: createdClient.Name, + PIC: createdClient.PIC, + Phone: createdClient.Phone, + Email: createdClient.Email, + Address: createdClient.Address, + Logo: req.Logo, + }, 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) + // } + 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) 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 + } + 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 + } + // logoBase64 := "" + // if len(updatedClient.Logo) > 0 { + // logoBase64 = base64.StdEncoding.EncodeToString(updatedClient.Logo) + // } + return dto.ClientResponse{ + ID: updatedClient.ID.String(), + Name: updatedClient.Name, + PIC: updatedClient.PIC, + Phone: updatedClient.Phone, + Email: updatedClient.Email, + Address: updatedClient.Address, + Logo: updatedClient.Logo, + }, nil +} + +func (s *clientService) Delete(ctx context.Context, clientId string) error { + tx := s.db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + 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 + } + return nil +} + +func NewClientService(clientRepo repository.ClientRepository, db *gorm.DB) ClientService { + return &clientService{ + clientRepo: clientRepo, + db: db, + } +} diff --git a/providers/core.go b/providers/core.go index bb12778..4ea610b 100644 --- a/providers/core.go +++ b/providers/core.go @@ -4,6 +4,9 @@ import ( "github.com/Caknoooo/go-gin-clean-starter/config" authRepo "github.com/Caknoooo/go-gin-clean-starter/modules/auth/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/auth/service" + clientController "github.com/Caknoooo/go-gin-clean-starter/modules/client/controller" + clientRepo "github.com/Caknoooo/go-gin-clean-starter/modules/client/repository" + clientService "github.com/Caknoooo/go-gin-clean-starter/modules/client/service" "github.com/sirupsen/logrus" // productController "github.com/Caknoooo/go-gin-clean-starter/modules/product/controller" @@ -58,8 +61,9 @@ func RegisterDependencies(injector *do.Injector) { userRepository := repository.NewUserRepository(db) refreshTokenRepository := authRepo.NewRefreshTokenRepository(db) // productRepository := productRepo.NewProductRepository(db) - roleRepository := roleRepo.NewRoleRepository(db) menuRepository := menuRepo.NewMenuRepository(db) + roleRepository := roleRepo.NewRoleRepository(db) + clientRepository := clientRepo.NewClientRepository(db) maintenanceGroupRepository := maintGroupRepo.NewMaintGroupRepository(db) maintenanceGroupRoleRepository := maintGroupRepoRole.NewMaintGroupRoleRepository(db) maintenanceGroupRoleUserRepository := maintGroupRepoRoleUser.NewMaintGroupRoleUserRepository(db) @@ -70,8 +74,14 @@ func RegisterDependencies(injector *do.Injector) { roleService := roleService.NewRoleService(roleRepository, refreshTokenRepository, jwtService, userServ, db) menuSvc := menuService.NewMenuService(menuRepository, jwtService, db) maintenanceGroupServ := maintGroupService.NewMaintenanceGroupService(maintenanceGroupRepository, maintenanceGroupRoleRepository, maintenanceGroupRoleUserRepository, db) + clientServ := clientService.NewClientService(clientRepository, db) // Controller + do.Provide( + injector, func(i *do.Injector) (clientController.ClientController, error) { + return clientController.NewClientController(i, clientServ), nil + }, + ) do.Provide( injector, func(i *do.Injector) (controller.UserController, error) { return controller.NewUserController(i, userServ), nil