package admin import ( "net/http" "time" "bindbox-game/internal/code" "bindbox-game/internal/pkg/core" "bindbox-game/internal/pkg/validation" "bindbox-game/internal/repository/mysql/model" ) type listPayOrdersRequest struct { Page int `form:"page"` PageSize int `form:"page_size"` Status *int32 `form:"status"` SourceType *int32 `form:"source_type"` UserID *int64 `form:"user_id"` OrderNo string `form:"order_no"` IsConsumed *int32 `form:"is_consumed"` StartDate string `form:"start_date"` EndDate string `form:"end_date"` PayStart string `form:"pay_start"` PayEnd string `form:"pay_end"` } type listPayOrdersResponse struct { Page int `json:"page"` PageSize int `json:"page_size"` Total int64 `json:"total"` List []*model.Orders `json:"list"` } func (h *handler) ListPayOrders() core.HandlerFunc { return func(ctx core.Context) { req := new(listPayOrdersRequest) rsp := new(listPayOrdersResponse) if err := ctx.ShouldBindForm(req); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) return } if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 { req.PageSize = 20 } if req.PageSize > 100 { req.PageSize = 100 } q := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB() if req.Status != nil { q = q.Where(h.readDB.Orders.Status.Eq(*req.Status)) } if req.SourceType != nil { q = q.Where(h.readDB.Orders.SourceType.Eq(*req.SourceType)) } if req.UserID != nil { q = q.Where(h.readDB.Orders.UserID.Eq(*req.UserID)) } if req.OrderNo != "" { q = q.Where(h.readDB.Orders.OrderNo.Eq(req.OrderNo)) } if req.IsConsumed != nil { q = q.Where(h.readDB.Orders.IsConsumed.Eq(*req.IsConsumed)) } if req.StartDate != "" { if t, err := time.Parse("2006-01-02", req.StartDate); err == nil { q = q.Where(h.readDB.Orders.CreatedAt.Gte(t)) } } if req.EndDate != "" { if t, err := time.Parse("2006-01-02", req.EndDate); err == nil { t = t.Add(24 * time.Hour).Add(-time.Second) q = q.Where(h.readDB.Orders.CreatedAt.Lte(t)) } } if req.PayStart != "" { if t, err := time.Parse(time.RFC3339, req.PayStart); err == nil { q = q.Where(h.readDB.Orders.PaidAt.Gte(t)) } } if req.PayEnd != "" { if t, err := time.Parse(time.RFC3339, req.PayEnd); err == nil { q = q.Where(h.readDB.Orders.PaidAt.Lte(t)) } } total, err := q.Count() if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21001, err.Error())) return } rows, err := q.Order(h.readDB.Orders.ID.Desc()).Offset((req.Page-1)*req.PageSize).Limit(req.PageSize).Find() if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21002, err.Error())) return } rsp.Page = req.Page rsp.PageSize = req.PageSize rsp.Total = total rsp.List = rows ctx.Payload(rsp) } } type getPayOrderResponse struct { Order *model.Orders `json:"order"` Items []*model.OrderItems `json:"items"` Shipments []*model.ShippingRecords `json:"shipments"` Ledgers []*model.UserPointsLedger `json:"ledgers"` User *model.Users `json:"user"` Activity *struct{ ActivityID int64 `json:"activity_id"` ActivityName string `json:"activity_name"` IssueID int64 `json:"issue_id"` IssueNumber string `json:"issue_number"` IsWinner int32 `json:"is_winner"` Level int32 `json:"level"` RewardID int64 `json:"reward_id"` RewardName string `json:"reward_name"` ProductID int64 `json:"product_id"` } `json:"activity"` Payment *struct{ Status int32 `json:"status"` ActualAmount int64 `json:"actual_amount"` PaidAt string `json:"paid_at"` PayPreorderID int64 `json:"pay_preorder_id"` TransactionID string `json:"transaction_id"` } `json:"payment"` Refunds []*struct{ RefundNo string `json:"refund_no"` Amount int64 `json:"amount"` Status string `json:"status"` Channel string `json:"channel"` Reason string `json:"reason"` CreatedAt string `json:"created_at"` } `json:"refunds"` RefundableAmount int64 `json:"refundable_amount"` } func (h *handler) GetPayOrderDetail() core.HandlerFunc { return func(ctx core.Context) { rsp := new(getPayOrderResponse) orderNo := ctx.Param("order_no") if orderNo == "" { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少订单号")) return } order, err := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Orders.OrderNo.Eq(orderNo)).First() if err != nil || order == nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21003, "订单不存在")) return } items, _ := h.readDB.OrderItems.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.OrderItems.OrderID.Eq(order.ID)).Find() shipments, _ := h.readDB.ShippingRecords.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ShippingRecords.OrderID.Eq(order.ID)).Find() ledgers, _ := h.readDB.UserPointsLedger.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.UserPointsLedger.RefTable.Eq("orders"), h.readDB.UserPointsLedger.RefID.Eq(orderNo)).Find() user, _ := h.readDB.Users.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Users.ID.Eq(order.UserID)).First() var activityID int64 var activityName string var issueID int64 var issueNumber string var isWinner int32 var level int32 var rewardID int64 var rewardName string var rewardProductID int64 if order.SourceType == 2 { drawLog, _ := h.readDB.ActivityDrawLogs.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityDrawLogs.OrderID.Eq(order.ID)).First() if drawLog != nil { isWinner = drawLog.IsWinner level = drawLog.Level rewardID = drawLog.RewardID issueID = drawLog.IssueID issue, _ := h.readDB.ActivityIssues.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityIssues.ID.Eq(issueID)).First() if issue != nil { issueNumber = issue.IssueNumber activityID = issue.ActivityID activity, _ := h.readDB.Activities.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Activities.ID.Eq(activityID)).First() if activity != nil { activityName = activity.Name } } if rewardID > 0 { reward, _ := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityRewardSettings.ID.Eq(rewardID)).First() if reward != nil { rewardName = reward.Name rewardProductID = reward.ProductID } } } } rsp.Activity = &struct{ActivityID int64 `json:"activity_id"`; ActivityName string `json:"activity_name"`; IssueID int64 `json:"issue_id"`; IssueNumber string `json:"issue_number"`; IsWinner int32 `json:"is_winner"`; Level int32 `json:"level"`; RewardID int64 `json:"reward_id"`; RewardName string `json:"reward_name"`; ProductID int64 `json:"product_id"`}{ ActivityID: activityID, ActivityName: activityName, IssueID: issueID, IssueNumber: issueNumber, IsWinner: isWinner, Level: level, RewardID: rewardID, RewardName: rewardName, ProductID: rewardProductID, } if user != nil { rsp.User = user } rsp.Payment = &struct{Status int32 `json:"status"`; ActualAmount int64 `json:"actual_amount"`; PaidAt string `json:"paid_at"`; PayPreorderID int64 `json:"pay_preorder_id"`; TransactionID string `json:"transaction_id"`}{ Status: order.Status, ActualAmount: order.ActualAmount, PaidAt: order.PaidAt.Format("2006-01-02 15:04:05"), PayPreorderID: order.PayPreorderID, TransactionID: "", } tx, _ := h.readDB.PaymentTransactions.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.PaymentTransactions.OrderNo.Eq(order.OrderNo)).Order(h.readDB.PaymentTransactions.ID.Desc()).First() if tx != nil { rsp.Payment.PaidAt = tx.SuccessTime.Format("2006-01-02 15:04:05") rsp.Payment.TransactionID = tx.TransactionID } var refundedSum int64 var refunds []*struct{ RefundNo string `json:"refund_no"`; Amount int64 `json:"amount"`; Status string `json:"status"`; Channel string `json:"channel"`; Reason string `json:"reason"`; CreatedAt string `json:"created_at"` } prList, _ := h.readDB.PaymentRefunds.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.PaymentRefunds.OrderNo.Eq(order.OrderNo)).Order(h.readDB.PaymentRefunds.ID.Desc()).Find() for _, r := range prList { refundedSum += r.AmountRefund refunds = append(refunds, &struct{ RefundNo string `json:"refund_no"`; Amount int64 `json:"amount"`; Status string `json:"status"`; Channel string `json:"channel"`; Reason string `json:"reason"`; CreatedAt string `json:"created_at"` }{ RefundNo: r.RefundNo, Amount: r.AmountRefund, Status: r.Status, Channel: r.Channel, Reason: r.Reason, CreatedAt: r.CreatedAt.Format("2006-01-02 15:04:05") }) } var refundable int64 = order.ActualAmount - refundedSum if refundable < 0 { refundable = 0 } rsp.Refunds = refunds rsp.RefundableAmount = refundable rsp.Order = order rsp.Items = items rsp.Shipments = shipments rsp.Ledgers = ledgers ctx.Payload(rsp) } } type updateOrderRemarkRequest struct { Remark string `json:"remark"` } type simpleResponse struct { Success bool `json:"success"` } func (h *handler) UpdateOrderRemark() core.HandlerFunc { return func(ctx core.Context) { req := new(updateOrderRemarkRequest) rsp := new(simpleResponse) if err := ctx.ShouldBindJSON(req); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) return } orderNo := ctx.Param("order_no") if orderNo == "" { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少订单号")) return } order, err := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Orders.OrderNo.Eq(orderNo)).First() if err != nil || order == nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21004, "订单不存在")) return } _, err = h.writeDB.Orders.WithContext(ctx.RequestContext()).Where(h.readDB.Orders.ID.Eq(order.ID)).Updates(map[string]any{ h.writeDB.Orders.Remark.ColumnName().String(): req.Remark, h.writeDB.Orders.UpdatedAt.ColumnName().String(): time.Now(), }) if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21005, err.Error())) return } rsp.Success = true ctx.Payload(rsp) } } func (h *handler) CancelOrder() core.HandlerFunc { return func(ctx core.Context) { orderNo := ctx.Param("order_no") if orderNo == "" { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少订单号")) return } order, err := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Orders.OrderNo.Eq(orderNo)).First() if err != nil || order == nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21006, "订单不存在")) return } _, err = h.writeDB.Orders.WithContext(ctx.RequestContext()).Where(h.readDB.Orders.ID.Eq(order.ID), h.readDB.Orders.Status.Eq(1)).Updates(map[string]any{ h.readDB.Orders.Status.ColumnName().String(): 3, h.readDB.Orders.CancelledAt.ColumnName().String(): time.Now(), }) if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21007, err.Error())) return } ctx.Payload(&simpleResponse{Success: true}) } } func (h *handler) ConsumeOrder() core.HandlerFunc { return func(ctx core.Context) { orderNo := ctx.Param("order_no") if orderNo == "" { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少订单号")) return } order, err := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Orders.OrderNo.Eq(orderNo)).First() if err != nil || order == nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21008, "订单不存在")) return } _, err = h.writeDB.Orders.WithContext(ctx.RequestContext()).Where(h.readDB.Orders.ID.Eq(order.ID), h.readDB.Orders.Status.Eq(2)).Updates(map[string]any{ h.readDB.Orders.IsConsumed.ColumnName().String(): 1, }) if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 21009, err.Error())) return } ctx.Payload(&simpleResponse{Success: true}) } }