283 lines
8.0 KiB
Go
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
|
|
}
|