fix(wallet): enforce consistent withdrawal accounting

This commit is contained in:
david
2026-07-31 09:54:17 +08:00
parent 36a5ced1c0
commit 42a2322c8e
23 changed files with 1405 additions and 250 deletions

View File

@@ -143,7 +143,7 @@ func Recharge(ctx *gin.Context) {
}
func CreateApplyCash(ctx *gin.Context) {
point, _, ok := currentScope(ctx)
account, point, _, ok := CurrentDeliveryAccount(ctx)
if !ok {
return
}
@@ -162,29 +162,31 @@ func CreateApplyCash(ctx *gin.Context) {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
var pending int64
if err := db().Model(&models.WalletApplyCash{}).Where("wallet_basic_id = ? AND apply_status = ? AND status <> ?",
wallet.ID, common.StatusPending, common.StatusArchived).Select("COALESCE(SUM(amount), 0)").Scan(&pending).Error; err != nil ||
request.Amount > wallet.WithdrawalBalance-pending {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
var bankID uint64
if request.WalletBankIdentity != "" {
var bank models.WalletBank
if err := common.ActiveRecords(db()).Where("identity = ? AND wallet_basic_id = ?",
request.WalletBankIdentity, wallet.ID).First(&bank).Error; err != nil {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
var apply models.WalletApplyCash
err := db().Transaction(func(tx *gorm.DB) error {
var bankID uint64
if request.WalletBankIdentity != "" {
var bank models.WalletBank
if err := common.ActiveRecords(tx).Where("identity = ? AND wallet_basic_id = ?",
request.WalletBankIdentity, wallet.ID).First(&bank).Error; err != nil {
return err
}
bankID = bank.ID
}
bankID = bank.ID
}
apply := models.WalletApplyCash{
Entity: common.NewEntity(common.StatusEnable), ApplyStatus: common.StatusPending,
WalletBasicID: wallet.ID, WalletBankID: bankID, CashNo: models.NewIdentity(), RequestNo: request.RequestNo,
Amount: request.Amount, Channel: request.Channel, Remark: request.Remark,
}
if err := db().Create(&apply).Error; err != nil {
var createErr error
apply, _, createErr = common.CreateReservedWithdrawal(tx, common.WalletWithdrawalInput{
WalletBasicID: wallet.ID,
WalletBankID: bankID,
RequestNo: request.RequestNo,
Amount: request.Amount,
Channel: request.Channel,
Remark: request.Remark,
OperatorIdentity: account.Identity,
OperatorName: account.DisplayName,
})
return createErr
})
if err != nil {
infra.Response.Error(ctx, err)
return
}