This commit is contained in:
2026-05-13 14:43:10 +08:00
parent 2312f54e1e
commit 3399de0dc5
49 changed files with 1637 additions and 287 deletions

View File

@@ -88,26 +88,29 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
}
}
// 5. 验证提现金额
if req.Amount <= 0 {
return nil, errors.Wrapf(xerr.NewErrMsg("提现金额必须大于0"), "")
}
// 6. 获取钱包信息
// 5. 获取钱包信息
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败, %v", err)
}
// 7. 验证余额(包括检查是否为负数)
if wallet.Balance < 0 {
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("账户存在欠款,请先补足欠款后再申请提现,当前余额:%.2f", wallet.Balance)), "")
// 6. 提现金额与可用余额:仅可提「可用余额」内金额;可用余额须大于 0
withdrawAmount := lzUtils.RoundMoney(req.Amount)
if withdrawAmount <= 0 {
return nil, errors.Wrapf(xerr.NewErrMsg("提现金额必须大于0"), "")
}
if wallet.Balance < req.Amount {
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("余额不足,当前余额:%.2f", wallet.Balance)), "")
bal := lzUtils.RoundMoney(wallet.Balance)
if bal < 0 {
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("账户存在欠款,请先补足欠款后再申请提现,当前可用余额:%.2f", bal)), "")
}
if bal <= 0 {
return nil, errors.Wrapf(xerr.NewErrMsg("可用余额须大于0才能申请提现"), "")
}
if withdrawAmount > bal {
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("提现金额不能超过可用余额(不含冻结),当前可用:%.2f", bal)), "")
}
// 8. 支付宝月度提现额度校验(仅针对支付宝提现)
// 7. 支付宝月度提现额度校验(仅针对支付宝提现)
if req.WithdrawalType == 1 {
now := time.Now()
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
@@ -138,7 +141,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
)
}
if req.Amount > remainQuota {
if withdrawAmount > remainQuota {
return nil, errors.Wrapf(
xerr.NewErrMsg(fmt.Sprintf("本月支付宝最高可提现 %.2f 元,请调整提现金额或使用银行卡提现", remainQuota)),
"",
@@ -148,7 +151,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
// 9. 计算税费
yearMonth := int64(time.Now().Year()*100 + int(time.Now().Month()))
taxInfo, err := l.calculateTax(l.ctx, agent.Id, req.Amount, yearMonth)
taxInfo, err := l.calculateTax(l.ctx, agent.Id, withdrawAmount, yearMonth)
if err != nil {
return nil, errors.Wrapf(err, "计算税费失败")
}
@@ -164,9 +167,26 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
// 11. 使用事务处理提现申请
var withdrawalId string
err = l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
// 提交前再次校验可用余额(防止并发入账/冲正与申请提现竞态)
fresh, wErr := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, agent.Id)
if wErr != nil {
return errors.Wrapf(wErr, "事务内查询钱包失败")
}
freshBal := lzUtils.RoundMoney(fresh.Balance)
if freshBal < 0 {
return errors.New("账户存在欠款,无法申请提现")
}
if freshBal <= 0 {
return errors.New("可用余额须大于0才能申请提现")
}
if withdrawAmount > freshBal {
return fmt.Errorf("提现金额不能超过当前可用余额(%.2f", freshBal)
}
wallet = fresh
// 11.1 冻结余额
wallet.FrozenBalance += req.Amount
wallet.Balance -= req.Amount
wallet.FrozenBalance += withdrawAmount
wallet.Balance -= withdrawAmount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil {
return errors.Wrapf(err, "冻结余额失败")
}
@@ -179,7 +199,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
WithdrawalType: req.WithdrawalType,
PayeeAccount: req.PayeeAccount,
PayeeName: req.PayeeName,
Amount: req.Amount,
Amount: withdrawAmount,
ActualAmount: taxInfo.ActualAmount,
TaxAmount: taxInfo.TaxAmount,
Status: 1, // 待审核
@@ -206,7 +226,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
AgentId: agent.Id,
WithdrawalId: withdrawalId,
YearMonth: yearMonth,
WithdrawalAmount: req.Amount,
WithdrawalAmount: withdrawAmount,
TaxableAmount: taxInfo.TaxableAmount,
TaxRate: taxInfo.TaxRate,
TaxAmount: taxInfo.TaxAmount,
@@ -293,8 +313,8 @@ func (l *ApplyWithdrawalLogic) calculateTax(ctx context.Context, agentId string,
}
// 计算税费
taxAmount := taxableAmount * taxRate
actualAmount := amount - taxAmount
taxAmount := lzUtils.RoundMoney(taxableAmount * taxRate)
actualAmount := lzUtils.RoundMoney(amount - taxAmount)
return &TaxInfo{
TaxableAmount: taxableAmount,