package handlers import ( "reflect" "strconv" "strings" "github.com/gin-gonic/gin" "goalfymax-admin/internal/services" "goalfymax-admin/pkg/utils" ) type FinanceHandler struct { response *utils.Response } func NewFinanceHandler() *FinanceHandler { return &FinanceHandler{response: utils.NewResponse()} } func getPageParams(c *gin.Context) (int, int) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) if page < 1 { page = 1 } if size < 1 { size = 20 } offset := (page - 1) * size return offset, size } func (h *FinanceHandler) ListSandboxRecords(c *gin.Context) { offset, size := getPageParams(c) // 兼容多种参数命名:user/user_id,project/project_id userID := c.DefaultQuery("user_id", c.Query("user")) project := c.DefaultQuery("project", c.Query("project_id")) start := c.Query("start") end := c.Query("end") res, err := services.ListSandboxRecords(offset, size, userID, project, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) ListTokenUsages(c *gin.Context) { offset, size := getPageParams(c) userID := c.DefaultQuery("user_id", c.Query("user")) project := c.DefaultQuery("project", c.Query("project_id")) start := c.Query("start") // 对于token使用,按day进行过滤 end := c.Query("end") res, err := services.ListTokenUsages(offset, size, userID, project, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) ListMCPUsages(c *gin.Context) { offset, size := getPageParams(c) userID := c.DefaultQuery("user_id", c.Query("user")) project := c.DefaultQuery("project", c.Query("project_id")) start := c.Query("start") end := c.Query("end") res, err := services.ListMCPUsages(offset, size, userID, project, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) ListTransactionLogs(c *gin.Context) { offset, size := getPageParams(c) userID := c.Query("user_id") orderID := c.Query("order_id") txType := c.Query("type") status := c.Query("status") start := c.Query("start") end := c.Query("end") res, err := services.ListTransactionLogs(offset, size, userID, orderID, txType, status, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) ListPaymentRecords(c *gin.Context) { offset, size := getPageParams(c) userID := c.Query("user_id") orderID := c.Query("order_id") paypalOrderID := c.Query("paypal_order_id") status := c.Query("status") refundStatus := c.Query("refund_status") payerEmail := c.Query("payer_email") start := c.Query("start") end := c.Query("end") res, err := services.ListPaymentRecords(offset, size, userID, orderID, paypalOrderID, status, refundStatus, payerEmail, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) RefundPaymentRecord(c *gin.Context) { var req struct { OrderID string `json:"order_id"` PayPalCaptureID string `json:"paypal_capture_id"` Amount *int64 `json:"amount"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } err := services.RefundPaymentRecord(req.OrderID, req.PayPalCaptureID, req.Amount) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "退款请求已提交"}) } func (h *FinanceHandler) ListMcpAccountRechargeRecords(c *gin.Context) { offset, size := getPageParams(c) provider := c.Query("provider") account := c.Query("account") start := c.Query("start") end := c.Query("end") res, err := services.ListMcpAccountRechargeRecords(offset, size, provider, account, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) CreateMcpAccountRechargeRecord(c *gin.Context) { var req struct { ProviderID string `json:"provider_id" binding:"required"` Amount float64 `json:"amount" binding:"required,gt=0"` RechargeDate string `json:"recharge_date" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } // 获取当前操作人信息 var operatorID interface{} operatorName := "系统管理员" if user, exists := c.Get("user"); exists { if userInfo, ok := user.(map[string]interface{}); ok { // 尝试从userInfo中获取sub字段(可能是UUID格式) if sub, ok := userInfo["sub"].(string); ok { operatorID = sub } if name, ok := userInfo["name"].(string); ok { operatorName = name } else if email, ok := userInfo["email"].(string); ok { operatorName = email } } } // 如果user中没有sub,尝试从user_id获取 if operatorID == nil { operatorID, _ = c.Get("user_id") } err := services.CreateMcpAccountRechargeRecord( req.ProviderID, req.Amount, req.RechargeDate, operatorID, operatorName, req.Remark, ) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "创建成功"}) } func (h *FinanceHandler) UpdateMcpAccountRechargeRecord(c *gin.Context) { id := c.Param("id") var req struct { Amount *float64 `json:"amount"` RechargeDate *string `json:"recharge_date"` Remark *string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } err := services.UpdateMcpAccountRechargeRecord(id, req.Amount, req.RechargeDate, req.Remark) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "更新成功"}) } func (h *FinanceHandler) DeleteMcpAccountRechargeRecord(c *gin.Context) { id := c.Param("id") err := services.DeleteMcpAccountRechargeRecord(id) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "删除成功"}) } func (h *FinanceHandler) GetMcpProviderAccounts(c *gin.Context) { status := c.Query("status") var isUsed *bool if v := c.Query("is_used"); v != "" { if v == "true" { val := true isUsed = &val } else if v == "false" { val := false isUsed = &val } } list, err := services.GetMcpProviderAccounts(status, isUsed) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } func (h *FinanceHandler) GetMcpAccountBalances(c *gin.Context) { list, err := services.GetMcpAccountBalances() if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } func (h *FinanceHandler) GetMcpAccountBalanceHistory(c *gin.Context) { providerID := c.Param("provider_id") start := c.Query("start") end := c.Query("end") list, err := services.GetMcpAccountBalanceHistory(providerID, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } // ========== 模型账号充值记录和余额管理 ========== func (h *FinanceHandler) ListModelAccountRechargeRecords(c *gin.Context) { offset, size := getPageParams(c) provider := c.Query("provider") modelName := c.Query("model_name") start := c.Query("start") end := c.Query("end") res, err := services.ListModelAccountRechargeRecords(offset, size, provider, modelName, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Page(c, res.List, res.Total, offset/size+1, size) } func (h *FinanceHandler) CreateModelAccountRechargeRecord(c *gin.Context) { var req struct { Account string `json:"account" binding:"required"` Amount float64 `json:"amount" binding:"required,gt=0"` RechargeDate string `json:"recharge_date" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } // 获取当前操作人信息 var operatorID interface{} operatorName := "系统管理员" // 先尝试从 user_id 获取 if userID, exists := c.Get("user_id"); exists { operatorID = userID } // 从 user 信息中获取名称 if user, exists := c.Get("user"); exists { // user 可能是 *models.UserInfo 类型 if userInfo, ok := user.(map[string]interface{}); ok { if name, ok := userInfo["name"].(string); ok && name != "" { operatorName = name } else if email, ok := userInfo["email"].(string); ok && email != "" { operatorName = email } } else { // 尝试使用反射获取结构体字段 userVal := reflect.ValueOf(user) if userVal.Kind() == reflect.Ptr { userVal = userVal.Elem() } if userVal.Kind() == reflect.Struct { if nameField := userVal.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String { if name := nameField.String(); name != "" { operatorName = name } } if operatorName == "系统管理员" { if emailField := userVal.FieldByName("Email"); emailField.IsValid() && emailField.Kind() == reflect.String { if email := emailField.String(); email != "" { operatorName = email } } } } } } err := services.CreateModelAccountRechargeRecord( req.Account, req.Amount, req.RechargeDate, operatorID, operatorName, req.Remark, ) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "创建成功"}) } func (h *FinanceHandler) UpdateModelAccountRechargeRecord(c *gin.Context) { id := c.Param("id") var req struct { Amount *float64 `json:"amount"` RechargeDate *string `json:"recharge_date"` Remark *string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } err := services.UpdateModelAccountRechargeRecord(id, req.Amount, req.RechargeDate, req.Remark) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "更新成功"}) } func (h *FinanceHandler) DeleteModelAccountRechargeRecord(c *gin.Context) { id := c.Param("id") err := services.DeleteModelAccountRechargeRecord(id) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "删除成功"}) } func (h *FinanceHandler) GetModelConfigAccounts(c *gin.Context) { var enabled *bool if v := c.Query("enabled"); v != "" { if v == "true" { val := true enabled = &val } else if v == "false" { val := false enabled = &val } } list, err := services.GetModelConfigAccounts(enabled) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } func (h *FinanceHandler) GetModelAccountBalances(c *gin.Context) { list, err := services.GetModelAccountBalances() if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } func (h *FinanceHandler) GetModelAccountBalanceHistory(c *gin.Context) { account := c.Param("account") start := c.Query("start") end := c.Query("end") list, err := services.GetModelAccountBalanceHistory(account, start, end) if err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, list) } func (h *FinanceHandler) AdjustMcpAccountBalance(c *gin.Context) { providerID := c.Param("provider_id") var req struct { Balance float64 `json:"balance" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } operatorName := "系统管理员" if user, exists := c.Get("user"); exists { if userInfo, ok := user.(map[string]interface{}); ok { if name, ok := userInfo["name"].(string); ok && name != "" { operatorName = name } else if email, ok := userInfo["email"].(string); ok && email != "" { operatorName = email } } else { userVal := reflect.ValueOf(user) if userVal.Kind() == reflect.Ptr { userVal = userVal.Elem() } if userVal.Kind() == reflect.Struct { if nameField := userVal.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String { if name := nameField.String(); name != "" { operatorName = name } } if operatorName == "系统管理员" { if emailField := userVal.FieldByName("Email"); emailField.IsValid() && emailField.Kind() == reflect.String { if email := emailField.String(); email != "" { operatorName = email } } } } } } if err := services.AdjustMcpAccountBalance(providerID, req.Balance, operatorName, req.Remark); err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "更新成功"}) } func (h *FinanceHandler) AdjustModelAccountBalance(c *gin.Context) { account := c.Param("account") var req struct { Balance float64 `json:"balance" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } operatorName := "系统管理员" if user, exists := c.Get("user"); exists { if userInfo, ok := user.(map[string]interface{}); ok { if name, ok := userInfo["name"].(string); ok && name != "" { operatorName = name } else if email, ok := userInfo["email"].(string); ok && email != "" { operatorName = email } } else { userVal := reflect.ValueOf(user) if userVal.Kind() == reflect.Ptr { userVal = userVal.Elem() } if userVal.Kind() == reflect.Struct { if nameField := userVal.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String { if name := nameField.String(); name != "" { operatorName = name } } if operatorName == "系统管理员" { if emailField := userVal.FieldByName("Email"); emailField.IsValid() && emailField.Kind() == reflect.String { if email := emailField.String(); email != "" { operatorName = email } } } } } } if err := services.AdjustModelAccountBalance(account, req.Balance, operatorName, req.Remark); err != nil { h.response.InternalServerError(c, err.Error()) return } h.response.Success(c, gin.H{"message": "更新成功"}) } func (h *FinanceHandler) CreateModelAccountBalance(c *gin.Context) { var req struct { Account string `json:"account" binding:"required"` Balance float64 `json:"balance" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } operatorName := "系统管理员" if user, exists := c.Get("user"); exists { if userInfo, ok := user.(map[string]interface{}); ok { if name, ok := userInfo["name"].(string); ok && name != "" { operatorName = name } else if email, ok := userInfo["email"].(string); ok && email != "" { operatorName = email } } else { userVal := reflect.ValueOf(user) if userVal.Kind() == reflect.Ptr { userVal = userVal.Elem() } if userVal.Kind() == reflect.Struct { if nameField := userVal.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String { if name := nameField.String(); name != "" { operatorName = name } } if operatorName == "系统管理员" { if emailField := userVal.FieldByName("Email"); emailField.IsValid() && emailField.Kind() == reflect.String { if email := emailField.String(); email != "" { operatorName = email } } } } } } if err := services.CreateModelAccountBalanceRecord(req.Account, req.Balance, operatorName, req.Remark); err != nil { if strings.Contains(err.Error(), "已存在") { h.response.BadRequest(c, err.Error()) } else { h.response.InternalServerError(c, err.Error()) } return } h.response.Success(c, gin.H{"message": "创建成功"}) } func (h *FinanceHandler) CreateMcpAccountBalance(c *gin.Context) { var req struct { ProviderID string `json:"provider_id" binding:"required"` Balance float64 `json:"balance" binding:"required"` Remark string `json:"remark"` } if err := c.ShouldBindJSON(&req); err != nil { h.response.ValidateError(c, err) return } operatorName := "系统管理员" if user, exists := c.Get("user"); exists { if userInfo, ok := user.(map[string]interface{}); ok { if name, ok := userInfo["name"].(string); ok && name != "" { operatorName = name } else if email, ok := userInfo["email"].(string); ok && email != "" { operatorName = email } } else { userVal := reflect.ValueOf(user) if userVal.Kind() == reflect.Ptr { userVal = userVal.Elem() } if userVal.Kind() == reflect.Struct { if nameField := userVal.FieldByName("Name"); nameField.IsValid() && nameField.Kind() == reflect.String { if name := nameField.String(); name != "" { operatorName = name } } if operatorName == "系统管理员" { if emailField := userVal.FieldByName("Email"); emailField.IsValid() && emailField.Kind() == reflect.String { if email := emailField.String(); email != "" { operatorName = email } } } } } } if err := services.CreateMcpAccountBalanceRecord(req.ProviderID, req.Balance, operatorName, req.Remark); err != nil { if strings.Contains(err.Error(), "已存在") { h.response.BadRequest(c, err.Error()) } else { h.response.InternalServerError(c, err.Error()) } return } h.response.Success(c, gin.H{"message": "创建成功"}) }