Files
ai_dianshang/server/internal/handler/admin_refund.go
2025-11-17 13:32:54 +08:00

331 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"dianshang/internal/service"
"dianshang/pkg/logger"
"dianshang/pkg/response"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
type AdminRefundHandler struct {
refundService *service.RefundService
orderService *service.OrderService
}
func NewAdminRefundHandler(refundService *service.RefundService, orderService *service.OrderService) *AdminRefundHandler {
return &AdminRefundHandler{
refundService: refundService,
orderService: orderService,
}
}
// GetPendingRefunds 获取待处理的退款申请
// @Summary 获取待处理的退款申请
// @Description 管理员获取所有待处理的退款申请(分页)
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Success 200 {object} response.Response{data=response.PageResponse{list=[]model.Refund}}
// @Failure 400 {object} response.Response
// @Router /admin/refunds/pending [get]
func (h *AdminRefundHandler) GetPendingRefunds(c *gin.Context) {
// 获取分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
// 获取待处理的退款申请
refunds, total, err := h.refundService.GetPendingRefunds(c.Request.Context(), page, pageSize)
if err != nil {
logger.Error("获取待处理退款申请失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, "获取待处理退款申请失败")
return
}
response.Page(c, refunds, total, page, pageSize)
}
// ProcessRefund 处理退款申请
// @Summary 处理退款申请
// @Description 管理员审核并处理退款申请
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Param request body ProcessRefundRequest true "处理退款请求"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/refunds/{refund_id}/process [post]
func (h *AdminRefundHandler) ProcessRefund(c *gin.Context) {
refundIDStr := c.Param("id")
logger.Info("ProcessRefund开始", "refund_id_param", refundIDStr, "path", c.Request.URL.Path)
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
logger.Error("解析退款ID失败", "refund_id_str", refundIDStr, "error", err)
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "无效的退款ID")
return
}
var req ProcessRefundRequest
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error("绑定处理退款参数失败", "error", err)
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "参数错误: "+err.Error())
return
}
// 从上下文获取管理员ID中间件设置的是user_id
adminID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
err = h.refundService.ProcessRefund(c.Request.Context(), uint(refundID), adminID.(uint), req.AdminRemark)
if err != nil {
logger.Error("处理退款申请失败", "error", err, "refundID", refundID, "adminID", adminID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("退款申请处理成功", "refundID", refundID, "adminID", adminID)
response.Success(c, "处理成功")
}
// RejectRefund 拒绝退款申请
// @Summary 拒绝退款申请
// @Description 管理员拒绝退款申请
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Param request body RejectRefundRequest true "拒绝退款请求"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/refunds/{refund_id}/reject [post]
func (h *AdminRefundHandler) RejectRefund(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "无效的退款ID")
return
}
var req RejectRefundRequest
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error("绑定拒绝退款参数失败", "error", err)
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "参数错误: "+err.Error())
return
}
// 从上下文获取管理员ID中间件设置的是user_id
adminID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
err = h.refundService.RejectRefund(c.Request.Context(), uint(refundID), adminID.(uint), req.RejectReason)
if err != nil {
logger.Error("拒绝退款申请失败", "error", err, "refundID", refundID, "adminID", adminID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("退款申请已拒绝", "refundID", refundID, "adminID", adminID, "reason", req.RejectReason)
response.Success(c, "拒绝成功")
}
// GetAllRefunds 获取所有退款记录
// @Summary 获取所有退款记录
// @Description 管理员获取所有退款记录(分页)
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param status query int false "退款状态筛选"
// @Param user_id query int false "用户ID筛选"
// @Success 200 {object} response.Response{data=response.PageResponse{list=[]model.Refund}}
// @Failure 400 {object} response.Response
// @Router /admin/refunds [get]
func (h *AdminRefundHandler) GetAllRefunds(c *gin.Context) {
// 获取分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
// 获取筛选参数
status := c.Query("status")
userID := c.Query("user_id")
// 获取所有退款记录
refunds, total, err := h.refundService.GetAllRefunds(c.Request.Context(), page, pageSize, status, userID)
if err != nil {
logger.Error("获取退款记录失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, "获取退款记录失败")
return
}
response.Page(c, refunds, total, page, pageSize)
}
// GetRefundDetail 获取退款详情
// @Summary 获取退款详情
// @Description 管理员获取指定退款记录的详细信息
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Success 200 {object} response.Response{data=model.Refund}
// @Failure 400 {object} response.Response
// @Router /admin/refunds/{refund_id} [get]
func (h *AdminRefundHandler) GetRefundDetail(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "无效的退款ID")
return
}
refund, err := h.refundService.GetRefundDetailForAdmin(c.Request.Context(), uint(refundID))
if err != nil {
logger.Error("获取退款详情失败", "error", err, "refundID", refundID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, refund)
}
// GetRefundLogs 获取退款日志
// @Summary 获取退款日志
// @Description 管理员获取指定退款的操作日志
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Success 200 {object} response.Response{data=[]model.RefundLog}
// @Failure 400 {object} response.Response
// @Router /admin/refunds/{refund_id}/logs [get]
func (h *AdminRefundHandler) GetRefundLogs(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "无效的退款ID")
return
}
// 获取退款日志
logs, err := h.refundService.GetRefundLogs(c.Request.Context(), uint(refundID))
if err != nil {
logger.Error("获取退款日志失败", "error", err, "refundID", refundID)
response.ErrorWithMessage(c, response.ERROR, "获取退款日志失败")
return
}
logger.Info("获取退款日志成功", "refundID", refundID, "logCount", len(logs))
response.Success(c, logs)
}
// GetRefundStatistics 获取退款统计
// @Summary 获取退款统计
// @Description 获取退款统计数据
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param start_date query string false "开始日期"
// @Param end_date query string false "结束日期"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/refunds/statistics [get]
func (h *AdminRefundHandler) GetRefundStatistics(c *gin.Context) {
startDate := c.Query("start_date")
endDate := c.Query("end_date")
// 如果没有提供日期默认查询最近30天
if startDate == "" || endDate == "" {
now := time.Now()
endDate = now.Format("2006-01-02")
startDate = now.AddDate(0, 0, -30).Format("2006-01-02")
}
// 解析日期
startTime, err := time.Parse("2006-01-02", startDate)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "开始日期格式错误")
return
}
endTime, err := time.Parse("2006-01-02", endDate)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "结束日期格式错误")
return
}
// 设置时间范围到一天的结束
endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
// 使用退款服务获取真实统计数据
stats, err := h.refundService.GetRefundStatistics(c.Request.Context(), startTime, endTime)
if err != nil {
logger.Error("获取退款统计失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, "获取退款统计失败")
return
}
response.Success(c, stats)
}
// QueryRefundStatus 查询退款状态
// @Summary 查询退款状态
// @Description 管理员主动查询退款状态
// @Tags 管理员-退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /admin/refunds/{refund_id}/query [post]
func (h *AdminRefundHandler) QueryRefundStatus(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "无效的退款ID")
return
}
err = h.refundService.QueryRefundStatus(c.Request.Context(), uint(refundID))
if err != nil {
logger.Error("查询退款状态失败", "error", err, "refundID", refundID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("查询退款状态成功", "refundID", refundID)
response.Success(c, "查询完成")
}
// 请求结构体
type ProcessRefundRequest struct {
AdminRemark string `json:"admin_remark" binding:"max=500"`
}
type RejectRefundRequest struct {
RejectReason string `json:"reject_reason" binding:"required,max=500"`
}