194 lines
4.5 KiB
Go
194 lines
4.5 KiB
Go
package withdrawal
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
"hfb_sys/backend/internal/modules/wallet"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// 管理员查询提现列表
|
|
func (r *Repository) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
|
|
db := r.db.WithContext(ctx).Model(&model.WithdrawalRequest{})
|
|
|
|
if query.Status != "" {
|
|
db = db.Where("status = ?", query.Status)
|
|
}
|
|
if query.UserID > 0 {
|
|
db = db.Where("user_id = ?", query.UserID)
|
|
}
|
|
|
|
var total int64
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
offset := (query.Page - 1) * query.Size
|
|
var withdrawals []model.WithdrawalRequest
|
|
if err := db.Order("created_at DESC").
|
|
Offset(offset).Limit(query.Size).
|
|
Find(&withdrawals).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
items := make([]WithdrawalDetailDTO, 0, len(withdrawals))
|
|
for _, w := range withdrawals {
|
|
dto, err := r.toDetailDTO(ctx, w)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
items = append(items, *dto)
|
|
}
|
|
|
|
return &AdminPaginatedResult{
|
|
Items: items,
|
|
Total: total,
|
|
Page: query.Page,
|
|
PageSize: query.Size,
|
|
}, nil
|
|
}
|
|
|
|
// 管理员查询提现详情
|
|
|
|
// 管理员查询提现详情
|
|
func (r *Repository) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
|
|
var withdrawal model.WithdrawalRequest
|
|
if err := r.db.WithContext(ctx).First(&withdrawal, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrWithdrawalNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return r.toDetailDTO(ctx, withdrawal)
|
|
}
|
|
|
|
// 管理员审核提现
|
|
|
|
// 管理员审核提现
|
|
func (r *Repository) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
|
|
db := r.db.WithContext(ctx)
|
|
var withdrawal model.WithdrawalRequest
|
|
if err := db.First(&withdrawal, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrWithdrawalNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
// 只有待审核状态可以审核
|
|
if withdrawal.Status != "pending" {
|
|
return nil, ErrWithdrawalLocked
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
if req.Approved {
|
|
// 审核通过,进入处理中状态
|
|
withdrawal.Status = "processing"
|
|
} else {
|
|
// 审核拒绝,解冻余额
|
|
withdrawal.Status = "rejected"
|
|
}
|
|
|
|
withdrawal.ReviewedBy = &adminID
|
|
withdrawal.ReviewedAt = &now
|
|
withdrawal.ReviewRemark = req.Remark
|
|
|
|
err := db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Save(&withdrawal).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// 如果拒绝,解冻余额
|
|
if !req.Approved {
|
|
if err := wallet.AppendEntries(tx, wallet.Entry{
|
|
UserID: withdrawal.UserID,
|
|
Direction: "out",
|
|
AmountCent: withdrawal.AmountCent,
|
|
BalanceType: "frozen",
|
|
BizType: "withdraw_reject",
|
|
BizNo: withdrawal.WithdrawNo,
|
|
Remark: fmt.Sprintf("提现被拒绝: %s", req.Remark),
|
|
}, wallet.Entry{
|
|
UserID: withdrawal.UserID,
|
|
Direction: "in",
|
|
AmountCent: withdrawal.AmountCent,
|
|
BalanceType: "available",
|
|
BizType: "withdraw_reject",
|
|
BizNo: withdrawal.WithdrawNo,
|
|
Remark: fmt.Sprintf("提现被拒绝: %s", req.Remark),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return r.AdminFindByID(ctx, id)
|
|
}
|
|
|
|
// 管理员确认打款
|
|
|
|
// 管理员确认打款
|
|
func (r *Repository) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
|
|
db := r.db.WithContext(ctx)
|
|
var withdrawal model.WithdrawalRequest
|
|
if err := db.First(&withdrawal, id).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, ErrWithdrawalNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
// 只有处理中状态可以确认打款
|
|
if withdrawal.Status != "processing" {
|
|
return nil, ErrWithdrawalLocked
|
|
}
|
|
|
|
now := time.Now()
|
|
withdrawal.Status = "completed"
|
|
withdrawal.PaidBy = &adminID
|
|
withdrawal.PaidAt = &now
|
|
withdrawal.PaymentProofURL = req.PaymentProofURL
|
|
withdrawal.PaymentRemark = req.Remark
|
|
|
|
err := db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Save(&withdrawal).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// 扣除冻结余额
|
|
if err := wallet.AppendEntries(tx, wallet.Entry{
|
|
UserID: withdrawal.UserID,
|
|
Direction: "out",
|
|
AmountCent: withdrawal.AmountCent,
|
|
BalanceType: "frozen",
|
|
BizType: "withdraw_complete",
|
|
BizNo: withdrawal.WithdrawNo,
|
|
Remark: "提现完成",
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return r.AdminFindByID(ctx, id)
|
|
}
|
|
|
|
// 转换为用户DTO
|