package handler import ( "strconv" "apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/logger" "apskel-pos-be/internal/service" "apskel-pos-be/internal/util" "apskel-pos-be/internal/validator" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type CategoryHandler struct { categoryService service.CategoryService categoryValidator validator.CategoryValidator } func NewCategoryHandler( categoryService service.CategoryService, categoryValidator validator.CategoryValidator, ) *CategoryHandler { return &CategoryHandler{ categoryService: categoryService, categoryValidator: categoryValidator, } } func (h *CategoryHandler) CreateCategory(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) var req contract.CreateCategoryRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(c.Request.Context()).WithError(err).Error("CategoryHandler::CreateCategory -> request binding failed") validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::CreateCategory") return } validationError, validationErrorCode := h.categoryValidator.ValidateCreateCategoryRequest(&req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::CreateCategory") return } categoryResponse := h.categoryService.CreateCategory(ctx, contextInfo, &req) if categoryResponse.HasErrors() { errorResp := categoryResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("CategoryHandler::CreateCategory -> Failed to create category from service") } util.HandleResponse(c.Writer, c.Request, categoryResponse, "CategoryHandler::CreateCategory") } func (h *CategoryHandler) UpdateCategory(c *gin.Context) { ctx := c.Request.Context() categoryIDStr := c.Param("id") categoryID, err := uuid.Parse(categoryIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CategoryHandler::UpdateCategory -> Invalid category ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid category ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::UpdateCategory") return } var req contract.UpdateCategoryRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("CategoryHandler::UpdateCategory -> request binding failed") validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::UpdateCategory") return } validationError, validationErrorCode := h.categoryValidator.ValidateUpdateCategoryRequest(&req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::UpdateCategory") return } categoryResponse := h.categoryService.UpdateCategory(ctx, categoryID, &req) if categoryResponse.HasErrors() { errorResp := categoryResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("CategoryHandler::UpdateCategory -> Failed to update category from service") } util.HandleResponse(c.Writer, c.Request, categoryResponse, "CategoryHandler::UpdateCategory") } func (h *CategoryHandler) DeleteCategory(c *gin.Context) { ctx := c.Request.Context() categoryIDStr := c.Param("id") categoryID, err := uuid.Parse(categoryIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CategoryHandler::DeleteCategory -> Invalid category ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid category ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::DeleteCategory") return } categoryResponse := h.categoryService.DeleteCategory(ctx, categoryID) if categoryResponse.HasErrors() { errorResp := categoryResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("CategoryHandler::DeleteCategory -> Failed to delete category from service") } util.HandleResponse(c.Writer, c.Request, categoryResponse, "CategoryHandler::DeleteCategory") } func (h *CategoryHandler) GetCategory(c *gin.Context) { ctx := c.Request.Context() categoryIDStr := c.Param("id") categoryID, err := uuid.Parse(categoryIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CategoryHandler::GetCategory -> Invalid category ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid category ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::GetCategory") return } categoryResponse := h.categoryService.GetCategoryByID(ctx, categoryID) if categoryResponse.HasErrors() { errorResp := categoryResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("CategoryHandler::GetCategory -> Failed to get category from service") } util.HandleResponse(c.Writer, c.Request, categoryResponse, "CategoryHandler::GetCategory") } func (h *CategoryHandler) ListCategories(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) req := &contract.ListCategoriesRequest{ Page: 1, Limit: 10, OrganizationID: &contextInfo.OrganizationID, } // Parse query parameters if pageStr := c.Query("page"); pageStr != "" { if page, err := strconv.Atoi(pageStr); err == nil { req.Page = page } } if limitStr := c.Query("limit"); limitStr != "" { if limit, err := strconv.Atoi(limitStr); err == nil { req.Limit = limit } } if search := c.Query("search"); search != "" { req.Search = search } if businessType := c.Query("business_type"); businessType != "" { req.BusinessType = businessType } if organizationIDStr := c.Query("organization_id"); organizationIDStr != "" { if organizationID, err := uuid.Parse(organizationIDStr); err == nil { req.OrganizationID = &organizationID } } validationError, validationErrorCode := h.categoryValidator.ValidateListCategoriesRequest(req) if validationError != nil { logger.FromContext(ctx).WithError(validationError).Error("CategoryHandler::ListCategories -> request validation failed") validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CategoryHandler::ListCategories") return } categoriesResponse := h.categoryService.ListCategories(ctx, req) if categoriesResponse.HasErrors() { errorResp := categoriesResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("CategoryHandler::ListCategories -> Failed to list categories from service") } util.HandleResponse(c.Writer, c.Request, categoriesResponse, "CategoryHandler::ListCategories") }