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"` }