This commit is contained in:
aditya.siregar
2025-04-10 11:21:08 +07:00
parent c642c5c61b
commit 09c9a4d59d
30 changed files with 1797 additions and 758 deletions
@@ -109,7 +109,7 @@ func MapOrderToCreateOrderResponse(orderResponse *entity.OrderResponse, req requ
PaymentType: order.PaymentType,
CreatedAt: order.CreatedAt,
OrderItems: orderItems,
Fee: order.Fee,
Tax: order.Tax,
Total: order.Total,
}
}
@@ -249,7 +249,7 @@ func (h *Handler) toOrderDetail(order *entity.Order) *response.OrderDetail {
PaymentLink: paymentLink,
PaymentToken: paymentToken,
SiteName: siteName,
Fee: order.Fee,
Fee: order.Tax,
}
orderDetail.OrderItems = make([]response.OrderDetailItem, len(order.OrderItems))
+8 -7
View File
@@ -38,7 +38,7 @@ type CreateInProgressOrderRequest struct {
OrderType string `json:"order_type"`
PaymentProvider string `json:"payment_provider"`
TableNumber string `json:"table_number"`
InProgressOrderID string `json:"in_progress_order_id"`
InProgressOrderID int64 `json:"in_progress_order_id"`
}
type InProgressOrderItemRequest struct {
@@ -72,15 +72,15 @@ func (h *InProgressOrderHandler) Save(c *gin.Context) {
return
}
orderItems := make([]entity.InProgressOrderItem, len(req.OrderItems))
orderItems := make([]entity.OrderItemRequest, len(req.OrderItems))
for i, item := range req.OrderItems {
orderItems[i] = entity.InProgressOrderItem{
ItemID: item.ProductID,
Quantity: item.Quantity,
orderItems[i] = entity.OrderItemRequest{
ProductID: item.ProductID,
Quantity: item.Quantity,
}
}
order := &entity.InProgressOrder{
order := &entity.OrderRequest{
PartnerID: *partnerID,
CustomerID: req.CustomerID,
CustomerName: req.CustomerName,
@@ -89,6 +89,7 @@ func (h *InProgressOrderHandler) Save(c *gin.Context) {
TableNumber: req.TableNumber,
OrderType: req.OrderType,
ID: req.InProgressOrderID,
Source: "POS",
}
_, err := h.service.Save(ctx, order)
@@ -103,7 +104,7 @@ func (h *InProgressOrderHandler) Save(c *gin.Context) {
})
}
func mapToInProgressOrderResponse(order *entity.InProgressOrder) map[string]interface{} {
func mapToInProgressOrderResponse(order *entity.Order) map[string]interface{} {
orderItems := make([]map[string]interface{}, len(order.OrderItems))
for i, item := range order.OrderItems {
orderItems[i] = map[string]interface{}{
+314 -1
View File
@@ -2,6 +2,7 @@ package http
import (
"enaklo-pos-be/internal/common/errors"
order2 "enaklo-pos-be/internal/constants/order"
"enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/handlers/request"
"enaklo-pos-be/internal/handlers/response"
@@ -9,6 +10,8 @@ import (
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"net/http"
"strconv"
"time"
)
type Handler struct {
@@ -26,6 +29,12 @@ func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
route.POST("/inquiry", jwt, h.Inquiry)
route.POST("/execute", jwt, h.Execute)
route.GET("/history", jwt, h.GetOrderHistory)
route.GET("/payment-analysis", jwt, h.GetPaymentMethodAnalysis)
route.GET("/revenue-overview", jwt, h.GetRevenueOverview)
route.GET("/sales-by-category", jwt, h.GetSalesByCategory)
route.GET("/popular-products", jwt, h.GetPopularProducts)
}
type InquiryRequest struct {
@@ -56,7 +65,7 @@ type OrderItemRequest struct {
type ExecuteRequest struct {
PaymentMethod string `json:"payment_method" validate:"required"`
PaymentProvider string `json:"payment_provider"`
InProgressOrderID string `json:"in_progress_order_id"`
InProgressOrderID int64 `json:"in_progress_order_id"`
Token string `json:"token"`
}
@@ -140,3 +149,307 @@ func (h *Handler) Execute(c *gin.Context) {
Data: response.MapToOrderResponse(result),
})
}
func (h *Handler) GetOrderHistory(c *gin.Context) {
ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID()
limitStr := c.Query("limit")
offsetStr := c.Query("offset")
status := c.Query("status")
startDateStr := c.Query("start_date")
endDateStr := c.Query("end_date")
// Build search request
searchReq := entity.SearchRequest{}
// Set status if provided
if status != "" {
searchReq.Status = status
}
// Parse and set limit
limit := 10
if limitStr != "" {
parsedLimit, err := strconv.Atoi(limitStr)
if err == nil && parsedLimit > 0 {
limit = parsedLimit
}
}
if limit > 20 {
limit = 20
}
searchReq.Limit = limit
// Parse and set offset
offset := 0
if offsetStr != "" {
parsedOffset, err := strconv.Atoi(offsetStr)
if err == nil && parsedOffset >= 0 {
offset = parsedOffset
}
}
searchReq.Offset = offset
if startDateStr != "" {
startDate, err := time.Parse(time.RFC3339, startDateStr)
if err == nil {
searchReq.Start = startDate
}
}
// Parse end date if provided
if endDateStr != "" {
endDate, err := time.Parse(time.RFC3339, endDateStr)
if err == nil {
searchReq.End = endDate
}
}
orders, total, err := h.service.GetOrderHistory(ctx, *partnerID, searchReq)
if err != nil {
response.ErrorWrapper(c, err)
return
}
responseData := []response.OrderHistoryResponse{}
for _, order := range orders {
var orderItems []response.OrderItemResponse
for _, item := range order.OrderItems {
orderItems = append(orderItems, response.OrderItemResponse{
ProductID: item.ItemID,
ProductName: item.ItemName,
Price: item.Price,
Quantity: item.Quantity,
Subtotal: item.Price * float64(item.Quantity),
})
}
responseData = append(responseData, response.OrderHistoryResponse{
ID: order.ID,
CustomerName: order.CustomerName,
Status: order.Status,
Amount: order.Amount,
Total: order.Total,
PaymentType: h.formatPayment(order.PaymentType, order.PaymentProvider),
TableNumber: order.TableNumber,
OrderType: order.OrderType,
OrderItems: orderItems,
CreatedAt: order.CreatedAt.Format("2006-01-02T15:04:05Z"),
Tax: order.Tax,
})
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: responseData,
PagingMeta: &response.PagingMeta{
Page: offset + 1,
Total: int64(total),
Limit: limit,
},
})
}
func (h *Handler) formatPayment(payment, provider string) string {
if payment == "CASH" {
return payment
}
return payment + " " + provider
}
func (h *Handler) GetPaymentMethodAnalysis(c *gin.Context) {
ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID()
// Parse query parameters
limitStr := c.Query("limit")
offsetStr := c.Query("offset")
status := c.Query("status")
startDateStr := c.Query("start_date")
endDateStr := c.Query("end_date")
searchReq := entity.SearchRequest{}
limit := 10
if limitStr != "" {
parsedLimit, err := strconv.Atoi(limitStr)
if err == nil && parsedLimit > 0 {
limit = parsedLimit
}
}
if limit > 20 {
limit = 20
}
searchReq.Limit = limit
offset := 0
if offsetStr != "" {
parsedOffset, err := strconv.Atoi(offsetStr)
if err == nil && parsedOffset >= 0 {
offset = parsedOffset
}
}
searchReq.Offset = offset
if status != "" {
searchReq.Status = status
}
if startDateStr != "" {
startDate, err := time.Parse(time.RFC3339, startDateStr)
if err == nil {
searchReq.Start = startDate
}
}
if endDateStr != "" {
endDate, err := time.Parse(time.RFC3339, endDateStr)
if err == nil {
searchReq.End = endDate
}
}
paymentAnalysis, err := h.service.GetOrderPaymentAnalysis(ctx, *partnerID, searchReq)
if err != nil {
response.ErrorWrapper(c, err)
return
}
paymentBreakdown := make([]PaymentMethodBreakdown, len(paymentAnalysis.PaymentMethodBreakdown))
for i, bd := range paymentAnalysis.PaymentMethodBreakdown {
paymentBreakdown[i] = PaymentMethodBreakdown{
PaymentMethod: h.formatPayment(bd.PaymentType, bd.PaymentProvider),
TotalTransactions: bd.TotalTransactions,
TotalAmount: bd.TotalAmount,
}
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: PaymentMethodAnalysisResponse{
PaymentMethodBreakdown: paymentBreakdown,
TotalAmount: paymentAnalysis.TotalAmount,
TotalTransactions: paymentAnalysis.TotalTransactions,
},
})
}
type PaymentMethodBreakdown struct {
PaymentMethod string `json:"payment_method"`
TotalTransactions int64 `json:"total_transactions"`
TotalAmount float64 `json:"total_amount"`
AverageTransactionAmount float64 `json:"average_transaction_amount"`
Percentage float64 `json:"percentage"`
}
type PaymentMethodAnalysisResponse struct {
PaymentMethodBreakdown []PaymentMethodBreakdown `json:"payment_method_breakdown"`
TotalAmount float64 `json:"total_amount"`
TotalTransactions int64 `json:"total_transactions"`
MostUsedPaymentMethod string `json:"most_used_payment_method"`
HighestRevenueMethod string `json:"highest_revenue_method"`
}
func (h *Handler) GetRevenueOverview(c *gin.Context) {
ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID()
granularity := c.Query("period")
year := time.Now().Year()
if granularity != "m" && granularity != "w" && granularity != "d" {
granularity = "m"
}
revenueOverview, err := h.service.GetRevenueOverview(
ctx,
*partnerID,
year,
granularity,
order2.Paid.String(),
)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: revenueOverview,
})
}
func (h *Handler) GetSalesByCategory(c *gin.Context) {
ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID()
period := c.Query("period")
status := order2.Paid.String()
if period != "d" && period != "w" && period != "m" {
period = "d"
}
salesByCategory, err := h.service.GetSalesByCategory(
ctx,
*partnerID,
period,
status,
)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: salesByCategory,
})
}
func (h *Handler) GetPopularProducts(c *gin.Context) {
ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID()
period := c.Query("period")
status := order2.Paid.String()
limitStr := c.Query("limit")
sortBy := c.Query("sort_by")
limit, err := strconv.Atoi(limitStr)
if err != nil {
limit = 10 // default limit
}
if period != "d" && period != "w" && period != "m" {
period = "d"
}
popularProducts, err := h.service.GetPopularProducts(
ctx,
*partnerID,
period,
status,
limit,
sortBy,
)
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: popularProducts,
})
}
+1 -1
View File
@@ -204,7 +204,7 @@ func MapOrderToCreateOrderResponse(orderResponse *entity.OrderResponse) response
Status: order.Status,
Amount: order.Amount,
Total: order.Total,
Fee: order.Fee,
Tax: order.Tax,
PaymentType: order.PaymentType,
CreatedAt: order.CreatedAt,
OrderItems: orderItems,
+25
View File
@@ -28,6 +28,7 @@ func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
route.PUT("/:id", jwt, isSuperAdmin, h.Update)
route.GET("/:id", jwt, isSuperAdmin, h.GetByID)
route.DELETE("/:id", jwt, isSuperAdmin, h.Delete)
route.PUT("/update", jwt, h.UpdateMyStore)
}
func NewHandler(service services.Partner) *Handler {
@@ -268,3 +269,27 @@ func (h *Handler) toPartnerResponseList(resp []*entity.Partner, total int64, req
Offset: req.Offset,
}
}
func (h *Handler) UpdateMyStore(c *gin.Context) {
ctx := request.GetMyContext(c)
PartnerID := ctx.GetPartnerID()
var req request.Partner
if err := c.ShouldBindJSON(&req); err != nil {
response.ErrorWrapper(c, errors.ErrorBadRequest)
return
}
updatedPartner, err := h.service.Update(ctx, req.ToEntityUpdate(*PartnerID))
if err != nil {
response.ErrorWrapper(c, err)
return
}
c.JSON(http.StatusOK, response.BaseResponse{
Success: true,
Status: http.StatusOK,
Data: h.toPartnerResponse(updatedPartner),
})
}