init
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
"apskel-pos-be/internal/util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AnalyticsHandler struct {
|
||||
analyticsService service.AnalyticsService
|
||||
transformer transformer.Transformer
|
||||
}
|
||||
|
||||
func NewAnalyticsHandler(
|
||||
analyticsService service.AnalyticsService,
|
||||
transformer transformer.Transformer,
|
||||
) *AnalyticsHandler {
|
||||
return &AnalyticsHandler{
|
||||
analyticsService: analyticsService,
|
||||
transformer: transformer,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AnalyticsHandler) GetPaymentMethodAnalytics(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.PaymentMethodAnalyticsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetPaymentMethodAnalytics", err.Error())}), "AnalyticsHandler::GetPaymentMethodAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
modelReq := transformer.PaymentMethodAnalyticsContractToModel(&req)
|
||||
|
||||
response, err := h.analyticsService.GetPaymentMethodAnalytics(ctx, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "AnalyticsHandler::GetPaymentMethodAnalytics", err.Error())}), "AnalyticsHandler::GetPaymentMethodAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.PaymentMethodAnalyticsModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "AnalyticsHandler::GetPaymentMethodAnalytics")
|
||||
}
|
||||
|
||||
// GetSalesAnalytics handles the request to get sales analytics
|
||||
func (h *AnalyticsHandler) GetSalesAnalytics(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.SalesAnalyticsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetSalesAnalytics", err.Error())}), "AnalyticsHandler::GetSalesAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
modelReq := transformer.SalesAnalyticsContractToModel(&req)
|
||||
|
||||
// Call service
|
||||
response, err := h.analyticsService.GetSalesAnalytics(ctx, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "AnalyticsHandler::GetSalesAnalytics", err.Error())}), "AnalyticsHandler::GetSalesAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.SalesAnalyticsModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "AnalyticsHandler::GetSalesAnalytics")
|
||||
}
|
||||
|
||||
// GetProductAnalytics handles the request to get product analytics
|
||||
func (h *AnalyticsHandler) GetProductAnalytics(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.ProductAnalyticsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetProductAnalytics", err.Error())}), "AnalyticsHandler::GetProductAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
// Transform contract to model
|
||||
modelReq := transformer.ProductAnalyticsContractToModel(&req)
|
||||
|
||||
// Call service
|
||||
response, err := h.analyticsService.GetProductAnalytics(ctx, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "AnalyticsHandler::GetProductAnalytics", err.Error())}), "AnalyticsHandler::GetProductAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.ProductAnalyticsModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "AnalyticsHandler::GetProductAnalytics")
|
||||
}
|
||||
|
||||
// GetDashboardAnalytics handles the request to get dashboard analytics
|
||||
func (h *AnalyticsHandler) GetDashboardAnalytics(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.DashboardAnalyticsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetDashboardAnalytics", err.Error())}), "AnalyticsHandler::GetDashboardAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
modelReq := transformer.DashboardAnalyticsContractToModel(&req)
|
||||
|
||||
response, err := h.analyticsService.GetDashboardAnalytics(ctx, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "AnalyticsHandler::GetDashboardAnalytics", err.Error())}), "AnalyticsHandler::GetDashboardAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.DashboardAnalyticsModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "AnalyticsHandler::GetDashboardAnalytics")
|
||||
}
|
||||
|
||||
func (h *AnalyticsHandler) GetProfitLossAnalytics(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.ProfitLossAnalyticsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetProfitLossAnalytics", err.Error())}), "AnalyticsHandler::GetProfitLossAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
modelReq, err := transformer.ProfitLossAnalyticsContractToModel(&req)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "AnalyticsHandler::GetProfitLossAnalytics", err.Error())}), "AnalyticsHandler::GetProfitLossAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Call service
|
||||
response, err := h.analyticsService.GetProfitLossAnalytics(ctx, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "AnalyticsHandler::GetProfitLossAnalytics", err.Error())}), "AnalyticsHandler::GetProfitLossAnalytics")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.ProfitLossAnalyticsModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "AnalyticsHandler::GetProfitLossAnalytics")
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/logger"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
authService service.AuthService
|
||||
}
|
||||
|
||||
func NewAuthHandler(authService service.AuthService) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Login(c *gin.Context) {
|
||||
var req contract.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Login -> request binding failed")
|
||||
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(req.Email) == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Login -> email is required")
|
||||
h.sendValidationErrorResponse(c, "Email is required", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(req.Password) == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Login -> password is required")
|
||||
h.sendValidationErrorResponse(c, "Password is required", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
loginResponse, err := h.authService.Login(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Login -> Failed to login")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::Login -> Successfully logged in user = %s", loginResponse.User.Email)
|
||||
c.JSON(http.StatusOK, loginResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::Logout -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.authService.Logout(c.Request.Context(), token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::Logout -> Failed to logout")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Info("AuthHandler::Logout -> Successfully logged out")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("Successfully logged out", nil))
|
||||
}
|
||||
|
||||
func (h *AuthHandler) RefreshToken(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::RefreshToken -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
loginResponse, err := h.authService.RefreshToken(c.Request.Context(), token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::RefreshToken -> Failed to refresh token")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::RefreshToken -> Successfully refreshed token for user = %s", loginResponse.User.Email)
|
||||
c.JSON(http.StatusOK, loginResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ValidateToken(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::ValidateToken -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.authService.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::ValidateToken -> Failed to validate token")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::ValidateToken -> Successfully validated token for user = %s", userResponse.Email)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) GetProfile(c *gin.Context) {
|
||||
token := h.extractTokenFromHeader(c)
|
||||
if token == "" {
|
||||
logger.FromContext(c.Request.Context()).Error("AuthHandler::GetProfile -> token is required")
|
||||
h.sendErrorResponse(c, "Token is required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.authService.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("AuthHandler::GetProfile -> Failed to get profile")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("AuthHandler::GetProfile -> Successfully retrieved profile for user = %s", userResponse.Email)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
func (h *AuthHandler) extractTokenFromHeader(c *gin.Context) string {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Expected format: "Bearer <token>"
|
||||
parts := strings.Split(authHeader, " ")
|
||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||
return ""
|
||||
}
|
||||
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func (h *AuthHandler) sendErrorResponse(c *gin.Context, message string, statusCode int) {
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: "error",
|
||||
Message: message,
|
||||
Code: statusCode,
|
||||
}
|
||||
c.JSON(statusCode, errorResponse)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) sendValidationErrorResponse(c *gin.Context, message string, errorCode string) {
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: "validation_error",
|
||||
Message: message,
|
||||
Code: http.StatusBadRequest,
|
||||
Details: map[string]interface{}{
|
||||
"error_code": errorCode,
|
||||
"entity": constants.AuthHandlerEntity,
|
||||
},
|
||||
}
|
||||
c.JSON(http.StatusBadRequest, errorResponse)
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
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()
|
||||
|
||||
req := &contract.ListCategoriesRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CommonMiddleware struct{}
|
||||
|
||||
func NewCommonMiddleware() *CommonMiddleware {
|
||||
return &CommonMiddleware{}
|
||||
}
|
||||
|
||||
func (m *CommonMiddleware) CORS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
|
||||
if r.Method == "OPTIONS" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *CommonMiddleware) ContentType(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *CommonMiddleware) Logging(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
_ = time.Since(start)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *CommonMiddleware) Recovery(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
}()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"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"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CustomerHandler struct {
|
||||
customerService service.CustomerService
|
||||
customerValidator validator.CustomerValidator
|
||||
}
|
||||
|
||||
func NewCustomerHandler(
|
||||
customerService service.CustomerService,
|
||||
customerValidator validator.CustomerValidator,
|
||||
) *CustomerHandler {
|
||||
return &CustomerHandler{
|
||||
customerService: customerService,
|
||||
customerValidator: customerValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) CreateCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateCustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("CustomerHandler::CreateCustomer -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::CreateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.customerValidator.ValidateCreateCustomerRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(validationError).Error("CustomerHandler::CreateCustomer -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::CreateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customerResponse, err := h.customerService.CreateCustomer(c.Request.Context(), &req, organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("CustomerHandler::CreateCustomer -> Failed to create customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::CreateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c.Request.Context()).Infof("CustomerHandler::CreateCustomer -> Successfully created customer = %+v", customerResponse)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customerResponse), "CustomerHandler::CreateCustomer")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) GetCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
customerID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::GetCustomer -> Invalid customer ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid customer ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::GetCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customerResponse, err := h.customerService.GetCustomer(c.Request.Context(), customerID, organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::GetCustomer -> Failed to get customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::GetCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customerResponse), "CustomerHandler::GetCustomer")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) ListCustomers(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
req := &contract.ListCustomersRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
req.Search = c.Query("search")
|
||||
req.SortBy = c.Query("sort_by")
|
||||
req.SortOrder = c.Query("sort_order")
|
||||
|
||||
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||
req.IsActive = &isActive
|
||||
}
|
||||
}
|
||||
|
||||
if isDefaultStr := c.Query("is_default"); isDefaultStr != "" {
|
||||
if isDefault, err := strconv.ParseBool(isDefaultStr); err == nil {
|
||||
req.IsDefault = &isDefault
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.customerValidator.ValidateListCustomersRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("CustomerHandler::ListCustomers -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::ListCustomers")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customersResponse, err := h.customerService.ListCustomers(c.Request.Context(), req, organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::ListCustomers -> Failed to list customers from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::ListCustomers")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customersResponse), "CustomerHandler::ListCustomers")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) UpdateCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
customerID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::UpdateCustomer -> Invalid customer ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid customer ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::UpdateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateCustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("CustomerHandler::UpdateCustomer -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::UpdateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.customerValidator.ValidateUpdateCustomerRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(validationError).Error("CustomerHandler::UpdateCustomer -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::UpdateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customerResponse, err := h.customerService.UpdateCustomer(c.Request.Context(), customerID, organizationID, &req)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::UpdateCustomer -> Failed to update customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::UpdateCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customerResponse), "CustomerHandler::UpdateCustomer")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) DeleteCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
customerID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::DeleteCustomer -> Invalid customer ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid customer ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::DeleteCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
err = h.customerService.DeleteCustomer(c.Request.Context(), customerID, organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::DeleteCustomer -> Failed to delete customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::DeleteCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(gin.H{"message": "Customer deleted successfully"}), "CustomerHandler::DeleteCustomer")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) SetDefaultCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.SetDefaultCustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("CustomerHandler::SetDefaultCustomer -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::SetDefaultCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.customerValidator.ValidateSetDefaultCustomerRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(validationError).Error("CustomerHandler::SetDefaultCustomer -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "CustomerHandler::SetDefaultCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customerResponse, err := h.customerService.SetDefaultCustomer(c.Request.Context(), req.CustomerID, organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::SetDefaultCustomer -> Failed to set default customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::SetDefaultCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customerResponse), "CustomerHandler::SetDefaultCustomer")
|
||||
}
|
||||
|
||||
func (h *CustomerHandler) GetDefaultCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
customerResponse, err := h.customerService.GetDefaultCustomer(c.Request.Context(), organizationID)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("CustomerHandler::GetDefaultCustomer -> Failed to get default customer from service")
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerServiceEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{errorResp}), "CustomerHandler::GetDefaultCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(customerResponse), "CustomerHandler::GetDefaultCustomer")
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
"apskel-pos-be/internal/validator"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type FileHandler struct {
|
||||
fileService service.FileService
|
||||
validator validator.FileValidator
|
||||
transformer transformer.Transformer
|
||||
}
|
||||
|
||||
func NewFileHandler(
|
||||
fileService service.FileService,
|
||||
validator validator.FileValidator,
|
||||
transformer transformer.Transformer,
|
||||
) *FileHandler {
|
||||
return &FileHandler{
|
||||
fileService: fileService,
|
||||
validator: validator,
|
||||
transformer: transformer,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *FileHandler) UploadFile(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "File is required", err)
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UploadFileRequest
|
||||
if fileType := c.PostForm("file_type"); fileType != "" {
|
||||
req.FileType = fileType
|
||||
}
|
||||
|
||||
if isPublicStr := c.PostForm("is_public"); isPublicStr != "" {
|
||||
if isPublic, err := strconv.ParseBool(isPublicStr); err == nil {
|
||||
req.IsPublic = &isPublic
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.validator.Validate(&req); err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "Validation failed", err)
|
||||
return
|
||||
}
|
||||
|
||||
organizationID := contextInfo.OrganizationID
|
||||
userID := contextInfo.UserID
|
||||
|
||||
// Transform contract to model
|
||||
modelReq := transformer.UploadFileContractToModel(&req)
|
||||
response, err := h.fileService.UploadFile(ctx, file, modelReq, organizationID, userID)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusInternalServerError, "Failed to upload file", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.FileModelToContract(response)
|
||||
h.transformer.Success(c, http.StatusCreated, "File uploaded successfully", contractResp)
|
||||
}
|
||||
|
||||
func (h *FileHandler) GetFileByID(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "Invalid file ID", err)
|
||||
return
|
||||
}
|
||||
|
||||
response, err := h.fileService.GetFileByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusInternalServerError, "Failed to get file", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.FileModelToContract(response)
|
||||
h.transformer.Success(c, http.StatusOK, "File retrieved successfully", contractResp)
|
||||
}
|
||||
|
||||
func (h *FileHandler) UpdateFile(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "Invalid file ID", err)
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateFileRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "Invalid request body", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.validator.Validate(&req); err != nil {
|
||||
h.transformer.Error(c, http.StatusBadRequest, "Validation failed", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform contract to model
|
||||
modelReq := transformer.UpdateFileContractToModel(&req)
|
||||
response, err := h.fileService.UpdateFile(c.Request.Context(), id, modelReq)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusInternalServerError, "Failed to update file", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.FileModelToContract(response)
|
||||
h.transformer.Success(c, http.StatusOK, "File updated successfully", contractResp)
|
||||
}
|
||||
|
||||
func (h *FileHandler) GetFilesByOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
organizationID := contextInfo.OrganizationID
|
||||
|
||||
response, err := h.fileService.GetFileByOrganizationID(ctx, organizationID)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusInternalServerError, "Failed to get files by organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractFiles := make([]*contract.FileResponse, len(response))
|
||||
for i, file := range response {
|
||||
contractFiles[i] = transformer.FileModelToContract(file)
|
||||
}
|
||||
|
||||
contractResp := &contract.ListFilesResponse{
|
||||
Files: contractFiles,
|
||||
TotalCount: len(response),
|
||||
Page: 1,
|
||||
Limit: len(response),
|
||||
TotalPages: 1,
|
||||
}
|
||||
|
||||
h.transformer.Success(c, http.StatusOK, "Files retrieved successfully", contractResp)
|
||||
}
|
||||
|
||||
func (h *FileHandler) GetFilesByUser(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
userID := contextInfo.UserID
|
||||
|
||||
response, err := h.fileService.GetFileByUserID(ctx, userID)
|
||||
if err != nil {
|
||||
h.transformer.Error(c, http.StatusInternalServerError, "Failed to get files by user", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractFiles := make([]*contract.FileResponse, len(response))
|
||||
for i, file := range response {
|
||||
contractFiles[i] = transformer.FileModelToContract(file)
|
||||
}
|
||||
|
||||
contractResp := &contract.ListFilesResponse{
|
||||
Files: contractFiles,
|
||||
TotalCount: len(response),
|
||||
Page: 1,
|
||||
Limit: len(response),
|
||||
TotalPages: 1,
|
||||
}
|
||||
|
||||
h.transformer.Success(c, http.StatusOK, "Files retrieved successfully", contractResp)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/logger"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type HealthHandler struct {
|
||||
}
|
||||
|
||||
func NewHealthHandler() *HealthHandler {
|
||||
return &HealthHandler{}
|
||||
}
|
||||
|
||||
func (hh *HealthHandler) HealthCheck(c *gin.Context) {
|
||||
log := logger.NewContextLogger(c, "healthCheck")
|
||||
log.Info("Health Check success")
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": "Healthy!!",
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
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 InventoryHandler struct {
|
||||
inventoryService service.InventoryService
|
||||
inventoryValidator validator.InventoryValidator
|
||||
}
|
||||
|
||||
func NewInventoryHandler(
|
||||
inventoryService service.InventoryService,
|
||||
inventoryValidator validator.InventoryValidator,
|
||||
) *InventoryHandler {
|
||||
return &InventoryHandler{
|
||||
inventoryService: inventoryService,
|
||||
inventoryValidator: inventoryValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) CreateInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateInventoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("InventoryHandler::CreateInventory -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::CreateInventory")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.inventoryValidator.ValidateCreateInventoryRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::CreateInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.CreateInventory(ctx, contextInfo, &req)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::CreateInventory -> Failed to create inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::CreateInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) UpdateInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
inventoryIDStr := c.Param("id")
|
||||
inventoryID, err := uuid.Parse(inventoryIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::UpdateInventory -> Invalid inventory ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid inventory ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::UpdateInventory")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateInventoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::UpdateInventory -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::UpdateInventory")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.inventoryValidator.ValidateUpdateInventoryRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::UpdateInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.UpdateInventory(ctx, inventoryID, &req)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::UpdateInventory -> Failed to update inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::UpdateInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) DeleteInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
inventoryIDStr := c.Param("id")
|
||||
inventoryID, err := uuid.Parse(inventoryIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::DeleteInventory -> Invalid inventory ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid inventory ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::DeleteInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.DeleteInventory(ctx, inventoryID)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::DeleteInventory -> Failed to delete inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::DeleteInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) GetInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
inventoryIDStr := c.Param("id")
|
||||
inventoryID, err := uuid.Parse(inventoryIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::GetInventory -> Invalid inventory ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid inventory ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::GetInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.GetInventoryByID(ctx, inventoryID)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::GetInventory -> Failed to get inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::GetInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) ListInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
req := &contract.ListInventoryRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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 outletIDStr := c.Query("outlet_id"); outletIDStr != "" {
|
||||
if outletID, err := uuid.Parse(outletIDStr); err == nil {
|
||||
req.OutletID = &outletID
|
||||
}
|
||||
}
|
||||
|
||||
if productIDStr := c.Query("product_id"); productIDStr != "" {
|
||||
if productID, err := uuid.Parse(productIDStr); err == nil {
|
||||
req.ProductID = &productID
|
||||
}
|
||||
}
|
||||
|
||||
if categoryIDStr := c.Query("category_id"); categoryIDStr != "" {
|
||||
if categoryID, err := uuid.Parse(categoryIDStr); err == nil {
|
||||
req.CategoryID = &categoryID
|
||||
}
|
||||
}
|
||||
|
||||
if lowStockStr := c.Query("low_stock_only"); lowStockStr != "" {
|
||||
if lowStock, err := strconv.ParseBool(lowStockStr); err == nil {
|
||||
req.LowStockOnly = &lowStock
|
||||
}
|
||||
}
|
||||
|
||||
if zeroStockStr := c.Query("zero_stock_only"); zeroStockStr != "" {
|
||||
if zeroStock, err := strconv.ParseBool(zeroStockStr); err == nil {
|
||||
req.ZeroStockOnly = &zeroStock
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.inventoryValidator.ValidateListInventoryRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("InventoryHandler::ListInventory -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::ListInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.ListInventory(ctx, req)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::ListInventory -> Failed to list inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::ListInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) AdjustInventory(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
var req contract.AdjustInventoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::AdjustInventory -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::AdjustInventory")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.inventoryValidator.ValidateAdjustInventoryRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::AdjustInventory")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.AdjustInventory(ctx, &req)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::AdjustInventory -> Failed to adjust inventory from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::AdjustInventory")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) GetLowStockItems(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
outletIDStr := c.Param("outlet_id")
|
||||
outletID, err := uuid.Parse(outletIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::GetLowStockItems -> Invalid outlet ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid outlet ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::GetLowStockItems")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.GetLowStockItems(ctx, outletID)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::GetLowStockItems -> Failed to get low stock items from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::GetLowStockItems")
|
||||
}
|
||||
|
||||
func (h *InventoryHandler) GetZeroStockItems(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
outletIDStr := c.Param("outlet_id")
|
||||
outletID, err := uuid.Parse(outletIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("InventoryHandler::GetZeroStockItems -> Invalid outlet ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid outlet ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "InventoryHandler::GetZeroStockItems")
|
||||
return
|
||||
}
|
||||
|
||||
inventoryResponse := h.inventoryService.GetZeroStockItems(ctx, outletID)
|
||||
if inventoryResponse.HasErrors() {
|
||||
errorResp := inventoryResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("InventoryHandler::GetZeroStockItems -> Failed to get zero stock items from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, inventoryResponse, "InventoryHandler::GetZeroStockItems")
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
"apskel-pos-be/internal/util"
|
||||
"apskel-pos-be/internal/validator"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OrderHandler struct {
|
||||
orderService service.OrderService
|
||||
validator validator.OrderValidator
|
||||
transformer transformer.Transformer
|
||||
}
|
||||
|
||||
func NewOrderHandler(
|
||||
orderService service.OrderService,
|
||||
validator validator.OrderValidator,
|
||||
transformer transformer.Transformer,
|
||||
) *OrderHandler {
|
||||
return &OrderHandler{
|
||||
orderService: orderService,
|
||||
validator: validator,
|
||||
transformer: transformer,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *OrderHandler) CreateOrder(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::CreateOrder", err.Error())}), "OrderHandler::CreateOrder")
|
||||
return
|
||||
}
|
||||
|
||||
req.UserID = contextInfo.UserID
|
||||
modelReq := transformer.CreateOrderContractToModel(&req)
|
||||
response, err := h.orderService.CreateOrder(ctx, modelReq, contextInfo.OrganizationID)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::CreateOrder", err.Error())}), "OrderHandler::CreateOrder")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.OrderModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::CreateOrder")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) GetOrderByID(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::GetOrderByID", err.Error())}), "OrderHandler::GetOrderByID")
|
||||
return
|
||||
}
|
||||
|
||||
response, err := h.orderService.GetOrderByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::GetOrderByID", err.Error())}), "OrderHandler::GetOrderByID")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.OrderModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::GetOrderByID")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) UpdateOrder(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::UpdateOrder", err.Error())}), "OrderHandler::UpdateOrder")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::UpdateOrder", err.Error())}), "OrderHandler::UpdateOrder")
|
||||
return
|
||||
}
|
||||
|
||||
modelReq := transformer.UpdateOrderContractToModel(&req)
|
||||
response, err := h.orderService.UpdateOrder(c.Request.Context(), id, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::UpdateOrder", err.Error())}), "OrderHandler::UpdateOrder")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.OrderModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::UpdateOrder")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) AddToOrder(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::AddToOrder", err.Error())}), "OrderHandler::AddToOrder")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.AddToOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::AddToOrder", err.Error())}), "OrderHandler::AddToOrder")
|
||||
return
|
||||
}
|
||||
|
||||
modelReq := transformer.AddToOrderContractToModel(&req)
|
||||
response, err := h.orderService.AddToOrder(c.Request.Context(), id, modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::AddToOrder", err.Error())}), "OrderHandler::AddToOrder")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.AddToOrderModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::AddToOrder")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) ListOrders(c *gin.Context) {
|
||||
var query contract.ListOrdersQuery
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_query_parameters", "OrderHandler::ListOrders", err.Error())}), "OrderHandler::ListOrders")
|
||||
return
|
||||
}
|
||||
|
||||
modelReq := transformer.ListOrdersQueryToModel(&query)
|
||||
if err := h.validator.Validate(modelReq); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::ListOrders", err.Error())}), "OrderHandler::ListOrders")
|
||||
return
|
||||
}
|
||||
|
||||
response, err := h.orderService.ListOrders(c.Request.Context(), modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::ListOrders", err.Error())}), "OrderHandler::ListOrders")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.ListOrdersModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::ListOrders")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) VoidOrder(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.VoidOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::VoidOrder", err.Error())}), "OrderHandler::VoidOrder")
|
||||
return
|
||||
}
|
||||
|
||||
userID := contextInfo.UserID
|
||||
if err := h.validator.Validate(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::VoidOrder", err.Error())}), "OrderHandler::VoidOrder")
|
||||
return
|
||||
}
|
||||
|
||||
modelReq := transformer.VoidOrderContractToModel(&req)
|
||||
if err := h.orderService.VoidOrder(ctx, modelReq, userID); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::VoidOrder", err.Error())}), "OrderHandler::VoidOrder")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(map[string]string{"message": "Order voided successfully"}), "OrderHandler::VoidOrder")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) RefundOrder(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
idStr := c.Param("id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::RefundOrder", err.Error())}), "OrderHandler::RefundOrder")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.RefundOrderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::RefundOrder", err.Error())}), "OrderHandler::RefundOrder")
|
||||
return
|
||||
}
|
||||
|
||||
userID := contextInfo.UserID
|
||||
|
||||
modelReq := transformer.RefundOrderContractToModel(&req)
|
||||
if err := h.validator.Validate(modelReq); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::RefundOrder", err.Error())}), "OrderHandler::RefundOrder")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.orderService.RefundOrder(ctx, id, modelReq, userID); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::RefundOrder", err.Error())}), "OrderHandler::RefundOrder")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(nil), "OrderHandler::RefundOrder")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) CreatePayment(c *gin.Context) {
|
||||
var req contract.CreatePaymentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::CreatePayment", err.Error())}), "OrderHandler::CreatePayment")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.validator.Validate(req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::CreatePayment", err.Error())}), "OrderHandler::CreatePayment")
|
||||
return
|
||||
}
|
||||
|
||||
modelReq := transformer.CreatePaymentContractToModel(&req)
|
||||
|
||||
response, err := h.orderService.CreatePayment(c.Request.Context(), modelReq)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::CreatePayment", err.Error())}), "OrderHandler::CreatePayment")
|
||||
return
|
||||
}
|
||||
|
||||
contractResp := transformer.PaymentModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::CreatePayment")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) RefundPayment(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
idStr := c.Param("id")
|
||||
paymentID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::RefundPayment", err.Error())}), "OrderHandler::RefundPayment")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.RefundPaymentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::RefundPayment", err.Error())}), "OrderHandler::RefundPayment")
|
||||
return
|
||||
}
|
||||
|
||||
userID := contextInfo.UserID
|
||||
if userID == uuid.Nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("unauthorized", "OrderHandler::RefundPayment", "Invalid User ID in context")}), "OrderHandler::RefundPayment")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.validator.Validate(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::RefundPayment", err.Error())}), "OrderHandler::RefundPayment")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.orderService.RefundPayment(ctx, paymentID, req.RefundAmount, req.Reason, userID); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::RefundPayment", err.Error())}), "OrderHandler::RefundPayment")
|
||||
return
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(nil), "OrderHandler::RefundPayment")
|
||||
}
|
||||
|
||||
func (h *OrderHandler) SetOrderCustomer(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
// Parse order ID from URL parameter
|
||||
orderIDStr := c.Param("id")
|
||||
orderID, err := uuid.Parse(orderIDStr)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_id", "OrderHandler::SetOrderCustomer", "Invalid order ID")}), "OrderHandler::SetOrderCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
// Parse request body
|
||||
var req contract.SetOrderCustomerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("invalid_request", "OrderHandler::SetOrderCustomer", err.Error())}), "OrderHandler::SetOrderCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform contract to model
|
||||
modelReq := transformer.SetOrderCustomerContractToModel(&req)
|
||||
|
||||
// Call service
|
||||
response, err := h.orderService.SetOrderCustomer(ctx, orderID, modelReq, contextInfo.OrganizationID)
|
||||
if err != nil {
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::SetOrderCustomer", err.Error())}), "OrderHandler::SetOrderCustomer")
|
||||
return
|
||||
}
|
||||
|
||||
// Transform model to contract
|
||||
contractResp := transformer.SetOrderCustomerModelToContract(response)
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "OrderHandler::SetOrderCustomer")
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"apskel-pos-be/internal/util"
|
||||
"strconv"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/logger"
|
||||
"apskel-pos-be/internal/service"
|
||||
"apskel-pos-be/internal/validator"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OrganizationHandler struct {
|
||||
organizationService service.OrganizationService
|
||||
organizationValidator validator.OrganizationValidator
|
||||
}
|
||||
|
||||
func NewOrganizationHandler(
|
||||
organizationService service.OrganizationService,
|
||||
organizationValidator validator.OrganizationValidator,
|
||||
) *OrganizationHandler {
|
||||
return &OrganizationHandler{
|
||||
organizationService: organizationService,
|
||||
organizationValidator: organizationValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *OrganizationHandler) CreateOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateOrganizationRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("OrganizationHandler::CreateOrganization -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::CreateOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.organizationValidator.ValidateCreateOrganizationRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::CreateOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
organizationResponse := h.organizationService.CreateOrganization(ctx, contextInfo, &req)
|
||||
if organizationResponse.HasErrors() {
|
||||
errorResp := organizationResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OrganizationHandler::CreateOrganization -> Failed to create organization from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, organizationResponse, "OrganizationHandler::CreateOrganization")
|
||||
}
|
||||
|
||||
func (h *OrganizationHandler) UpdateOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
organizationIDStr := c.Param("id")
|
||||
organizationID, err := uuid.Parse(organizationIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OrganizationHandler::UpdateOrganization -> Invalid organization ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid organization ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::UpdateOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateOrganizationRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OrganizationHandler::UpdateOrganization -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::UpdateOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.organizationValidator.ValidateUpdateOrganizationRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::UpdateOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
organizationResponse := h.organizationService.UpdateOrganization(ctx, organizationID, &req)
|
||||
if organizationResponse.HasErrors() {
|
||||
errorResp := organizationResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OrganizationHandler::UpdateOrganization -> Failed to update organization from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, organizationResponse, "OrganizationHandler::UpdateOrganization")
|
||||
}
|
||||
|
||||
func (h *OrganizationHandler) DeleteOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
organizationIDStr := c.Param("id")
|
||||
organizationID, err := uuid.Parse(organizationIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OrganizationHandler::DeleteOrganization -> Invalid organization ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid organization ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::DeleteOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
organizationResponse := h.organizationService.DeleteOrganization(ctx, organizationID)
|
||||
if organizationResponse.HasErrors() {
|
||||
errorResp := organizationResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OrganizationHandler::DeleteOrganization -> Failed to delete organization from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, organizationResponse, "OrganizationHandler::DeleteOrganization")
|
||||
}
|
||||
|
||||
func (h *OrganizationHandler) GetOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
organizationIDStr := c.Param("id")
|
||||
organizationID, err := uuid.Parse(organizationIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OrganizationHandler::GetOrganization -> Invalid organization ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid organization ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::GetOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
organizationResponse := h.organizationService.GetOrganizationByID(ctx, organizationID)
|
||||
if organizationResponse.HasErrors() {
|
||||
errorResp := organizationResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OrganizationHandler::GetOrganization -> Failed to get organization from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, organizationResponse, "OrganizationHandler::GetOrganization")
|
||||
}
|
||||
|
||||
func (h *OrganizationHandler) ListOrganizations(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
req := &contract.ListOrganizationsRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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 planType := c.Query("plan_type"); planType != "" {
|
||||
req.PlanType = planType
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.organizationValidator.ValidateListOrganizationsRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("OrganizationHandler::ListOrganizations -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OrganizationHandler::ListOrganizations")
|
||||
return
|
||||
}
|
||||
|
||||
organizationsResponse := h.organizationService.ListOrganizations(ctx, req)
|
||||
if organizationsResponse.HasErrors() {
|
||||
errorResp := organizationsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OrganizationHandler::ListOrganizations -> Failed to list organizations from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, organizationsResponse, "OrganizationHandler::ListOrganizations")
|
||||
}
|
||||
|
||||
// Old error response methods removed - now using util.HandleResponse pattern
|
||||
@@ -0,0 +1,144 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"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"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OutletHandler struct {
|
||||
outletService service.OutletService
|
||||
outletValidator validator.OutletValidator
|
||||
}
|
||||
|
||||
func NewOutletHandler(outletService service.OutletService, outletValidator validator.OutletValidator) *OutletHandler {
|
||||
return &OutletHandler{
|
||||
outletService: outletService,
|
||||
outletValidator: outletValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *OutletHandler) ListOutlets(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
req := &contract.ListOutletsRequest{
|
||||
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 isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||
req.IsActive = &isActive
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.outletValidator.ValidateListOutletsRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("OutletHandler::ListOutlets -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OutletHandler::ListOutlets")
|
||||
return
|
||||
}
|
||||
|
||||
outletsResponse := h.outletService.ListOutlets(ctx, req)
|
||||
if outletsResponse.HasErrors() {
|
||||
errorResp := outletsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OutletHandler::ListOutlets -> Failed to list outlets from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, outletsResponse, "OutletHandler::ListOutlets")
|
||||
}
|
||||
|
||||
func (h *OutletHandler) GetOutlet(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
outletIDStr := c.Param("id")
|
||||
outletID, err := uuid.Parse(outletIDStr)
|
||||
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OutletHandler::GetOutlet -> Invalid outlet ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid outlet ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OutletHandler::GetOutlet")
|
||||
return
|
||||
}
|
||||
|
||||
outletResponse := h.outletService.GetOutletByID(ctx, contextInfo.OrganizationID, outletID)
|
||||
if outletResponse.HasErrors() {
|
||||
errorResp := outletResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OutletHandler::GetOutlet -> Failed to get outlet from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, outletResponse, "OutletHandler::GetOutlet")
|
||||
}
|
||||
|
||||
func (h *OutletHandler) UpdateOutlet(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
outletIDStr := c.Param("id")
|
||||
outletID, err := uuid.Parse(outletIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OutletHandler::UpdateOutlet -> Invalid outlet ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid outlet ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OutletHandler::UpdateOutlet")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateOutletRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("OutletHandler::UpdateOutlet -> Failed to bind JSON")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OutletHandler::UpdateOutlet")
|
||||
return
|
||||
}
|
||||
|
||||
req.OrganizationID = contextInfo.OrganizationID
|
||||
|
||||
validationError, validationErrorCode := h.outletValidator.ValidateUpdateOutletRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("OutletHandler::UpdateOutlet -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "OutletHandler::UpdateOutlet")
|
||||
return
|
||||
}
|
||||
|
||||
outletResponse := h.outletService.UpdateOutlet(ctx, outletID, &req)
|
||||
if outletResponse.HasErrors() {
|
||||
errorResp := outletResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("OutletHandler::UpdateOutlet -> Failed to update outlet from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, outletResponse, "OutletHandler::UpdateOutlet")
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/models"
|
||||
"apskel-pos-be/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OutletSettingHandlerImpl struct {
|
||||
outletSettingService service.OutletSettingService
|
||||
}
|
||||
|
||||
func NewOutletSettingHandlerImpl(outletSettingService service.OutletSettingService) *OutletSettingHandlerImpl {
|
||||
return &OutletSettingHandlerImpl{
|
||||
outletSettingService: outletSettingService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *OutletSettingHandlerImpl) CreateSetting(c *gin.Context) {
|
||||
var req models.CreateOutletSettingRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
req.OutletID = outletID
|
||||
|
||||
setting, err := h.outletSettingService.CreateSetting(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, contract.ErrorResponse{
|
||||
Error: "Failed to create setting",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contract.SuccessResponse{
|
||||
Data: setting,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *OutletSettingHandlerImpl) UpdateSetting(c *gin.Context) {
|
||||
var req models.UpdateOutletSettingRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate outlet ID from URL
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Get key from URL
|
||||
key := c.Param("key")
|
||||
if key == "" {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Missing setting key",
|
||||
Message: "Setting key is required",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
setting, err := h.outletSettingService.UpdateSetting(c.Request.Context(), outletID, key, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, contract.ErrorResponse{
|
||||
Error: "Failed to update setting",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.SuccessResponse{
|
||||
Data: setting,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *OutletSettingHandlerImpl) GetSetting(c *gin.Context) {
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Get key from URL
|
||||
key := c.Param("key")
|
||||
if key == "" {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Missing setting key",
|
||||
Message: "Setting key is required",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
setting, err := h.outletSettingService.GetSetting(c.Request.Context(), outletID, key)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, contract.ErrorResponse{
|
||||
Error: "Setting not found",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.SuccessResponse{
|
||||
Data: setting,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *OutletSettingHandlerImpl) GetPrinterSettings(c *gin.Context) {
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
settings, err := h.outletSettingService.GetPrinterSettings(c.Request.Context(), outletID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, contract.ErrorResponse{
|
||||
Error: "Failed to get printer settings",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.SuccessResponse{
|
||||
Data: settings,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *OutletSettingHandlerImpl) UpdatePrinterSettings(c *gin.Context) {
|
||||
var req models.UpdateOutletPrinterSettingsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid request body",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
settings, err := h.outletSettingService.UpdatePrinterSettings(c.Request.Context(), outletID, &req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, contract.ErrorResponse{
|
||||
Error: "Failed to update printer settings",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.SuccessResponse{
|
||||
Data: settings,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteSetting deletes a specific outlet setting
|
||||
func (h *OutletSettingHandlerImpl) DeleteSetting(c *gin.Context) {
|
||||
// Validate outlet ID from URL
|
||||
outletID, err := uuid.Parse(c.Param("outlet_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Invalid outlet ID",
|
||||
Message: "Outlet ID must be a valid UUID",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Get key from URL
|
||||
key := c.Param("key")
|
||||
if key == "" {
|
||||
c.JSON(http.StatusBadRequest, contract.ErrorResponse{
|
||||
Error: "Missing setting key",
|
||||
Message: "Setting key is required",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = h.outletSettingService.DeleteSetting(c.Request.Context(), outletID, key)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, contract.ErrorResponse{
|
||||
Error: "Failed to delete setting",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contract.SuccessResponse{
|
||||
Message: "Setting deleted successfully",
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
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 PaymentMethodHandler struct {
|
||||
paymentMethodService service.PaymentMethodService
|
||||
paymentMethodValidator validator.PaymentMethodValidator
|
||||
}
|
||||
|
||||
func NewPaymentMethodHandler(
|
||||
paymentMethodService service.PaymentMethodService,
|
||||
paymentMethodValidator validator.PaymentMethodValidator,
|
||||
) *PaymentMethodHandler {
|
||||
return &PaymentMethodHandler{
|
||||
paymentMethodService: paymentMethodService,
|
||||
paymentMethodValidator: paymentMethodValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) CreatePaymentMethod(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreatePaymentMethodRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("PaymentMethodHandler::CreatePaymentMethod -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::CreatePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.paymentMethodValidator.ValidateCreatePaymentMethodRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::CreatePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodResponse := h.paymentMethodService.CreatePaymentMethod(ctx, contextInfo, &req)
|
||||
if paymentMethodResponse.HasErrors() {
|
||||
errorResp := paymentMethodResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::CreatePaymentMethod -> Failed to create payment method from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodResponse, "PaymentMethodHandler::CreatePaymentMethod")
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) GetPaymentMethod(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
paymentMethodIDStr := c.Param("id")
|
||||
paymentMethodID, err := uuid.Parse(paymentMethodIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("PaymentMethodHandler::GetPaymentMethod -> Invalid payment method ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid payment method ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::GetPaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodResponse := h.paymentMethodService.GetPaymentMethodByID(ctx, paymentMethodID)
|
||||
if paymentMethodResponse.HasErrors() {
|
||||
errorResp := paymentMethodResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::GetPaymentMethod -> Failed to get payment method from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodResponse, "PaymentMethodHandler::GetPaymentMethod")
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) ListPaymentMethods(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
req := &contract.ListPaymentMethodsRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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 paymentMethodType := c.Query("type"); paymentMethodType != "" {
|
||||
req.Type = &paymentMethodType
|
||||
}
|
||||
|
||||
if organizationIDStr := c.Query("organization_id"); organizationIDStr != "" {
|
||||
if organizationID, err := uuid.Parse(organizationIDStr); err == nil {
|
||||
req.OrganizationID = &organizationID
|
||||
}
|
||||
}
|
||||
|
||||
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||
req.IsActive = &isActive
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.paymentMethodValidator.ValidateListPaymentMethodsRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("PaymentMethodHandler::ListPaymentMethods -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::ListPaymentMethods")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodsResponse := h.paymentMethodService.ListPaymentMethods(ctx, req)
|
||||
if paymentMethodsResponse.HasErrors() {
|
||||
errorResp := paymentMethodsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::ListPaymentMethods -> Failed to list payment methods from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodsResponse, "PaymentMethodHandler::ListPaymentMethods")
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) UpdatePaymentMethod(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
paymentMethodIDStr := c.Param("id")
|
||||
paymentMethodID, err := uuid.Parse(paymentMethodIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("PaymentMethodHandler::UpdatePaymentMethod -> Invalid payment method ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid payment method ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::UpdatePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdatePaymentMethodRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("PaymentMethodHandler::UpdatePaymentMethod -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::UpdatePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.paymentMethodValidator.ValidateUpdatePaymentMethodRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::UpdatePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodResponse := h.paymentMethodService.UpdatePaymentMethod(ctx, paymentMethodID, &req)
|
||||
if paymentMethodResponse.HasErrors() {
|
||||
errorResp := paymentMethodResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::UpdatePaymentMethod -> Failed to update payment method from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodResponse, "PaymentMethodHandler::UpdatePaymentMethod")
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) DeletePaymentMethod(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
paymentMethodIDStr := c.Param("id")
|
||||
paymentMethodID, err := uuid.Parse(paymentMethodIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("PaymentMethodHandler::DeletePaymentMethod -> Invalid payment method ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid payment method ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::DeletePaymentMethod")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodResponse := h.paymentMethodService.DeletePaymentMethod(ctx, paymentMethodID)
|
||||
if paymentMethodResponse.HasErrors() {
|
||||
errorResp := paymentMethodResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::DeletePaymentMethod -> Failed to delete payment method from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodResponse, "PaymentMethodHandler::DeletePaymentMethod")
|
||||
}
|
||||
|
||||
func (h *PaymentMethodHandler) GetActivePaymentMethodsByOrganization(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
organizationIDStr := c.Param("organization_id")
|
||||
organizationID, err := uuid.Parse(organizationIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("PaymentMethodHandler::GetActivePaymentMethodsByOrganization -> Invalid organization ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid organization ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PaymentMethodHandler::GetActivePaymentMethodsByOrganization")
|
||||
return
|
||||
}
|
||||
|
||||
paymentMethodsResponse := h.paymentMethodService.GetActivePaymentMethodsByOrganization(ctx, organizationID)
|
||||
if paymentMethodsResponse.HasErrors() {
|
||||
errorResp := paymentMethodsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("PaymentMethodHandler::GetActivePaymentMethodsByOrganization -> Failed to get active payment methods from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, paymentMethodsResponse, "PaymentMethodHandler::GetActivePaymentMethodsByOrganization")
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
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 ProductHandler struct {
|
||||
productService service.ProductService
|
||||
productValidator validator.ProductValidator
|
||||
}
|
||||
|
||||
func NewProductHandler(
|
||||
productService service.ProductService,
|
||||
productValidator validator.ProductValidator,
|
||||
) *ProductHandler {
|
||||
return &ProductHandler{
|
||||
productService: productService,
|
||||
productValidator: productValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ProductHandler) CreateProduct(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateProductRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("ProductHandler::CreateProduct -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::CreateProduct")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.productValidator.ValidateCreateProductRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::CreateProduct")
|
||||
return
|
||||
}
|
||||
|
||||
productResponse := h.productService.CreateProduct(ctx, contextInfo, &req)
|
||||
if productResponse.HasErrors() {
|
||||
errorResp := productResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductHandler::CreateProduct -> Failed to create product from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, productResponse, "ProductHandler::CreateProduct")
|
||||
}
|
||||
|
||||
func (h *ProductHandler) UpdateProduct(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
productIDStr := c.Param("id")
|
||||
productID, err := uuid.Parse(productIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductHandler::UpdateProduct -> Invalid product ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid product ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::UpdateProduct")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateProductRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductHandler::UpdateProduct -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::UpdateProduct")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.productValidator.ValidateUpdateProductRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::UpdateProduct")
|
||||
return
|
||||
}
|
||||
|
||||
productResponse := h.productService.UpdateProduct(ctx, productID, &req)
|
||||
if productResponse.HasErrors() {
|
||||
errorResp := productResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductHandler::UpdateProduct -> Failed to update product from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, productResponse, "ProductHandler::UpdateProduct")
|
||||
}
|
||||
|
||||
func (h *ProductHandler) DeleteProduct(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
productIDStr := c.Param("id")
|
||||
productID, err := uuid.Parse(productIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductHandler::DeleteProduct -> Invalid product ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid product ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::DeleteProduct")
|
||||
return
|
||||
}
|
||||
|
||||
productResponse := h.productService.DeleteProduct(ctx, productID)
|
||||
if productResponse.HasErrors() {
|
||||
errorResp := productResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductHandler::DeleteProduct -> Failed to delete product from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, productResponse, "ProductHandler::DeleteProduct")
|
||||
}
|
||||
|
||||
func (h *ProductHandler) GetProduct(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
productIDStr := c.Param("id")
|
||||
productID, err := uuid.Parse(productIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductHandler::GetProduct -> Invalid product ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid product ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::GetProduct")
|
||||
return
|
||||
}
|
||||
|
||||
productResponse := h.productService.GetProductByID(ctx, productID)
|
||||
if productResponse.HasErrors() {
|
||||
errorResp := productResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductHandler::GetProduct -> Failed to get product from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, productResponse, "ProductHandler::GetProduct")
|
||||
}
|
||||
|
||||
func (h *ProductHandler) ListProducts(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
req := &contract.ListProductsRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
if categoryIDStr := c.Query("category_id"); categoryIDStr != "" {
|
||||
if categoryID, err := uuid.Parse(categoryIDStr); err == nil {
|
||||
req.CategoryID = &categoryID
|
||||
}
|
||||
}
|
||||
|
||||
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||
req.IsActive = &isActive
|
||||
}
|
||||
}
|
||||
|
||||
if minPriceStr := c.Query("min_price"); minPriceStr != "" {
|
||||
if minPrice, err := strconv.ParseFloat(minPriceStr, 64); err == nil {
|
||||
req.MinPrice = &minPrice
|
||||
}
|
||||
}
|
||||
|
||||
if maxPriceStr := c.Query("max_price"); maxPriceStr != "" {
|
||||
if maxPrice, err := strconv.ParseFloat(maxPriceStr, 64); err == nil {
|
||||
req.MaxPrice = &maxPrice
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.productValidator.ValidateListProductsRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(ctx).WithError(validationError).Error("ProductHandler::ListProducts -> request validation failed")
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductHandler::ListProducts")
|
||||
return
|
||||
}
|
||||
|
||||
productsResponse := h.productService.ListProducts(ctx, req)
|
||||
if productsResponse.HasErrors() {
|
||||
errorResp := productsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductHandler::ListProducts -> Failed to list products from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, productsResponse, "ProductHandler::ListProducts")
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"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 ProductVariantHandler struct {
|
||||
productVariantService service.ProductVariantService
|
||||
productVariantValidator validator.ProductVariantValidator
|
||||
}
|
||||
|
||||
func NewProductVariantHandler(
|
||||
productVariantService service.ProductVariantService,
|
||||
productVariantValidator validator.ProductVariantValidator,
|
||||
) *ProductVariantHandler {
|
||||
return &ProductVariantHandler{
|
||||
productVariantService: productVariantService,
|
||||
productVariantValidator: productVariantValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ProductVariantHandler) CreateProductVariant(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
contextInfo := appcontext.FromGinContext(ctx)
|
||||
|
||||
var req contract.CreateProductVariantRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c.Request.Context()).WithError(err).Error("ProductVariantHandler::CreateProductVariant -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::CreateProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.productVariantValidator.ValidateCreateProductVariantRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::CreateProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
variantResponse := h.productVariantService.CreateProductVariant(ctx, contextInfo, &req)
|
||||
if variantResponse.HasErrors() {
|
||||
errorResp := variantResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductVariantHandler::CreateProductVariant -> Failed to create product variant from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, variantResponse, "ProductVariantHandler::CreateProductVariant")
|
||||
}
|
||||
|
||||
func (h *ProductVariantHandler) UpdateProductVariant(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
variantIDStr := c.Param("id")
|
||||
variantID, err := uuid.Parse(variantIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductVariantHandler::UpdateProductVariant -> Invalid variant ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid variant ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::UpdateProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateProductVariantRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductVariantHandler::UpdateProductVariant -> request binding failed")
|
||||
validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::UpdateProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.productVariantValidator.ValidateUpdateProductVariantRequest(&req)
|
||||
if validationError != nil {
|
||||
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::UpdateProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
variantResponse := h.productVariantService.UpdateProductVariant(ctx, variantID, &req)
|
||||
if variantResponse.HasErrors() {
|
||||
errorResp := variantResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductVariantHandler::UpdateProductVariant -> Failed to update product variant from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, variantResponse, "ProductVariantHandler::UpdateProductVariant")
|
||||
}
|
||||
|
||||
func (h *ProductVariantHandler) DeleteProductVariant(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
variantIDStr := c.Param("id")
|
||||
variantID, err := uuid.Parse(variantIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductVariantHandler::DeleteProductVariant -> Invalid variant ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid variant ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::DeleteProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
variantResponse := h.productVariantService.DeleteProductVariant(ctx, variantID)
|
||||
if variantResponse.HasErrors() {
|
||||
errorResp := variantResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductVariantHandler::DeleteProductVariant -> Failed to delete product variant from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, variantResponse, "ProductVariantHandler::DeleteProductVariant")
|
||||
}
|
||||
|
||||
func (h *ProductVariantHandler) GetProductVariant(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
variantIDStr := c.Param("id")
|
||||
variantID, err := uuid.Parse(variantIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductVariantHandler::GetProductVariant -> Invalid variant ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid variant ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::GetProductVariant")
|
||||
return
|
||||
}
|
||||
|
||||
variantResponse := h.productVariantService.GetProductVariantByID(ctx, variantID)
|
||||
if variantResponse.HasErrors() {
|
||||
errorResp := variantResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductVariantHandler::GetProductVariant -> Failed to get product variant from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, variantResponse, "ProductVariantHandler::GetProductVariant")
|
||||
}
|
||||
|
||||
func (h *ProductVariantHandler) GetProductVariantsByProduct(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
productIDStr := c.Param("product_id")
|
||||
productID, err := uuid.Parse(productIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(ctx).WithError(err).Error("ProductVariantHandler::GetProductVariantsByProduct -> Invalid product ID")
|
||||
validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid product ID")
|
||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "ProductVariantHandler::GetProductVariantsByProduct")
|
||||
return
|
||||
}
|
||||
|
||||
variantsResponse := h.productVariantService.GetProductVariantsByProductID(ctx, productID)
|
||||
if variantsResponse.HasErrors() {
|
||||
errorResp := variantsResponse.GetErrors()[0]
|
||||
logger.FromContext(ctx).WithError(errorResp).Error("ProductVariantHandler::GetProductVariantsByProduct -> Failed to get product variants from service")
|
||||
}
|
||||
|
||||
util.HandleResponse(c.Writer, c.Request, variantsResponse, "ProductVariantHandler::GetProductVariantsByProduct")
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/logger"
|
||||
"apskel-pos-be/internal/transformer"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserHandler struct {
|
||||
userService UserService
|
||||
userValidator UserValidator
|
||||
}
|
||||
|
||||
func NewUserHandler(userService UserService, userValidator UserValidator) *UserHandler {
|
||||
return &UserHandler{
|
||||
userService: userService,
|
||||
userValidator: userValidator,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *UserHandler) CreateUser(c *gin.Context) {
|
||||
var req contract.CreateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::CreateUser -> request binding failed")
|
||||
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateCreateUserRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::CreateUser -> request validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.userService.CreateUser(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::CreateUser -> Failed to create user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::CreateUser -> Successfully created user = %+v", userResponse)
|
||||
c.JSON(http.StatusCreated, userResponse)
|
||||
}
|
||||
|
||||
func (h *UserHandler) UpdateUser(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::UpdateUser -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::UpdateUser -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.UpdateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::UpdateUser -> request binding failed")
|
||||
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode = h.userValidator.ValidateUpdateUserRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::UpdateUser -> request validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.userService.UpdateUser(c.Request.Context(), userID, &req)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::UpdateUser -> Failed to update user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::UpdateUser -> Successfully updated user = %+v", userResponse)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
func (h *UserHandler) DeleteUser(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::DeleteUser -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::DeleteUser -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.userService.DeleteUser(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::DeleteUser -> Failed to delete user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Info("UserHandler::DeleteUser -> Successfully deleted user")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("User deleted successfully", nil))
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetUser(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::GetUser -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::GetUser -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
userResponse, err := h.userService.GetUserByID(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::GetUser -> Failed to get user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::GetUser -> Successfully retrieved user = %+v", userResponse)
|
||||
c.JSON(http.StatusOK, userResponse)
|
||||
}
|
||||
|
||||
func (h *UserHandler) ListUsers(c *gin.Context) {
|
||||
req := &contract.ListUsersRequest{
|
||||
Page: 1,
|
||||
Limit: 10,
|
||||
}
|
||||
|
||||
if page := c.Query("page"); page != "" {
|
||||
if p, err := strconv.Atoi(page); err == nil {
|
||||
req.Page = p
|
||||
}
|
||||
}
|
||||
|
||||
if limit := c.Query("limit"); limit != "" {
|
||||
if l, err := strconv.Atoi(limit); err == nil {
|
||||
req.Limit = l
|
||||
}
|
||||
}
|
||||
|
||||
if role := c.Query("role"); role != "" {
|
||||
req.Role = &role
|
||||
}
|
||||
|
||||
if outletIDStr := c.Query("outlet_id"); outletIDStr != "" {
|
||||
if outletID, err := uuid.Parse(outletIDStr); err == nil {
|
||||
req.OutletID = &outletID
|
||||
}
|
||||
}
|
||||
|
||||
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
|
||||
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
|
||||
req.IsActive = &isActive
|
||||
}
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateListUsersRequest(req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::ListUsers -> request validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
usersResponse, err := h.userService.ListUsers(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ListUsers -> Failed to list users from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Infof("UserHandler::ListUsers -> Successfully listed users = %+v", usersResponse)
|
||||
c.JSON(http.StatusOK, contract.BuildSuccessResponse(usersResponse))
|
||||
}
|
||||
|
||||
func (h *UserHandler) ChangePassword(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ChangePassword -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::ChangePassword -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
var req contract.ChangePasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ChangePassword -> request binding failed")
|
||||
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode = h.userValidator.ValidateChangePasswordRequest(&req)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::ChangePassword -> request validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.userService.ChangePassword(c.Request.Context(), userID, &req)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ChangePassword -> Failed to change password from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Info("UserHandler::ChangePassword -> Successfully changed password")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("Password changed successfully", nil))
|
||||
}
|
||||
|
||||
func (h *UserHandler) ActivateUser(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ActivateUser -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::ActivateUser -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.userService.ActivateUser(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::ActivateUser -> Failed to activate user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Info("UserHandler::ActivateUser -> Successfully activated user")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("User activated successfully", nil))
|
||||
}
|
||||
|
||||
func (h *UserHandler) DeactivateUser(c *gin.Context) {
|
||||
userIDStr := c.Param("id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::DeactivateUser -> Invalid user ID")
|
||||
h.sendValidationErrorResponse(c, "Invalid user ID", constants.MalformedFieldErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
validationError, validationErrorCode := h.userValidator.ValidateUserID(userID)
|
||||
if validationError != nil {
|
||||
logger.FromContext(c).WithError(validationError).Error("UserHandler::DeactivateUser -> user ID validation failed")
|
||||
h.sendValidationErrorResponse(c, validationError.Error(), validationErrorCode)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.userService.DeactivateUser(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
logger.FromContext(c).WithError(err).Error("UserHandler::DeactivateUser -> Failed to deactivate user from service")
|
||||
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
logger.FromContext(c).Info("UserHandler::DeactivateUser -> Successfully deactivated user")
|
||||
c.JSON(http.StatusOK, transformer.CreateSuccessResponse("User deactivated successfully", nil))
|
||||
}
|
||||
|
||||
func (h *UserHandler) sendErrorResponse(c *gin.Context, message string, statusCode int) {
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: message,
|
||||
Code: statusCode,
|
||||
Details: map[string]interface{}{},
|
||||
}
|
||||
c.JSON(statusCode, errorResponse)
|
||||
}
|
||||
|
||||
func (h *UserHandler) sendValidationErrorResponse(c *gin.Context, message string, errorCode string) {
|
||||
statusCode := constants.HttpErrorMap[errorCode]
|
||||
if statusCode == 0 {
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
errorResponse := &contract.ErrorResponse{
|
||||
Error: message,
|
||||
Code: statusCode,
|
||||
Details: map[string]interface{}{
|
||||
"error_code": errorCode,
|
||||
"entity": constants.UserValidatorEntity,
|
||||
},
|
||||
}
|
||||
c.JSON(statusCode, errorResponse)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/contract"
|
||||
"context"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserService interface {
|
||||
CreateUser(ctx context.Context, req *contract.CreateUserRequest) (*contract.UserResponse, error)
|
||||
UpdateUser(ctx context.Context, id uuid.UUID, req *contract.UpdateUserRequest) (*contract.UserResponse, error)
|
||||
DeleteUser(ctx context.Context, id uuid.UUID) error
|
||||
GetUserByID(ctx context.Context, id uuid.UUID) (*contract.UserResponse, error)
|
||||
GetUserByEmail(ctx context.Context, email string) (*contract.UserResponse, error)
|
||||
ListUsers(ctx context.Context, req *contract.ListUsersRequest) (*contract.ListUsersResponse, error)
|
||||
ChangePassword(ctx context.Context, userID uuid.UUID, req *contract.ChangePasswordRequest) error
|
||||
ActivateUser(ctx context.Context, userID uuid.UUID) error
|
||||
DeactivateUser(ctx context.Context, userID uuid.UUID) error
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/contract"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserValidator interface {
|
||||
ValidateCreateUserRequest(req *contract.CreateUserRequest) (error, string)
|
||||
ValidateUpdateUserRequest(req *contract.UpdateUserRequest) (error, string)
|
||||
ValidateListUsersRequest(req *contract.ListUsersRequest) (error, string)
|
||||
ValidateChangePasswordRequest(req *contract.ChangePasswordRequest) (error, string)
|
||||
ValidateUserID(userID uuid.UUID) (error, string)
|
||||
}
|
||||
Reference in New Issue
Block a user