Files
hm-server/app/main/api/internal/logic/admin_agent/adminreviewbankcardwithdrawallogic.go
2025-12-24 19:16:34 +08:00

188 lines
6.7 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 admin_agent
import (
"context"
"database/sql"
"time"
"tydata-server/app/main/model"
"tydata-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
// 审核操作常量
const (
ReviewActionApprove = 1 // 确认
ReviewActionReject = 2 // 拒绝
)
// 状态常量
const (
StatusPending = 1 // 申请中/处理中
StatusSuccess = 2 // 成功
StatusFailed = 3 // 失败
)
// 提现类型常量
const (
WithdrawTypeAlipay = 1 // 支付宝提现
WithdrawTypeBankCard = 2 // 银行卡提现
)
type AdminReviewBankCardWithdrawalLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminReviewBankCardWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminReviewBankCardWithdrawalLogic {
return &AdminReviewBankCardWithdrawalLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *types.AdminReviewBankCardWithdrawalReq) (resp *types.AdminReviewBankCardWithdrawalResp, err error) {
// 验证操作类型
if req.Action != ReviewActionApprove && req.Action != ReviewActionReject {
return nil, errors.Wrapf(xerr.NewErrMsg("操作类型不正确"), "操作类型验证失败")
}
// 拒绝操作必须填写备注
if req.Action == ReviewActionReject && req.Remark == "" {
return nil, errors.Wrapf(xerr.NewErrMsg("拒绝提现必须填写拒绝原因"), "拒绝原因验证失败")
}
resp = &types.AdminReviewBankCardWithdrawalResp{
Success: false,
}
// 使用事务处理审核操作
err = l.svcCtx.AgentModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 获取提现记录
record, err := l.svcCtx.AgentWithdrawalModel.FindOne(ctx, req.WithdrawalId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrMsg("提现记录不存在"), "提现记录不存在")
}
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询提现记录失败: %v", err)
}
// 验证提现记录状态必须是申请中
if record.Status != StatusPending {
return errors.Wrapf(xerr.NewErrMsg("该提现记录已处理,无法重复操作"), "状态验证失败")
}
// 验证提现类型
if record.WithdrawType != WithdrawTypeBankCard {
return errors.Wrapf(xerr.NewErrMsg("该记录不是银行卡提现,无法审核"), "提现类型验证失败")
}
if req.Action == ReviewActionApprove {
// 确认提现
return l.approveWithdrawal(ctx, session, record)
} else {
// 拒绝提现
return l.rejectWithdrawal(ctx, session, record, req.Remark)
}
})
if err != nil {
return nil, err
}
resp.Success = true
return resp, nil
}
// 确认提现
func (l *AdminReviewBankCardWithdrawalLogic) approveWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
// 更新提现记录状态为成功
record.Status = StatusSuccess
record.Remark = sql.NullString{String: "管理员确认提现", Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金并扣除FrozenBalance -= amount, Balance不变
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 更新扣税记录状态为成功
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusSuccess // 扣税状态 = 成功
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
// 提现成功后,给上级代理发放提现奖励
withdrawRewardErr := l.svcCtx.AgentService.GiveWithdrawReward(ctx, record.AgentId, record.Amount, session)
if withdrawRewardErr != nil {
l.Logger.Errorf("发放提现奖励失败代理ID%d提现金额%f错误%+v", record.AgentId, record.Amount, withdrawRewardErr)
// 提现奖励失败不影响主流程,只记录日志
} else {
l.Logger.Infof("发放提现奖励成功代理ID%d提现金额%f", record.AgentId, record.Amount)
}
l.Logger.Infof("银行卡提现确认成功 withdrawalId:%d amount:%f", record.Id, record.Amount)
return nil
}
// 拒绝提现
func (l *AdminReviewBankCardWithdrawalLogic) rejectWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal, remark string) error {
// 更新提现记录状态为失败
record.Status = StatusFailed
record.Remark = sql.NullString{String: "管理员拒绝:" + remark, Valid: true}
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
}
// 解冻资金FrozenBalance -= amount, Balance += amount
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
}
wallet.Balance += record.Amount
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
}
// 更新扣税记录状态为失败
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
}
if taxModel.TaxStatus == model.TaxStatusPending {
taxModel.TaxStatus = model.TaxStatusFailed // 扣税状态 = 失败
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
}
}
l.Logger.Infof("银行卡提现拒绝 withdrawalId:%d amount:%f reason:%s", record.Id, record.Amount, remark)
return nil
}