Files
ai_dianshang/server/internal/handler/admin_refund.go

331 lines
11 KiB
Go
Raw Permalink Normal View History

2025-11-17 13:32:54 +08:00
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"`
}