package customerorder import ( "encoding/json" "furtuna-be/internal/common/errors" "furtuna-be/internal/entity" "furtuna-be/internal/handlers/request" "furtuna-be/internal/handlers/response" "furtuna-be/internal/services" "net/http" "time" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" ) type Handler struct { service services.Order } func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { route := group.Group("/order") route.POST("/inquiry", jwt, h.Inquiry) route.POST("/execute", jwt, h.Execute) route.GET("/history", jwt, h.History) route.GET("/detail", jwt, h.Detail) } func NewHandler(service services.Order) *Handler { return &Handler{ service: service, } } func (h *Handler) Inquiry(c *gin.Context) { ctx := request.GetMyContext(c) var req request.CustomerOrder if err := c.ShouldBindJSON(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } validate := validator.New() if err := validate.Struct(req); err != nil { response.ErrorWrapper(c, err) return } order, err := h.service.CreateOrder(ctx, req.ToEntity(ctx.RequestedBy())) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: MapOrderToCreateOrderResponse(order), }) } func (h *Handler) Execute(c *gin.Context) { ctx := request.GetMyContext(c) var req request.Execute if err := c.ShouldBindJSON(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } validate := validator.New() if err := validate.Struct(req); err != nil { response.ErrorWrapper(c, err) return } order, err := h.service.Execute(ctx, req.ToOrderExecuteRequest(ctx.RequestedBy())) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: MapOrderToExecuteOrderResponse(order), }) } func MapOrderToCreateOrderResponse(orderResponse *entity.OrderResponse) response.CreateOrderResponse { order := orderResponse.Order orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems)) for i, item := range order.OrderItems { orderItems[i] = response.CreateOrderItemResponse{ ID: item.ID, ItemID: item.ItemID, Quantity: item.Quantity, Price: item.Price, Name: item.Product.Name, } } return response.CreateOrderResponse{ ID: order.ID, RefID: order.RefID, PartnerID: order.PartnerID, Status: order.Status, Amount: order.Amount, PaymentType: order.PaymentType, CreatedAt: order.CreatedAt, OrderItems: orderItems, Token: orderResponse.Token, } } func MapOrderToExecuteOrderResponse(orderResponse *entity.ExecuteOrderResponse) response.ExecuteOrderResponse { order := orderResponse.Order orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems)) for i, item := range order.OrderItems { orderItems[i] = response.CreateOrderItemResponse{ ID: item.ID, ItemID: item.ItemID, Quantity: item.Quantity, Price: item.Price, Name: item.Product.Name, } } return response.ExecuteOrderResponse{ ID: order.ID, RefID: order.RefID, PartnerID: order.PartnerID, Status: order.Status, Amount: order.Amount, PaymentType: order.PaymentType, CreatedAt: order.CreatedAt, OrderItems: orderItems, PaymentToken: orderResponse.PaymentToken, RedirectURL: orderResponse.RedirectURL, QRcode: orderResponse.QRCode, } } func (h *Handler) toHistoryOrderResponse(resp *entity.HistoryOrder) response.HistoryOrder { return response.HistoryOrder{ ID: resp.ID, Employee: resp.Employee, Site: resp.Site, Timestamp: resp.Timestamp.Format(time.RFC3339), BookingTime: resp.BookingTime.Format(time.RFC3339), Tickets: resp.Tickets, PaymentType: resp.PaymentType, Status: resp.Status, Amount: resp.Amount, } } func (h *Handler) toHistoryOrderList(resp []*entity.HistoryOrder, total int64, req request.OrderParamCustomer) response.HistoryOrderList { var orders []response.HistoryOrder for _, b := range resp { orders = append(orders, h.toHistoryOrderResponse(b)) } return response.HistoryOrderList{ Orders: orders, Total: total, Limit: req.Limit, Offset: req.Offset, } } func (h *Handler) History(c *gin.Context) { var req request.OrderParamCustomer if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) orders, total, err := h.service.GetAllHistoryOrders(ctx, req.ToOrderEntity(ctx)) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: h.toHistoryOrderList(orders, int64(total), req), }) } func (h *Handler) Detail(c *gin.Context) { var req request.OrderParamCustomer if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) order, err := h.service.GetByID(ctx, req.ID, req.ReferenceID) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: h.toOrderDetail(order), }) } func (h *Handler) toOrderDetail(order *entity.Order) *response.OrderDetail { if order == nil { return nil } payment := map[string]string{} paymentLink := "" if order.Payment.RequestMetadata != nil && order.Status != "EXPIRED" { json.Unmarshal(order.Payment.RequestMetadata, &payment) paymentLink = payment["payment_redirect_url"] } orderDetail := &response.OrderDetail{ ID: order.ID, QRCode: order.RefID, FullName: order.User.Name, Email: order.User.Email, PhoneNumber: order.User.PhoneNumber, TotalAmount: order.Amount, CreatedAt: order.CreatedAt, Status: order.Status, PaymentLink: paymentLink, } orderDetail.OrderItems = make([]response.OrderDetailItem, len(order.OrderItems)) for i, item := range order.OrderItems { orderDetail.OrderItems[i] = response.OrderDetailItem{ ItemType: item.ItemType, Description: "", Quantity: int(item.Quantity), UnitPrice: item.Price, TotalPrice: float64(item.Quantity) * item.Price, } } return orderDetail }