331 lines
11 KiB
Go
331 lines
11 KiB
Go
|
|
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"`
|
|||
|
|
}
|