package handler import ( "apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/util" "strconv" "time" "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 PurchaseOrderHandler struct { purchaseOrderService service.PurchaseOrderService purchaseOrderValidator validator.PurchaseOrderValidator } func NewPurchaseOrderHandler( purchaseOrderService service.PurchaseOrderService, purchaseOrderValidator validator.PurchaseOrderValidator, ) *PurchaseOrderHandler { return &PurchaseOrderHandler{ purchaseOrderService: purchaseOrderService, purchaseOrderValidator: purchaseOrderValidator, } } func (h *PurchaseOrderHandler) CreatePurchaseOrder(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) var req contract.CreatePurchaseOrderRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(c.Request.Context()).WithError(err).Error("PurchaseOrderHandler::CreatePurchaseOrder -> request binding failed") validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::CreatePurchaseOrder") return } validationError, validationErrorCode := h.purchaseOrderValidator.ValidateCreatePurchaseOrderRequest(&req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::CreatePurchaseOrder") return } poResponse := h.purchaseOrderService.CreatePurchaseOrder(ctx, contextInfo, &req) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::CreatePurchaseOrder -> Failed to create purchase order from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::CreatePurchaseOrder") } func (h *PurchaseOrderHandler) UpdatePurchaseOrder(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) poIDStr := c.Param("id") poID, err := uuid.Parse(poIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("PurchaseOrderHandler::UpdatePurchaseOrder -> Invalid purchase order ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid purchase order ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::UpdatePurchaseOrder") return } var req contract.UpdatePurchaseOrderRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("PurchaseOrderHandler::UpdatePurchaseOrder -> request binding failed") validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Invalid request body") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::UpdatePurchaseOrder") return } validationError, validationErrorCode := h.purchaseOrderValidator.ValidateUpdatePurchaseOrderRequest(&req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::UpdatePurchaseOrder") return } poResponse := h.purchaseOrderService.UpdatePurchaseOrder(ctx, contextInfo, poID, &req) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::UpdatePurchaseOrder -> Failed to update purchase order from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::UpdatePurchaseOrder") } func (h *PurchaseOrderHandler) DeletePurchaseOrder(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) poIDStr := c.Param("id") poID, err := uuid.Parse(poIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("PurchaseOrderHandler::DeletePurchaseOrder -> Invalid purchase order ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid purchase order ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::DeletePurchaseOrder") return } poResponse := h.purchaseOrderService.DeletePurchaseOrder(ctx, contextInfo, poID) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::DeletePurchaseOrder -> Failed to delete purchase order from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::DeletePurchaseOrder") } func (h *PurchaseOrderHandler) GetPurchaseOrder(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) poIDStr := c.Param("id") poID, err := uuid.Parse(poIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("PurchaseOrderHandler::GetPurchaseOrder -> Invalid purchase order ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid purchase order ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::GetPurchaseOrder") return } poResponse := h.purchaseOrderService.GetPurchaseOrderByID(ctx, contextInfo, poID) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::GetPurchaseOrder -> Failed to get purchase order from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::GetPurchaseOrder") } func (h *PurchaseOrderHandler) ListPurchaseOrders(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) req := &contract.ListPurchaseOrdersRequest{ 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 status := c.Query("status"); status != "" { req.Status = status } if vendorIDStr := c.Query("vendor_id"); vendorIDStr != "" { if vendorID, err := uuid.Parse(vendorIDStr); err == nil { req.VendorID = &vendorID } } if startDateStr := c.Query("start_date"); startDateStr != "" { if startDate, err := time.Parse("2006-01-02", startDateStr); err == nil { req.StartDate = &startDate } } if endDateStr := c.Query("end_date"); endDateStr != "" { if endDate, err := time.Parse("2006-01-02", endDateStr); err == nil { req.EndDate = &endDate } } validationError, validationErrorCode := h.purchaseOrderValidator.ValidateListPurchaseOrdersRequest(req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::ListPurchaseOrders") return } poResponse := h.purchaseOrderService.ListPurchaseOrders(ctx, contextInfo, req) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::ListPurchaseOrders -> Failed to list purchase orders from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::ListPurchaseOrders") } func (h *PurchaseOrderHandler) GetPurchaseOrdersByStatus(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) status := c.Param("status") if status == "" { validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Status parameter is required") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::GetPurchaseOrdersByStatus") return } poResponse := h.purchaseOrderService.GetPurchaseOrdersByStatus(ctx, contextInfo, status) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::GetPurchaseOrdersByStatus -> Failed to get purchase orders by status from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::GetPurchaseOrdersByStatus") } func (h *PurchaseOrderHandler) GetOverduePurchaseOrders(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) poResponse := h.purchaseOrderService.GetOverduePurchaseOrders(ctx, contextInfo) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::GetOverduePurchaseOrders -> Failed to get overdue purchase orders from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::GetOverduePurchaseOrders") } func (h *PurchaseOrderHandler) UpdatePurchaseOrderStatus(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) poIDStr := c.Param("id") poID, err := uuid.Parse(poIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("PurchaseOrderHandler::UpdatePurchaseOrderStatus -> Invalid purchase order ID") validationResponseError := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid purchase order ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::UpdatePurchaseOrderStatus") return } status := c.Param("status") if status == "" { validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "Status parameter is required") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "PurchaseOrderHandler::UpdatePurchaseOrderStatus") return } poResponse := h.purchaseOrderService.UpdatePurchaseOrderStatus(ctx, contextInfo, poID, status) if poResponse.HasErrors() { errorResp := poResponse.GetErrors()[0] logger.FromContext(ctx).WithError(errorResp).Error("PurchaseOrderHandler::UpdatePurchaseOrderStatus -> Failed to update purchase order status from service") } util.HandleResponse(c.Writer, c.Request, poResponse, "PurchaseOrderHandler::UpdatePurchaseOrderStatus") }