From 83573032373ad08a3a3c9334606d709319334584 Mon Sep 17 00:00:00 2001 From: Habib Fatkhul Rohman Date: Tue, 21 Oct 2025 15:03:53 +0700 Subject: [PATCH] Remove product and tenant modules, including controllers, services, repositories, DTOs, queries, and routes for a cleaner codebase. --- .../product/controller/product_controller.go | 128 ------------------ modules/product/dto/product_dto.go | 89 ------------ modules/product/query/product_query.go | 64 --------- .../product/repository/product_repository.go | 108 --------------- modules/product/routes.go | 24 ---- modules/product/service/product_service.go | 111 --------------- .../tenant/controller/tenant_controller.go | 122 ----------------- modules/tenant/dto/tenant_dto.go | 83 ------------ modules/tenant/query/tenant_query.go | 63 --------- .../tenant/repository/tenant_repository.go | 109 --------------- modules/tenant/routes.go | 24 ---- modules/tenant/service/tenant_service.go | 102 -------------- 12 files changed, 1027 deletions(-) delete mode 100644 modules/product/controller/product_controller.go delete mode 100644 modules/product/dto/product_dto.go delete mode 100644 modules/product/query/product_query.go delete mode 100644 modules/product/repository/product_repository.go delete mode 100644 modules/product/routes.go delete mode 100644 modules/product/service/product_service.go delete mode 100644 modules/tenant/controller/tenant_controller.go delete mode 100644 modules/tenant/dto/tenant_dto.go delete mode 100644 modules/tenant/query/tenant_query.go delete mode 100644 modules/tenant/repository/tenant_repository.go delete mode 100644 modules/tenant/routes.go delete mode 100644 modules/tenant/service/tenant_service.go diff --git a/modules/product/controller/product_controller.go b/modules/product/controller/product_controller.go deleted file mode 100644 index 48d4375..0000000 --- a/modules/product/controller/product_controller.go +++ /dev/null @@ -1,128 +0,0 @@ -package controller - -import ( - "net/http" - - "github.com/Caknoooo/go-gin-clean-starter/modules/product/dto" - "github.com/Caknoooo/go-gin-clean-starter/modules/product/query" - "github.com/Caknoooo/go-gin-clean-starter/modules/product/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 ( - ProductController interface { - Create(ctx *gin.Context) - GetAll(ctx *gin.Context) - GetById(ctx *gin.Context) - Update(ctx *gin.Context) - Delete(ctx *gin.Context) - } - - productController struct { - productService service.ProductService - db *gorm.DB - } -) - -func NewProductController(injector *do.Injector, ps service.ProductService) ProductController { - db := do.MustInvokeNamed[*gorm.DB](injector, constants.DB) - return &productController{ - productService: ps, - db: db, - } -} - -func (c *productController) Create(ctx *gin.Context) { - var product dto.ProductCreateRequest - if err := ctx.ShouldBind(&product); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) - ctx.AbortWithStatusJSON(http.StatusBadRequest, res) - return - } - - tenantID := ctx.MustGet("tenant_id").(string) - product.TenantID = tenantID // set tenantID dari middleware ke request - - result, err := c.productService.Create(ctx.Request.Context(), product) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_REGISTER_PRODUCT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_REGISTER_PRODUCT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *productController) GetById(ctx *gin.Context) { - productId := ctx.Param("id") - - result, err := c.productService.GetProductById(ctx.Request.Context(), productId) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_PRODUCT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_PRODUCT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *productController) GetAll(ctx *gin.Context) { - tenantId := ctx.MustGet("tenant_id").(string) - var filter = &query.ProductFilter{ - TenantID: tenantId, - Name: ctx.Query("name"), - } - filter.BindPagination(ctx) - - ctx.ShouldBindQuery(filter) - - products, total, err := pagination.PaginatedQueryWithIncludable[query.Product](c.db, filter) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_PRODUCT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - paginationResponse := pagination.CalculatePagination(filter.Pagination, total) - response := pagination.NewPaginatedResponse(http.StatusOK, dto.MESSAGE_SUCCESS_GET_LIST_PRODUCT, products, paginationResponse) - ctx.JSON(http.StatusOK, response) -} - -func (c *productController) Update(ctx *gin.Context) { - productId := ctx.Param("id") - var product dto.ProductUpdateRequest - if err := ctx.ShouldBind(&product); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) - ctx.AbortWithStatusJSON(http.StatusBadRequest, res) - return - } - - result, err := c.productService.Update(ctx.Request.Context(), product, productId) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_PRODUCT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_PRODUCT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *productController) Delete(ctx *gin.Context) { - productId := ctx.Param("id") - - if err := c.productService.Delete(ctx.Request.Context(), productId); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_PRODUCT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_PRODUCT, nil) - ctx.JSON(http.StatusOK, res) -} diff --git a/modules/product/dto/product_dto.go b/modules/product/dto/product_dto.go deleted file mode 100644 index c5da006..0000000 --- a/modules/product/dto/product_dto.go +++ /dev/null @@ -1,89 +0,0 @@ -package dto - -import ( - "errors" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" -) - -const ( - // Failed - MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body" - MESSAGE_FAILED_REGISTER_PRODUCT = "failed create product" - MESSAGE_FAILED_GET_LIST_PRODUCT = "failed get list product" - MESSAGE_FAILED_TOKEN_NOT_VALID = "token not valid" - MESSAGE_FAILED_TOKEN_NOT_FOUND = "token not found" - MESSAGE_FAILED_GET_PRODUCT = "failed get product" - MESSAGE_FAILED_LOGIN = "failed login" - MESSAGE_FAILED_UPDATE_PRODUCT = "failed update product" - MESSAGE_FAILED_DELETE_PRODUCT = "failed delete product" - MESSAGE_FAILED_PROSES_REQUEST = "failed proses request" - MESSAGE_FAILED_DENIED_ACCESS = "denied access" - MESSAGE_FAILED_VERIFY_EMAIL = "failed verify email" - - // Success - MESSAGE_SUCCESS_REGISTER_PRODUCT = "success create product" - MESSAGE_SUCCESS_GET_LIST_PRODUCT = "success get list product" - MESSAGE_SUCCESS_GET_PRODUCT = "success get product" - MESSAGE_SUCCESS_LOGIN = "success login" - MESSAGE_SUCCESS_UPDATE_PRODUCT = "success update product" - MESSAGE_SUCCESS_DELETE_PRODUCT = "success delete product" - MESSAGE_SEND_VERIFICATION_EMAIL_SUCCESS = "success send verification email" - MESSAGE_SUCCESS_VERIFY_EMAIL = "success verify email" -) - -var ( - ErrCreateProduct = errors.New("failed to create product") - ErrGetProductById = errors.New("failed to get product by id") - ErrGetProductByName = errors.New("failed to get product by name") - ErrProductAlreadyExists = errors.New("product already exist") - ErrUpdateProduct = errors.New("failed to update product") - ErrProductNotFound = errors.New("product not found") - ErrEmailNotFound = errors.New("email not found") - ErrDeleteProduct = errors.New("failed to delete product") - ErrTokenInvalid = errors.New("token invalid") - ErrTokenExpired = errors.New("token expired") - ErrAccountAlreadyVerified = errors.New("account already verified") - ErrNameAlreadyExists = errors.New("name already exists") -) - -type ( - ProductCreateRequest struct { - Name string `json:"name" form:"name" binding:"required,min=2,max=100"` - Price float64 `json:"price" form:"price" binding:"required,gt=0"` - // TenantID akan diisi dari context (middleware) - TenantID string `json:"tenant_id" form:"tenant_id" binding:"-"` - } - - ProductResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Price float64 `json:"price"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - } - - ProductPaginationResponse struct { - Data []ProductResponse `json:"data"` - dto.PaginationResponse - } - - GetAllProductRepositoryResponse struct { - Products []entities.Product `json:"products"` - dto.PaginationResponse - } - - ProductUpdateRequest struct { - Name string `json:"name" form:"name" binding:"omitempty,min=2,max=100"` - Price float64 `json:"price" form:"price" binding:"omitempty,gt=0"` - } - - ProductUpdateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Price float64 `json:"price"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - } -) diff --git a/modules/product/query/product_query.go b/modules/product/query/product_query.go deleted file mode 100644 index c852851..0000000 --- a/modules/product/query/product_query.go +++ /dev/null @@ -1,64 +0,0 @@ -package query - -import ( - "github.com/Caknoooo/go-pagination" - "gorm.io/gorm" -) - -type Product struct { - ID string `json:"id"` - Name string `json:"name"` - Price float64 `json:"price"` -} - -type ProductFilter struct { - pagination.BaseFilter - Name string `form:"name"` // tambahkan ini - TenantID string `form:"tenant_id"` // tambahkan ini -} - -func (f *ProductFilter) ApplyFilters(query *gorm.DB) *gorm.DB { - // Apply your filters here - if f.Name != "" { - query = query.Where("name ILIKE ?", "%"+f.Name+"%") - } - if f.TenantID != "" { - query = query.Where("tenant_id = ?", f.TenantID) - } - return query -} - -func (f *ProductFilter) GetTableName() string { - return "products" -} - -func (f *ProductFilter) GetSearchFields() []string { - return []string{"name"} -} - -func (f *ProductFilter) GetDefaultSort() string { - return "id asc" -} - -func (f *ProductFilter) GetIncludes() []string { - return f.Includes -} - -func (f *ProductFilter) GetPagination() pagination.PaginationRequest { - return f.Pagination -} - -func (f *ProductFilter) Validate() { - var validIncludes []string - allowedIncludes := f.GetAllowedIncludes() - for _, include := range f.Includes { - if allowedIncludes[include] { - validIncludes = append(validIncludes, include) - } - } - f.Includes = validIncludes -} - -func (f *ProductFilter) GetAllowedIncludes() map[string]bool { - return map[string]bool{} -} diff --git a/modules/product/repository/product_repository.go b/modules/product/repository/product_repository.go deleted file mode 100644 index cba2b64..0000000 --- a/modules/product/repository/product_repository.go +++ /dev/null @@ -1,108 +0,0 @@ -package repository - -import ( - "context" - "errors" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "gorm.io/gorm" -) - -type ( - ProductRepository interface { - Create(ctx context.Context, tx *gorm.DB, product entities.Product) (entities.Product, error) - GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.Product, error) - GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.Product, error) - CheckName(ctx context.Context, tx *gorm.DB, name string) (entities.Product, bool, error) - Update(ctx context.Context, tx *gorm.DB, product entities.Product) (entities.Product, error) - Delete(ctx context.Context, tx *gorm.DB, productId string) error - } - - productRepository struct { - db *gorm.DB - } -) - -func NewProductRepository(db *gorm.DB) ProductRepository { - return &productRepository{ - db: db, - } -} - -func (r *productRepository) Create(ctx context.Context, tx *gorm.DB, product entities.Product) (entities.Product, error) { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Create(&product).Error; err != nil { - return entities.Product{}, err - } - - return product, nil -} - -func (r *productRepository) GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.Product, error) { - if tx == nil { - tx = r.db - } - - var product entities.Product - if err := tx.WithContext(ctx).Where("id = ?", productId).Take(&product).Error; err != nil { - return entities.Product{}, err - } - - return product, nil -} - -func (r *productRepository) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.Product, error) { - if tx == nil { - tx = r.db - } - - var product entities.Product - if err := tx.WithContext(ctx).Where("name = ?", name).Take(&product).Error; err != nil { - return entities.Product{}, err - } - - return product, nil -} - -func (r *productRepository) Update(ctx context.Context, tx *gorm.DB, product entities.Product) (entities.Product, error) { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Updates(&product).Error; err != nil { - return entities.Product{}, err - } - - return product, nil -} - -func (r *productRepository) Delete(ctx context.Context, tx *gorm.DB, productId string) error { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Delete(&entities.Product{}, "id = ?", productId).Error; err != nil { - return err - } - - return nil -} - -func (r *productRepository) CheckName(ctx context.Context, tx *gorm.DB, name string) (entities.Product, bool, error) { - if tx == nil { - tx = r.db - } - - var product entities.Product - if err := tx.WithContext(ctx).Where("name = ?", name).Take(&product).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return entities.Product{}, false, nil - } - return entities.Product{}, false, err - } - - return product, true, nil -} diff --git a/modules/product/routes.go b/modules/product/routes.go deleted file mode 100644 index eebd8bd..0000000 --- a/modules/product/routes.go +++ /dev/null @@ -1,24 +0,0 @@ -package product - -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/product/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) { - productController := do.MustInvoke[controller.ProductController](injector) - jwtService := do.MustInvokeNamed[service.JWTService](injector, constants.JWTService) - - productRoutes := server.Group("/api/product") - { - productRoutes.POST("", middlewares.Authenticate(jwtService), productController.Create) - productRoutes.GET("", middlewares.Authenticate(jwtService), productController.GetAll) - productRoutes.GET("/:id", middlewares.Authenticate(jwtService), productController.GetById) - productRoutes.PUT("/:id", middlewares.Authenticate(jwtService), productController.Update) - productRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), productController.Delete) - } -} diff --git a/modules/product/service/product_service.go b/modules/product/service/product_service.go deleted file mode 100644 index afc5d00..0000000 --- a/modules/product/service/product_service.go +++ /dev/null @@ -1,111 +0,0 @@ -package service - -import ( - "context" - "time" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "github.com/Caknoooo/go-gin-clean-starter/modules/product/dto" - "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository" - "github.com/google/uuid" - "gorm.io/gorm" -) - -type ProductService interface { - Create(ctx context.Context, req dto.ProductCreateRequest) (dto.ProductResponse, error) - GetProductById(ctx context.Context, productId string) (dto.ProductResponse, error) - Update(ctx context.Context, req dto.ProductUpdateRequest, productId string) (dto.ProductUpdateResponse, error) - Delete(ctx context.Context, productId string) error -} - -type productService struct { - productRepository repository.ProductRepository - db *gorm.DB -} - -func NewProductService( - productRepo repository.ProductRepository, - db *gorm.DB, -) ProductService { - return &productService{ - productRepository: productRepo, - db: db, - } -} - -func (s *productService) Create(ctx context.Context, req dto.ProductCreateRequest) (dto.ProductResponse, error) { - _, exists, err := s.productRepository.CheckName(ctx, s.db, req.Name) - if err != nil && err != gorm.ErrRecordNotFound { - return dto.ProductResponse{}, err - } - if exists { - return dto.ProductResponse{}, dto.ErrNameAlreadyExists - } - - product := entities.Product{ - ID: uuid.New(), - Name: req.Name, - Price: req.Price, - TenantID: uuid.MustParse(req.TenantID), - } - - createdProduct, err := s.productRepository.Create(ctx, s.db, product) - if err != nil { - return dto.ProductResponse{}, err - } - - return dto.ProductResponse{ - ID: createdProduct.ID.String(), - Name: createdProduct.Name, - Price: createdProduct.Price, - CreatedAt: createdProduct.CreatedAt.Format(time.RFC3339), - UpdatedAt: createdProduct.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *productService) GetProductById(ctx context.Context, productId string) (dto.ProductResponse, error) { - product, err := s.productRepository.GetById(ctx, s.db, productId) - if err != nil { - return dto.ProductResponse{}, err - } - - return dto.ProductResponse{ - ID: product.ID.String(), - Name: product.Name, - Price: product.Price, - CreatedAt: product.CreatedAt.Format(time.RFC3339), - UpdatedAt: product.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *productService) Update(ctx context.Context, req dto.ProductUpdateRequest, productId string) (dto.ProductUpdateResponse, error) { - product, err := s.productRepository.GetById(ctx, s.db, productId) - if err != nil { - return dto.ProductUpdateResponse{}, dto.ErrProductNotFound - } - - if req.Name != "" { - product.Name = req.Name - } - - if req.Price >= 0 { - product.Price = req.Price - } - - updatedProduct, err := s.productRepository.Update(ctx, s.db, product) - if err != nil { - return dto.ProductUpdateResponse{}, err - } - - return dto.ProductUpdateResponse{ - ID: updatedProduct.ID.String(), - Name: updatedProduct.Name, - Price: updatedProduct.Price, - CreatedAt: updatedProduct.CreatedAt.Format(time.RFC3339), - UpdatedAt: updatedProduct.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *productService) Delete(ctx context.Context, productId string) error { - return s.productRepository.Delete(ctx, s.db, productId) -} diff --git a/modules/tenant/controller/tenant_controller.go b/modules/tenant/controller/tenant_controller.go deleted file mode 100644 index 4018432..0000000 --- a/modules/tenant/controller/tenant_controller.go +++ /dev/null @@ -1,122 +0,0 @@ -package controller - -import ( - "net/http" - - "github.com/Caknoooo/go-gin-clean-starter/modules/tenant/dto" - "github.com/Caknoooo/go-gin-clean-starter/modules/tenant/query" - "github.com/Caknoooo/go-gin-clean-starter/modules/tenant/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 ( - TenantController interface { - Create(ctx *gin.Context) - GetAll(ctx *gin.Context) - GetById(ctx *gin.Context) - Update(ctx *gin.Context) - Delete(ctx *gin.Context) - } - - tenantController struct { - tenantService service.TenantService - db *gorm.DB - } -) - -func NewTenantController(injector *do.Injector, ts service.TenantService) TenantController { - db := do.MustInvokeNamed[*gorm.DB](injector, constants.DB) - return &tenantController{ - tenantService: ts, - db: db, - } -} - -func (c *tenantController) Create(ctx *gin.Context) { - var tenant dto.TenantCreateRequest - if err := ctx.ShouldBind(&tenant); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) - ctx.AbortWithStatusJSON(http.StatusBadRequest, res) - return - } - - result, err := c.tenantService.Create(ctx.Request.Context(), tenant) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_REGISTER_TENANT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_REGISTER_TENANT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *tenantController) GetById(ctx *gin.Context) { - tenantId := ctx.Param("id") - - result, err := c.tenantService.GetTenantById(ctx.Request.Context(), tenantId) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_TENANT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_TENANT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *tenantController) GetAll(ctx *gin.Context) { - var filter = &query.TenantFilter{} - filter.BindPagination(ctx) - - ctx.ShouldBindQuery(filter) - - tenants, total, err := pagination.PaginatedQueryWithIncludable[query.Tenant](c.db, filter) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_TENANT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - paginationResponse := pagination.CalculatePagination(filter.Pagination, total) - response := pagination.NewPaginatedResponse(http.StatusOK, dto.MESSAGE_SUCCESS_GET_LIST_TENANT, tenants, paginationResponse) - ctx.JSON(http.StatusOK, response) -} - -func (c *tenantController) Update(ctx *gin.Context) { - tenantId := ctx.Param("id") - var tenant dto.TenantUpdateRequest - if err := ctx.ShouldBind(&tenant); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil) - ctx.AbortWithStatusJSON(http.StatusBadRequest, res) - return - } - - result, err := c.tenantService.Update(ctx.Request.Context(), tenant, tenantId) - if err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_TENANT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_TENANT, result) - ctx.JSON(http.StatusOK, res) -} - -func (c *tenantController) Delete(ctx *gin.Context) { - tenantId := ctx.Param("id") - - if err := c.tenantService.Delete(ctx.Request.Context(), tenantId); err != nil { - res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_TENANT, err.Error(), nil) - ctx.JSON(http.StatusBadRequest, res) - return - } - - res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_TENANT, nil) - ctx.JSON(http.StatusOK, res) -} diff --git a/modules/tenant/dto/tenant_dto.go b/modules/tenant/dto/tenant_dto.go deleted file mode 100644 index 46ea4b2..0000000 --- a/modules/tenant/dto/tenant_dto.go +++ /dev/null @@ -1,83 +0,0 @@ -package dto - -import ( - "errors" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" -) - -const ( - // Failed - MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body" - MESSAGE_FAILED_REGISTER_TENANT = "failed create tenant" - MESSAGE_FAILED_GET_LIST_TENANT = "failed get list tenant" - MESSAGE_FAILED_TOKEN_NOT_VALID = "token not valid" - MESSAGE_FAILED_TOKEN_NOT_FOUND = "token not found" - MESSAGE_FAILED_GET_TENANT = "failed get tenant" - MESSAGE_FAILED_LOGIN = "failed login" - MESSAGE_FAILED_UPDATE_TENANT = "failed update tenant" - MESSAGE_FAILED_DELETE_TENANT = "failed delete tenant" - MESSAGE_FAILED_PROSES_REQUEST = "failed proses request" - MESSAGE_FAILED_DENIED_ACCESS = "denied access" - MESSAGE_FAILED_VERIFY_EMAIL = "failed verify email" - - // Success - MESSAGE_SUCCESS_REGISTER_TENANT = "success create tenant" - MESSAGE_SUCCESS_GET_LIST_TENANT = "success get list tenant" - MESSAGE_SUCCESS_GET_TENANT = "success get tenant" - MESSAGE_SUCCESS_LOGIN = "success login" - MESSAGE_SUCCESS_UPDATE_TENANT = "success update tenant" - MESSAGE_SUCCESS_DELETE_TENANT = "success delete tenant" - MESSAGE_SEND_VERIFICATION_EMAIL_SUCCESS = "success send verification email" - MESSAGE_SUCCESS_VERIFY_EMAIL = "success verify email" -) - -var ( - ErrCreateTenant = errors.New("failed to create tenant") - ErrGetTenantById = errors.New("failed to get tenant by id") - ErrGetTenantByEmail = errors.New("failed to get tenant by email") - ErrEmailAlreadyExists = errors.New("email already exist") - ErrUpdateTenant = errors.New("failed to update tenant") - ErrTenantNotFound = errors.New("tenant not found") - ErrEmailNotFound = errors.New("email not found") - ErrDeleteTenant = errors.New("failed to delete tenant") - ErrTokenInvalid = errors.New("token invalid") - ErrTokenExpired = errors.New("token expired") - ErrAccountAlreadyVerified = errors.New("account already verified") - ErrNameAlreadyExists = errors.New("name already exists") -) - -type ( - TenantCreateRequest struct { - Name string `json:"name" form:"name" binding:"required,min=2,max=100"` - } - - TenantResponse struct { - ID string `json:"id"` - Name string `json:"name"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - } - - TenantPaginationResponse struct { - Data []TenantResponse `json:"data"` - dto.PaginationResponse - } - - GetAllTenantRepositoryResponse struct { - Tenants []entities.Tenant `json:"tenants"` - dto.PaginationResponse - } - - TenantUpdateRequest struct { - Name string `json:"name" form:"name" binding:"omitempty,min=2,max=100"` - } - - TenantUpdateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - } -) diff --git a/modules/tenant/query/tenant_query.go b/modules/tenant/query/tenant_query.go deleted file mode 100644 index 11d833b..0000000 --- a/modules/tenant/query/tenant_query.go +++ /dev/null @@ -1,63 +0,0 @@ -package query - -import ( - "github.com/Caknoooo/go-pagination" - "gorm.io/gorm" -) - -type Tenant struct { - ID string `json:"id"` - Name string `json:"name"` -} - -type TenantFilter struct { - pagination.BaseFilter - Name string `form:"name"` // tambahkan ini - TenantID string `form:"tenant_id"` // tambahkan ini -} - -func (f *TenantFilter) ApplyFilters(query *gorm.DB) *gorm.DB { - // Apply your filters here - if f.Name != "" { - query = query.Where("name ILIKE ?", "%"+f.Name+"%") - } - if f.TenantID != "" { - query = query.Where("id = ?", f.TenantID) - } - return query -} - -func (f *TenantFilter) GetTableName() string { - return "tenants" -} - -func (f *TenantFilter) GetSearchFields() []string { - return []string{"name"} -} - -func (f *TenantFilter) GetDefaultSort() string { - return "id asc" -} - -func (f *TenantFilter) GetIncludes() []string { - return f.Includes -} - -func (f *TenantFilter) GetPagination() pagination.PaginationRequest { - return f.Pagination -} - -func (f *TenantFilter) Validate() { - var validIncludes []string - allowedIncludes := f.GetAllowedIncludes() - for _, include := range f.Includes { - if allowedIncludes[include] { - validIncludes = append(validIncludes, include) - } - } - f.Includes = validIncludes -} - -func (f *TenantFilter) GetAllowedIncludes() map[string]bool { - return map[string]bool{} -} diff --git a/modules/tenant/repository/tenant_repository.go b/modules/tenant/repository/tenant_repository.go deleted file mode 100644 index 9e1b99f..0000000 --- a/modules/tenant/repository/tenant_repository.go +++ /dev/null @@ -1,109 +0,0 @@ -package repository - -import ( - "context" - "errors" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "gorm.io/gorm" -) - -type ( - TenantRepository interface { - Create(ctx context.Context, tx *gorm.DB, tenant entities.Tenant) (entities.Tenant, error) - GetById(ctx context.Context, tx *gorm.DB, tenantId string) (entities.Tenant, error) - GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.Tenant, error) - // CheckEmail(ctx context.Context, tx *gorm.DB, email string) (entities.Tenant, bool, error) - CheckName(ctx context.Context, tx *gorm.DB, name string) (entities.Tenant, bool, error) - Update(ctx context.Context, tx *gorm.DB, tenant entities.Tenant) (entities.Tenant, error) - Delete(ctx context.Context, tx *gorm.DB, tenantId string) error - } - - tenantRepository struct { - db *gorm.DB - } -) - -func NewTenantRepository(db *gorm.DB) TenantRepository { - return &tenantRepository{ - db: db, - } -} - -func (r *tenantRepository) Create(ctx context.Context, tx *gorm.DB, tenant entities.Tenant) (entities.Tenant, error) { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Create(&tenant).Error; err != nil { - return entities.Tenant{}, err - } - - return tenant, nil -} - -func (r *tenantRepository) GetById(ctx context.Context, tx *gorm.DB, tenantId string) (entities.Tenant, error) { - if tx == nil { - tx = r.db - } - - var tenant entities.Tenant - if err := tx.WithContext(ctx).Where("id = ?", tenantId).Take(&tenant).Error; err != nil { - return entities.Tenant{}, err - } - - return tenant, nil -} - -func (r *tenantRepository) GetByName(ctx context.Context, tx *gorm.DB, name string) (entities.Tenant, error) { - if tx == nil { - tx = r.db - } - - var tenant entities.Tenant - if err := tx.WithContext(ctx).Where("name = ?", name).Take(&tenant).Error; err != nil { - return entities.Tenant{}, err - } - - return tenant, nil -} - -func (r *tenantRepository) Update(ctx context.Context, tx *gorm.DB, tenant entities.Tenant) (entities.Tenant, error) { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Updates(&tenant).Error; err != nil { - return entities.Tenant{}, err - } - - return tenant, nil -} - -func (r *tenantRepository) Delete(ctx context.Context, tx *gorm.DB, tenantId string) error { - if tx == nil { - tx = r.db - } - - if err := tx.WithContext(ctx).Delete(&entities.Tenant{}, "id = ?", tenantId).Error; err != nil { - return err - } - - return nil -} - -func (r *tenantRepository) CheckName(ctx context.Context, tx *gorm.DB, name string) (entities.Tenant, bool, error) { - if tx == nil { - tx = r.db - } - - var tenant entities.Tenant - if err := tx.WithContext(ctx).Where("name = ?", name).Take(&tenant).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return entities.Tenant{}, false, nil - } - return entities.Tenant{}, false, err - } - - return tenant, true, nil -} diff --git a/modules/tenant/routes.go b/modules/tenant/routes.go deleted file mode 100644 index 49b9545..0000000 --- a/modules/tenant/routes.go +++ /dev/null @@ -1,24 +0,0 @@ -package tenant - -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/tenant/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) { - tenantController := do.MustInvoke[controller.TenantController](injector) - jwtService := do.MustInvokeNamed[service.JWTService](injector, constants.JWTService) - - userRoutes := server.Group("/api/tenant") - { - userRoutes.POST("", tenantController.Create) - userRoutes.GET("", tenantController.GetAll) - userRoutes.GET("/:id", tenantController.GetById) - userRoutes.PUT("/:id", middlewares.Authenticate(jwtService), tenantController.Update) - userRoutes.DELETE("/:id", middlewares.Authenticate(jwtService), tenantController.Delete) - } -} diff --git a/modules/tenant/service/tenant_service.go b/modules/tenant/service/tenant_service.go deleted file mode 100644 index 12b7112..0000000 --- a/modules/tenant/service/tenant_service.go +++ /dev/null @@ -1,102 +0,0 @@ -package service - -import ( - "context" - "time" - - "github.com/Caknoooo/go-gin-clean-starter/database/entities" - "github.com/Caknoooo/go-gin-clean-starter/modules/tenant/dto" - "github.com/Caknoooo/go-gin-clean-starter/modules/tenant/repository" - "github.com/google/uuid" - "gorm.io/gorm" -) - -type TenantService interface { - Create(ctx context.Context, req dto.TenantCreateRequest) (dto.TenantResponse, error) - GetTenantById(ctx context.Context, tenantId string) (dto.TenantResponse, error) - Update(ctx context.Context, req dto.TenantUpdateRequest, tenantId string) (dto.TenantUpdateResponse, error) - Delete(ctx context.Context, tenantId string) error -} - -type tenantService struct { - tenantRepository repository.TenantRepository - db *gorm.DB -} - -func NewTenantService( - tenantRepo repository.TenantRepository, - db *gorm.DB, -) TenantService { - return &tenantService{ - tenantRepository: tenantRepo, - db: db, - } -} - -func (s *tenantService) Create(ctx context.Context, req dto.TenantCreateRequest) (dto.TenantResponse, error) { - _, exists, err := s.tenantRepository.CheckName(ctx, s.db, req.Name) - if err != nil && err != gorm.ErrRecordNotFound { - return dto.TenantResponse{}, err - } - if exists { - return dto.TenantResponse{}, dto.ErrNameAlreadyExists - } - - tenant := entities.Tenant{ - ID: uuid.New(), - Name: req.Name, - } - - createdTenant, err := s.tenantRepository.Create(ctx, s.db, tenant) - if err != nil { - return dto.TenantResponse{}, err - } - - return dto.TenantResponse{ - ID: createdTenant.ID.String(), - Name: createdTenant.Name, - CreatedAt: createdTenant.CreatedAt.Format(time.RFC3339), - UpdatedAt: createdTenant.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *tenantService) GetTenantById(ctx context.Context, tenantId string) (dto.TenantResponse, error) { - tenant, err := s.tenantRepository.GetById(ctx, s.db, tenantId) - if err != nil { - return dto.TenantResponse{}, err - } - - return dto.TenantResponse{ - ID: tenant.ID.String(), - Name: tenant.Name, - CreatedAt: tenant.CreatedAt.Format(time.RFC3339), - UpdatedAt: tenant.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *tenantService) Update(ctx context.Context, req dto.TenantUpdateRequest, tenantId string) (dto.TenantUpdateResponse, error) { - tenant, err := s.tenantRepository.GetById(ctx, s.db, tenantId) - if err != nil { - return dto.TenantUpdateResponse{}, dto.ErrTenantNotFound - } - - if req.Name != "" { - tenant.Name = req.Name - } - - updatedTenant, err := s.tenantRepository.Update(ctx, s.db, tenant) - if err != nil { - return dto.TenantUpdateResponse{}, err - } - - return dto.TenantUpdateResponse{ - ID: updatedTenant.ID.String(), - Name: updatedTenant.Name, - CreatedAt: updatedTenant.CreatedAt.Format(time.RFC3339), - UpdatedAt: updatedTenant.UpdatedAt.Format(time.RFC3339), - }, nil -} - -func (s *tenantService) Delete(ctx context.Context, tenantId string) error { - return s.tenantRepository.Delete(ctx, s.db, tenantId) -}