Initial commit: 网络验证平台
This commit is contained in:
@@ -0,0 +1,526 @@
|
||||
package developer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"verification-platform-backend/internal/database"
|
||||
"verification-platform-backend/internal/model"
|
||||
"verification-platform-backend/internal/service"
|
||||
"verification-platform-backend/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type FinanceRecordResponse struct {
|
||||
ID uint `json:"id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Type string `json:"type"`
|
||||
UserID uint `json:"user_id"`
|
||||
AppID uint `json:"app_id"`
|
||||
Amount float64 `json:"amount"`
|
||||
Detail string `json:"detail"`
|
||||
Status string `json:"status"`
|
||||
PaymentType string `json:"payment_type"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
User *struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
} `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
func SetupFinanceRoutes(r *gin.RouterGroup) {
|
||||
finance := r.Group("/finance")
|
||||
{
|
||||
finance.GET("/stats", handleGetFinanceStatistics)
|
||||
finance.GET("/statistics", handleGetFinanceStatistics)
|
||||
finance.GET("/recharge-records", handleGetRechargeRecords)
|
||||
finance.GET("/consumption-records", handleGetConsumptionRecords)
|
||||
finance.GET("/records", handleGetFinanceRecords)
|
||||
finance.DELETE("/records/:id", handleDeleteFinanceRecord)
|
||||
finance.POST("/records/batch-delete", handleBatchDeleteFinanceRecords)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetFinanceStatistics(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
|
||||
if len(appIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"total_income": 0,
|
||||
"total_expense": 0,
|
||||
"net_profit": 0,
|
||||
"monthly_transactions": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"total_income": 0,
|
||||
"total_expense": 0,
|
||||
"net_profit": 0,
|
||||
"monthly_transactions": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var totalIncome float64
|
||||
var totalExpense float64
|
||||
|
||||
database.DB.Model(&model.RechargeRecord{}).
|
||||
Where("user_id IN ? AND status = ?", appUserIDs, "success").
|
||||
Select("COALESCE(SUM(amount), 0)").
|
||||
Scan(&totalIncome)
|
||||
|
||||
database.DB.Model(&model.ConsumptionRecord{}).
|
||||
Where("user_id IN ? AND status = ?", appUserIDs, "success").
|
||||
Select("COALESCE(SUM(amount), 0)").
|
||||
Scan(&totalExpense)
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"total_income": totalIncome,
|
||||
"total_expense": totalExpense,
|
||||
"net_profit": totalIncome - totalExpense,
|
||||
})
|
||||
}
|
||||
|
||||
func handleGetRechargeRecords(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
|
||||
if len(appIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"records": []model.RechargeRecord{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"records": []model.RechargeRecord{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var records []model.RechargeRecord
|
||||
query := database.DB.Model(&model.RechargeRecord{}).Preload("AppUser").Where("user_id IN ?", appUserIDs)
|
||||
|
||||
search := c.Query("search")
|
||||
status := c.Query("status")
|
||||
startDate := c.Query("start_date")
|
||||
endDate := c.Query("end_date")
|
||||
|
||||
if search != "" {
|
||||
query = query.Where("order_no LIKE ? OR card_code LIKE ?", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
if status != "" && status != "all" {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
if startDate != "" {
|
||||
query = query.Where("created_at >= ?", startDate)
|
||||
}
|
||||
if endDate != "" {
|
||||
query = query.Where("created_at <= ?", endDate+" 23:59:59")
|
||||
}
|
||||
|
||||
if err := query.Order("created_at DESC").Find(&records).Error; err != nil {
|
||||
response.Error(c, 500, "获取充值记录失败")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"records": records,
|
||||
"total": len(records),
|
||||
})
|
||||
}
|
||||
|
||||
func handleGetConsumptionRecords(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
|
||||
if len(appIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"records": []model.ConsumptionRecord{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"records": []model.ConsumptionRecord{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var records []model.ConsumptionRecord
|
||||
query := database.DB.Model(&model.ConsumptionRecord{}).Preload("AppUser").Where("user_id IN ?", appUserIDs)
|
||||
|
||||
search := c.Query("search")
|
||||
recordType := c.Query("type")
|
||||
status := c.Query("status")
|
||||
startDate := c.Query("start_date")
|
||||
endDate := c.Query("end_date")
|
||||
|
||||
if search != "" {
|
||||
query = query.Where("order_no LIKE ? OR content LIKE ?", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
if recordType != "" && recordType != "all" {
|
||||
query = query.Where("type = ?", recordType)
|
||||
}
|
||||
if status != "" && status != "all" {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
if startDate != "" {
|
||||
query = query.Where("created_at >= ?", startDate)
|
||||
}
|
||||
if endDate != "" {
|
||||
query = query.Where("created_at <= ?", endDate+" 23:59:59")
|
||||
}
|
||||
|
||||
if err := query.Order("created_at DESC").Find(&records).Error; err != nil {
|
||||
response.Error(c, 500, "获取消费记录失败")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"records": records,
|
||||
"total": len(records),
|
||||
})
|
||||
}
|
||||
|
||||
func handleGetFinanceRecords(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
|
||||
if len(appIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"recharge_records": []FinanceRecordResponse{},
|
||||
"consumption_records": []FinanceRecordResponse{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Success(c, gin.H{
|
||||
"recharge_records": []FinanceRecordResponse{},
|
||||
"consumption_records": []FinanceRecordResponse{},
|
||||
"total": 0,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
page := c.DefaultQuery("page", "1")
|
||||
pageSize := c.DefaultQuery("page_size", "10")
|
||||
search := c.Query("search")
|
||||
recordType := c.Query("type")
|
||||
status := c.Query("status")
|
||||
startDate := c.Query("start_date")
|
||||
endDate := c.Query("end_date")
|
||||
|
||||
var rechargeRecords []model.RechargeRecord
|
||||
rechargeQuery := database.DB.Model(&model.RechargeRecord{}).Preload("AppUser").Where("user_id IN ?", appUserIDs)
|
||||
|
||||
if search != "" {
|
||||
rechargeQuery = rechargeQuery.Where("order_no LIKE ? OR card_code LIKE ?", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
if recordType == "recharge" || recordType == "" || recordType == "all" {
|
||||
if status != "" && status != "all" {
|
||||
rechargeQuery = rechargeQuery.Where("status = ?", status)
|
||||
}
|
||||
if startDate != "" {
|
||||
rechargeQuery = rechargeQuery.Where("created_at >= ?", startDate)
|
||||
}
|
||||
if endDate != "" {
|
||||
rechargeQuery = rechargeQuery.Where("created_at <= ?", endDate+" 23:59:59")
|
||||
}
|
||||
if err := rechargeQuery.Order("created_at DESC").Find(&rechargeRecords).Error; err != nil {
|
||||
response.Error(c, 500, "获取充值记录失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var consumptionRecords []model.ConsumptionRecord
|
||||
consumptionQuery := database.DB.Model(&model.ConsumptionRecord{}).Preload("AppUser").Where("user_id IN ?", appUserIDs)
|
||||
|
||||
if search != "" {
|
||||
consumptionQuery = consumptionQuery.Where("order_no LIKE ? OR content LIKE ?", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
if recordType == "consumption" || recordType == "" || recordType == "all" {
|
||||
if status != "" && status != "all" {
|
||||
consumptionQuery = consumptionQuery.Where("status = ?", status)
|
||||
}
|
||||
if startDate != "" {
|
||||
consumptionQuery = consumptionQuery.Where("created_at >= ?", startDate)
|
||||
}
|
||||
if endDate != "" {
|
||||
consumptionQuery = consumptionQuery.Where("created_at <= ?", endDate+" 23:59:59")
|
||||
}
|
||||
if err := consumptionQuery.Order("created_at DESC").Find(&consumptionRecords).Error; err != nil {
|
||||
response.Error(c, 500, "获取消费记录失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var allRecords []FinanceRecordResponse
|
||||
for _, r := range rechargeRecords {
|
||||
var user *struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
if r.AppUser != nil && r.AppUser.ID != 0 {
|
||||
user = &struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}{
|
||||
ID: r.AppUser.ID,
|
||||
Username: r.AppUser.Username,
|
||||
Email: r.AppUser.Email,
|
||||
}
|
||||
}
|
||||
allRecords = append(allRecords, FinanceRecordResponse{
|
||||
ID: r.ID,
|
||||
OrderNo: r.OrderNo,
|
||||
Type: "recharge",
|
||||
UserID: r.UserID,
|
||||
AppID: r.AppUser.ApplicationID,
|
||||
Amount: r.Amount,
|
||||
Detail: r.CardCode,
|
||||
Status: r.Status,
|
||||
PaymentType: r.PaymentType,
|
||||
Remark: r.Remark,
|
||||
CreatedAt: r.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
User: user,
|
||||
})
|
||||
}
|
||||
|
||||
for _, r := range consumptionRecords {
|
||||
var user *struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
if r.AppUser != nil && r.AppUser.ID != 0 {
|
||||
user = &struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}{
|
||||
ID: r.AppUser.ID,
|
||||
Username: r.AppUser.Username,
|
||||
Email: r.AppUser.Email,
|
||||
}
|
||||
}
|
||||
allRecords = append(allRecords, FinanceRecordResponse{
|
||||
ID: r.ID,
|
||||
OrderNo: r.OrderNo,
|
||||
Type: "consumption",
|
||||
UserID: r.UserID,
|
||||
AppID: r.AppUser.ApplicationID,
|
||||
Amount: r.Amount,
|
||||
Detail: r.Content,
|
||||
Status: r.Status,
|
||||
PaymentType: r.PaymentType,
|
||||
Remark: r.Remark,
|
||||
CreatedAt: r.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
User: user,
|
||||
})
|
||||
}
|
||||
|
||||
total := len(allRecords)
|
||||
start := 0
|
||||
end := total
|
||||
if p, err := parseInt(page); err == nil && p > 0 {
|
||||
if ps, err := parseInt(pageSize); err == nil && ps > 0 {
|
||||
start = (p - 1) * ps
|
||||
end = start + ps
|
||||
if start > total {
|
||||
start = total
|
||||
}
|
||||
if end > total {
|
||||
end = total
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if start > end {
|
||||
start = end
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"records": allRecords[start:end],
|
||||
"total": total,
|
||||
})
|
||||
}
|
||||
|
||||
func parseInt(s string) (int, error) {
|
||||
var result int
|
||||
_, err := fmt.Sscanf(s, "%d", &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func handleDeleteFinanceRecord(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
recordID := c.Param("id")
|
||||
recordType := c.Query("type")
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
if len(appIDs) == 0 {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var deletedType string
|
||||
var deletedAmount float64
|
||||
|
||||
if recordType == "recharge" {
|
||||
var record model.RechargeRecord
|
||||
if err := database.DB.Where("id = ? AND user_id IN ?", recordID, appUserIDs).First(&record).Error; err != nil {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
if err := database.DB.Delete(&record).Error; err != nil {
|
||||
response.Error(c, 500, "删除失败")
|
||||
return
|
||||
}
|
||||
deletedType = "充值记录"
|
||||
deletedAmount = record.Amount
|
||||
} else if recordType == "consumption" {
|
||||
var record model.ConsumptionRecord
|
||||
if err := database.DB.Where("id = ? AND user_id IN ?", recordID, appUserIDs).First(&record).Error; err != nil {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
if err := database.DB.Delete(&record).Error; err != nil {
|
||||
response.Error(c, 500, "删除失败")
|
||||
return
|
||||
}
|
||||
deletedType = "消费记录"
|
||||
deletedAmount = record.Amount
|
||||
} else {
|
||||
var rechargeRecord model.RechargeRecord
|
||||
var consumptionRecord model.ConsumptionRecord
|
||||
|
||||
if err := database.DB.Where("id = ? AND user_id IN ?", recordID, appUserIDs).First(&rechargeRecord).Error; err == nil {
|
||||
database.DB.Delete(&rechargeRecord)
|
||||
deletedType = "充值记录"
|
||||
deletedAmount = rechargeRecord.Amount
|
||||
service.LogOperation(c, "delete", "finance_record", nil, fmt.Sprintf("删除%s: %.2f", deletedType, deletedAmount), nil)
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.DB.Where("id = ? AND user_id IN ?", recordID, appUserIDs).First(&consumptionRecord).Error; err == nil {
|
||||
database.DB.Delete(&consumptionRecord)
|
||||
deletedType = "消费记录"
|
||||
deletedAmount = consumptionRecord.Amount
|
||||
service.LogOperation(c, "delete", "finance_record", nil, fmt.Sprintf("删除%s: %.2f", deletedType, deletedAmount), nil)
|
||||
response.Success(c, nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
|
||||
service.LogOperation(c, "delete", "finance_record", nil, fmt.Sprintf("删除%s: %.2f", deletedType, deletedAmount), nil)
|
||||
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
func handleBatchDeleteFinanceRecords(c *gin.Context) {
|
||||
userID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, 401, "未授权")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
IDs []uint `json:"ids"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if len(req.IDs) == 0 {
|
||||
response.Error(c, 400, "请选择要删除的记录")
|
||||
return
|
||||
}
|
||||
|
||||
var appIDs []uint
|
||||
database.DB.Model(&model.Application{}).Where("user_id = ?", userID).Pluck("id", &appIDs)
|
||||
if len(appIDs) == 0 {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
|
||||
var appUserIDs []uint
|
||||
database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Pluck("id", &appUserIDs)
|
||||
if len(appUserIDs) == 0 {
|
||||
response.Error(c, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
|
||||
database.DB.Where("id IN ? AND user_id IN ?", req.IDs, appUserIDs).Delete(&model.RechargeRecord{})
|
||||
database.DB.Where("id IN ? AND user_id IN ?", req.IDs, appUserIDs).Delete(&model.ConsumptionRecord{})
|
||||
|
||||
service.LogOperation(c, "batch_delete", "finance_record", nil, fmt.Sprintf("批量删除财务记录: %d条", len(req.IDs)), nil)
|
||||
|
||||
response.Success(c, gin.H{"deleted": len(req.IDs)})
|
||||
}
|
||||
Reference in New Issue
Block a user