package order import ( "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.GET("/print-detail", jwt, h.PrintDetail) route.POST("/execute", jwt, h.Execute) route.GET("/history", jwt, h.GetAllHistoryOrders) route.GET("/ticket-sold", jwt, h.CountSoldOfTicket) route.POST("/checkin/inquiry", jwt, h.CheckInInquiry) route.POST("/checkin/execute", jwt, h.CheckInExecute) route.GET("/sum-amount", jwt, h.SumAmount) route.GET("/daily-sales", jwt, h.GetDailySalesTicket) route.GET("/payment-distribution", jwt, h.GetPaymentDistributionChart) } func NewHandler(service services.Order) *Handler { return &Handler{ service: service, } } func (h *Handler) Inquiry(c *gin.Context) { ctx := request.GetMyContext(c) var req request.Order if err := c.ShouldBindJSON(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } if !ctx.IsCasheer() { response.ErrorWrapper(c, errors.ErrorBadRequest) return } // override the partner_id req.PartnerID = *ctx.GetPartnerID() 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) PrintDetail(c *gin.Context) { ctx := request.GetMyContext(c) var req request.OrderPrintDetail if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } order, err := h.service.GetPrintDetail(ctx, req.ID) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: MapOrderToPrintDetailResponse(order, ctx.GetName()), }) } 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 } if !ctx.IsCasheer() { response.ErrorWrapper(c, errors.ErrorBadRequest) return } req.PartnerID = *ctx.GetPartnerID() 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 (h *Handler) CheckInInquiry(c *gin.Context) { ctx := request.GetMyContext(c) var req request.Checkin if err := c.ShouldBindJSON(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } if !ctx.IsCasheer() || req.QRCode == "" { response.ErrorWrapper(c, errors.ErrorBadRequest) return } partnerID := ctx.GetPartnerID() resp, err := h.service.CheckInInquiry(ctx, req.QRCode, partnerID) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: response.CheckingInquiryResponse{ Token: resp.Token, }, }) } func (h *Handler) CheckInExecute(c *gin.Context) { ctx := request.GetMyContext(c) var req request.CheckinExecute if err := c.ShouldBindJSON(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } if !ctx.IsCasheer() || req.Token == "" { response.ErrorWrapper(c, errors.ErrorBadRequest) return } partnerID := ctx.GetPartnerID() resp, err := h.service.CheckInExecute(ctx, req.Token, partnerID) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: MapOrderToExecuteCheckinResponse(resp.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, Total: order.Total, Fee: order.Fee, 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 MapOrderToExecuteCheckinResponse(order *entity.Order) response.ExecuteCheckinResponse { 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.ExecuteCheckinResponse{ ID: order.ID, RefID: order.RefID, PartnerID: order.PartnerID, Status: order.Status, Amount: order.Amount, PaymentType: order.PaymentType, CreatedAt: order.CreatedAt, OrderItems: orderItems, } } 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("2006-01-02 15:04:05"), BookingTime: resp.BookingTime.Format("2006-01-02 15:04:05"), Tickets: resp.Tickets, PaymentType: resp.PaymentType, Status: resp.Status, Amount: resp.Amount, VisitDate: resp.VisitDate.Format("2006-01-02"), TicketStatus: resp.TicketStatus, Source: resp.Source, } } func (h *Handler) SumAmount(c *gin.Context) { var req request.OrderParam if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) order, err := h.service.SumAmount(ctx, req.ToOrderEntity(ctx)) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: response.OrderAmount{ Amount: order.Amount, }, }) } func (h *Handler) GetAllHistoryOrders(c *gin.Context) { var req request.OrderParam 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) CountSoldOfTicket(c *gin.Context) { var req request.OrderParam if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) res, err := h.service.CountSoldOfTicket(ctx, req.ToOrderEntity(ctx)) if err != nil { response.ErrorWrapper(c, err) return } c.JSON(http.StatusOK, response.BaseResponse{ Success: true, Status: http.StatusOK, Data: response.TicketSold{ Count: res.Count, }, }) } func (h *Handler) GetDailySalesTicket(c *gin.Context) { var req request.OrderParam if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) resp, err := h.service.GetDailySales(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.toDailySales(resp), }) } func (h *Handler) GetPaymentDistributionChart(c *gin.Context) { var req request.OrderParam if err := c.ShouldBindQuery(&req); err != nil { response.ErrorWrapper(c, errors.ErrorBadRequest) return } ctx := request.GetMyContext(c) resp, err := h.service.GetPaymentDistribution(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.toPaymentDistributionChart(resp), }) } func (h *Handler) toHistoryOrderList(resp []*entity.HistoryOrder, total int64, req request.OrderParam) 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) toDailySales(resp []entity.ProductDailySales) []response.ProductDailySales { var dailySales []response.ProductDailySales for _, b := range resp { dailySales = append(dailySales, response.ProductDailySales{ Day: b.Day, SiteID: b.SiteID, Total: b.Total, SiteName: b.SiteName, PaymentType: b.PaymentType, }) } return dailySales } func (h *Handler) toPaymentDistributionChart(resp []entity.PaymentTypeDistribution) []response.PaymentDistribution { var dailySales []response.PaymentDistribution for _, b := range resp { dailySales = append(dailySales, response.PaymentDistribution{ PaymentType: b.PaymentType, Count: b.Count, }) } return dailySales } func MapOrderToPrintDetailResponse(order *entity.OrderPrintDetail, casherName string) response.PrintDetailResponse { 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.PrintDetailResponse{ ID: order.ID, OrderID: order.OrderID, Total: order.Total, Fee: order.Fee, PaymentType: order.GetPaymanetType(), Source: order.Source, VisitDateAt: order.VisitDate.Format("2006-01-02"), VisitTime: time.Now().Format("15:04:05"), OrderItems: orderItems, CasheerName: casherName, PartnerName: order.SiteName, Logo: order.Logo, } }