Files
verify/backend/internal/router/developer/orders.go
T
2026-04-27 17:22:56 +08:00

283 lines
8.0 KiB
Go

package developer
import (
"fmt"
"strconv"
"time"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
"verification-platform-backend/pkg/response"
"github.com/gin-gonic/gin"
)
func SetupOrderRoutes(r *gin.RouterGroup) {
r.GET("/orders", handleGetOrders)
r.GET("/orders/:id", handleGetOrder)
r.POST("/orders/:id/refund", handleRefundOrder)
r.GET("/orders/stats", handleGetOrderStats)
}
func handleGetOrders(c *gin.Context) {
userID := c.GetUint("user_id")
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
orderType := c.Query("order_type")
status := c.Query("status")
applicationID := c.Query("application_id")
search := c.Query("search")
startDate := c.Query("start_date")
endDate := c.Query("end_date")
var orders []model.Order
var total int64
query := database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID)
if orderType != "" {
query = query.Where("orders.order_type = ?", orderType)
}
if status != "" {
query = query.Where("orders.status = ?", status)
}
if applicationID != "" && applicationID != "all" {
query = query.Where("orders.application_id = ?", applicationID)
}
if search != "" {
query = query.Where("orders.order_no LIKE ? OR orders.title LIKE ?", "%"+search+"%", "%"+search+"%")
}
if startDate != "" {
query = query.Where("orders.created_at >= ?", startDate+" 00:00:00")
}
if endDate != "" {
query = query.Where("orders.created_at <= ?", endDate+" 23:59:59")
}
query.Count(&total)
offset := (page - 1) * pageSize
if err := query.Preload("User").Preload("Application").
Order("orders.created_at DESC").
Offset(offset).Limit(pageSize).
Find(&orders).Error; err != nil {
response.Error(c, 500, "获取订单列表失败")
return
}
response.Success(c, gin.H{
"orders": orders,
"total": total,
"page": page,
"page_size": pageSize,
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
})
}
func handleGetOrder(c *gin.Context) {
userID := c.GetUint("user_id")
orderID := c.Param("id")
var order model.Order
if err := database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("orders.id = ? AND (applications.user_id = ? OR orders.application_id IS NULL)", orderID, userID).
Preload("User").Preload("Application").
First(&order).Error; err != nil {
response.Error(c, 404, "订单不存在")
return
}
response.Success(c, order)
}
func handleRefundOrder(c *gin.Context) {
userID := c.GetUint("user_id")
orderID := c.Param("id")
var req struct {
Reason string `json:"reason" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误: "+err.Error())
return
}
var order model.Order
if err := database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("orders.id = ? AND (applications.user_id = ? OR orders.application_id IS NULL)", orderID, userID).
First(&order).Error; err != nil {
response.Error(c, 404, "订单不存在")
return
}
if order.Status != "paid" {
response.Error(c, 400, "只能退款已支付的订单")
return
}
tx := database.DB.Begin()
now := time.Now()
order.Status = "refunded"
order.RefundAt = &now
order.RefundReason = req.Reason
if err := tx.Save(&order).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "退款失败")
return
}
switch order.OrderType {
case "card_recharge":
var rechargeRecord model.RechargeRecord
if err := tx.Where("order_no = ?", order.OrderNo).First(&rechargeRecord).Error; err == nil {
rechargeRecord.Status = "refunded"
tx.Save(&rechargeRecord)
}
}
tx.Commit()
response.Success(c, gin.H{
"message": "退款成功",
"order": order,
})
}
func handleGetOrderStats(c *gin.Context) {
userID := c.GetUint("user_id")
applicationID := c.Query("application_id")
startDate := c.Query("start_date")
endDate := c.Query("end_date")
query := database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID)
if applicationID != "" && applicationID != "all" {
query = query.Where("orders.application_id = ?", applicationID)
}
if startDate != "" {
query = query.Where("orders.created_at >= ?", startDate+" 00:00:00")
}
if endDate != "" {
query = query.Where("orders.created_at <= ?", endDate+" 23:59:59")
}
var totalOrders, pendingOrders, paidOrders, refundedOrders int64
var totalAmount, paidAmount, refundedAmount float64
query.Count(&totalOrders)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status = ?", "pending").
Count(&pendingOrders)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status = ?", "paid").
Count(&paidOrders)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status = ?", "refunded").
Count(&refundedOrders)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status IN ?", []string{"paid", "refunded"}).
Select("COALESCE(SUM(amount), 0)").
Scan(&totalAmount)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status = ?", "paid").
Select("COALESCE(SUM(amount), 0)").
Scan(&paidAmount)
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Where("orders.status = ?", "refunded").
Select("COALESCE(SUM(amount), 0)").
Scan(&refundedAmount)
var typeStats []struct {
OrderType string
Count int64
TotalAmount float64
}
database.DB.Model(&model.Order{}).
Joins("LEFT JOIN applications ON orders.application_id = applications.id").
Where("applications.user_id = ? OR orders.application_id IS NULL", userID).
Select("order_type, COUNT(*) as count, COALESCE(SUM(amount), 0) as total_amount").
Group("order_type").
Scan(&typeStats)
response.Success(c, gin.H{
"total_orders": totalOrders,
"pending_orders": pendingOrders,
"paid_orders": paidOrders,
"refunded_orders": refundedOrders,
"total_amount": totalAmount,
"paid_amount": paidAmount,
"refunded_amount": refundedAmount,
"type_stats": typeStats,
})
}
func CreateOrder(orderType string, userID uint, applicationID *uint, title string, amount float64, paymentType string, description string) (*model.Order, error) {
orderNo := fmt.Sprintf("ORD%d%d", time.Now().Unix(), userID)
order := model.Order{
OrderNo: orderNo,
UserID: userID,
ApplicationID: applicationID,
OrderType: orderType,
Title: title,
Amount: amount,
PaymentType: paymentType,
Status: "pending",
Description: description,
}
if err := database.DB.Create(&order).Error; err != nil {
return nil, err
}
return &order, nil
}
func PayOrder(orderNo string) error {
var order model.Order
if err := database.DB.Where("order_no = ?", orderNo).First(&order).Error; err != nil {
return err
}
now := time.Now()
order.Status = "paid"
order.PaymentAt = &now
return database.DB.Save(&order).Error
}