fix
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
"ycc-server/app/main/model"
|
||||
"ycc-server/common/ctxdata"
|
||||
"ycc-server/common/globalkey"
|
||||
"ycc-server/common/xerr"
|
||||
"ycc-server/pkg/lzkit/lzUtils"
|
||||
|
||||
@@ -62,53 +61,133 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请先完成实名认证"), "")
|
||||
}
|
||||
|
||||
// 3. 验证提现金额
|
||||
// 3. 验证提现方式
|
||||
if req.WithdrawalType != 1 && req.WithdrawalType != 2 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("提现方式无效"), "")
|
||||
}
|
||||
|
||||
// 4. 验证提现信息
|
||||
if req.WithdrawalType == 1 {
|
||||
// 支付宝提现:验证支付宝账号和姓名
|
||||
if req.PayeeAccount == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入支付宝账号"), "")
|
||||
}
|
||||
if req.PayeeName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入收款人姓名"), "")
|
||||
}
|
||||
} else if req.WithdrawalType == 2 {
|
||||
// 银行卡提现:验证银行卡号、开户行和姓名
|
||||
if req.BankCardNo == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入银行卡号"), "")
|
||||
}
|
||||
if req.BankName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入开户行名称"), "")
|
||||
}
|
||||
if req.PayeeName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入收款人姓名"), "")
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 验证提现金额
|
||||
if req.Amount <= 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("提现金额必须大于0"), "")
|
||||
}
|
||||
|
||||
// 4. 获取钱包信息
|
||||
// 6. 获取钱包信息
|
||||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败, %v", err)
|
||||
}
|
||||
|
||||
// 5. 验证余额
|
||||
// 7. 验证余额(包括检查是否为负数)
|
||||
if wallet.Balance < 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("账户存在欠款,请先补足欠款后再申请提现,当前余额:%.2f", wallet.Balance)), "")
|
||||
}
|
||||
if wallet.Balance < req.Amount {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("余额不足,当前余额:%.2f", wallet.Balance)), "")
|
||||
}
|
||||
|
||||
// 6. 计算税费
|
||||
// 8. 支付宝月度提现额度校验(仅针对支付宝提现)
|
||||
if req.WithdrawalType == 1 {
|
||||
now := time.Now()
|
||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
nextMonthStart := monthStart.AddDate(0, 1, 0)
|
||||
|
||||
// 8.1 获取支付宝月度额度配置(默认 800 元)
|
||||
alipayQuota := 800.0
|
||||
if cfg, cfgErr := l.svcCtx.AgentConfigModel.FindOneByConfigKey(l.ctx, "alipay_month_quota"); cfgErr == nil {
|
||||
if parsed, parseErr := l.parseFloat(cfg.ConfigValue); parseErr == nil && parsed > 0 {
|
||||
alipayQuota = parsed
|
||||
}
|
||||
}
|
||||
|
||||
// 8.2 统计本月已申请/成功的支付宝提现金额(status IN (1,5)),避免多次申请占用超额
|
||||
withdrawBuilder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().
|
||||
Where("agent_id = ? AND withdrawal_type = ? AND status IN (1,5) AND create_time >= ? AND create_time < ?",
|
||||
agent.Id, 1, monthStart, nextMonthStart)
|
||||
usedAmount, sumErr := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, withdrawBuilder, "amount")
|
||||
if sumErr != nil {
|
||||
return nil, errors.Wrapf(sumErr, "查询本月支付宝提现额度使用情况失败")
|
||||
}
|
||||
|
||||
remainQuota := alipayQuota - usedAmount
|
||||
if remainQuota <= 0 {
|
||||
return nil, errors.Wrapf(
|
||||
xerr.NewErrMsg(fmt.Sprintf("本月支付宝提现额度已用完(额度:%.2f 元),请使用银行卡提现", alipayQuota)),
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
if req.Amount > remainQuota {
|
||||
return nil, errors.Wrapf(
|
||||
xerr.NewErrMsg(fmt.Sprintf("本月支付宝最高可提现 %.2f 元,请调整提现金额或使用银行卡提现", remainQuota)),
|
||||
"",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 计算税费
|
||||
yearMonth := int64(time.Now().Year()*100 + int(time.Now().Month()))
|
||||
taxInfo, err := l.calculateTax(l.ctx, agent.Id, req.Amount, yearMonth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "计算税费失败")
|
||||
}
|
||||
|
||||
// 7. 生成提现单号
|
||||
withdrawNo := fmt.Sprintf("WD%d%d", time.Now().Unix(), agent.Id)
|
||||
// 10. 生成提现单号
|
||||
withdrawNo := fmt.Sprintf("WD%d%s", time.Now().Unix(), agent.Id)
|
||||
|
||||
// 8. 使用事务处理提现申请
|
||||
// 11. 使用事务处理提现申请
|
||||
var withdrawalId string
|
||||
err = l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||
// 8.1 冻结余额
|
||||
// 11.1 冻结余额
|
||||
wallet.FrozenBalance += req.Amount
|
||||
wallet.Balance -= req.Amount
|
||||
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil {
|
||||
return errors.Wrapf(err, "冻结余额失败")
|
||||
}
|
||||
|
||||
// 8.2 创建提现记录
|
||||
// 11.2 创建提现记录
|
||||
withdrawal := &model.AgentWithdrawal{
|
||||
Id: uuid.New().String(),
|
||||
AgentId: agent.Id,
|
||||
WithdrawNo: withdrawNo,
|
||||
PayeeAccount: req.PayeeAccount,
|
||||
PayeeName: req.PayeeName,
|
||||
Amount: req.Amount,
|
||||
ActualAmount: taxInfo.ActualAmount,
|
||||
TaxAmount: taxInfo.TaxAmount,
|
||||
Status: 1, // 处理中(待审核)
|
||||
Id: uuid.New().String(),
|
||||
AgentId: agent.Id,
|
||||
WithdrawNo: withdrawNo,
|
||||
WithdrawalType: req.WithdrawalType,
|
||||
PayeeAccount: req.PayeeAccount,
|
||||
PayeeName: req.PayeeName,
|
||||
Amount: req.Amount,
|
||||
ActualAmount: taxInfo.ActualAmount,
|
||||
TaxAmount: taxInfo.TaxAmount,
|
||||
Status: 1, // 待审核
|
||||
}
|
||||
|
||||
// 如果是银行卡提现,设置银行卡相关字段
|
||||
if req.WithdrawalType == 2 {
|
||||
withdrawal.BankCardNo = lzUtils.StringToNullString(req.BankCardNo)
|
||||
withdrawal.BankName = lzUtils.StringToNullString(req.BankName)
|
||||
// 银行卡提现时,payee_account 可以存储银行卡号(便于查询),也可以留空
|
||||
if req.PayeeAccount == "" {
|
||||
withdrawal.PayeeAccount = req.BankCardNo
|
||||
}
|
||||
}
|
||||
|
||||
_, err := l.svcCtx.AgentWithdrawalModel.Insert(transCtx, session, withdrawal)
|
||||
@@ -117,7 +196,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
|
||||
}
|
||||
withdrawalId = withdrawal.Id
|
||||
|
||||
// 8.3 创建扣税记录
|
||||
// 11.3 创建扣税记录
|
||||
taxRecord := &model.AgentWithdrawalTax{
|
||||
AgentId: agent.Id,
|
||||
WithdrawalId: withdrawalId,
|
||||
@@ -167,8 +246,10 @@ func (l *ApplyWithdrawalLogic) calculateTax(ctx context.Context, agentId string,
|
||||
}
|
||||
|
||||
// 查询本月已提现金额
|
||||
// 注意:FindAll 方法会自动添加 del_state = ? 条件,所以这里不需要手动添加
|
||||
// 这里对 year_month 使用反引号包裹,避免与某些数据库版本/SQL 模式下的关键字冲突
|
||||
builder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().
|
||||
Where("agent_id = ? AND year_month = ? AND del_state = ?", agentId, yearMonth, globalkey.DelStateNo)
|
||||
Where("agent_id = ? AND `year_month` = ?", agentId, yearMonth)
|
||||
taxRecords, err := l.svcCtx.AgentWithdrawalTaxModel.FindAll(ctx, builder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "查询月度提现记录失败")
|
||||
|
||||
Reference in New Issue
Block a user