2 Commits

Author SHA1 Message Date
masoodafar-web 0457ef6c7c fix: validate discount wallet balance before applying discount in PlaceOrderCommandHandler
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m36s
2026-02-23 23:06:37 +03:30
masoodafar-web f3ac5ad7df fix: add missing UserWalletChangeLog for discount shop purchases and discount wallet charge
Bug: when buying from discount shop, DiscountBalance was deducted from DB
but no UserWalletChangeLog was created — making it invisible in wallet history.
Same issue existed for discount wallet top-up (charge).

Fixed in 3 handlers:
- PlaceOrderCommandHandler (fully paid by discount balance path)
- CompleteOrderPaymentCommandHandler (gateway + discount balance path)
- VerifyDiscountWalletChargeCommandHandler (discount wallet charge)
2026-02-23 22:59:00 +03:30
3 changed files with 59 additions and 3 deletions
@@ -62,9 +62,23 @@ public class CompleteOrderPaymentCommandHandler : IRequestHandler<CompleteOrderP
var userWallet = await _context.UserWallets
.FirstOrDefaultAsync(w => w.UserId == order.UserId, cancellationToken);
if (userWallet != null)
if (userWallet != null && order.DiscountBalanceUsed > 0)
{
userWallet.DiscountBalance -= order.DiscountBalanceUsed;
// ثبت لاگ تغییرات کیف پول
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
{
WalletId = userWallet.Id,
CurrentBalance = userWallet.Balance,
ChangeValue = 0,
CurrentNetworkBalance = userWallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = userWallet.DiscountBalance,
ChangeDiscountValue = -order.DiscountBalanceUsed,
IsIncrease = false,
RefrenceId = transaction.Id
});
}
// تایید فروش و کسر موجودی از طریق InventoryService
@@ -111,7 +111,18 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
// Always apply maximum possible discount (100%) — user cannot choose less
var maxDiscountBalanceUsable = totalDiscountAmount;
var actualDiscountBalanceUsed = Math.Min(maxDiscountBalanceUsable, userWallet.DiscountBalance);
// بررسی کافی بودن موجودی کیف پول اعتباری (تخفیفی)
if (userWallet.DiscountBalance < maxDiscountBalanceUsable)
{
return new PlaceOrderResponseDto
{
Success = false,
Message = $"موجودی کیف پول اعتباری کافی نیست. مبلغ مورد نیاز: {maxDiscountBalanceUsable:N0} ریال، موجودی شما: {userWallet.DiscountBalance:N0} ریال"
};
}
var actualDiscountBalanceUsed = maxDiscountBalanceUsable;
_logger.LogInformation(
"Discount auto-applied: max allowed={MaxAllowed}, wallet balance={WalletBalance}, used={Used}",
@@ -263,9 +274,25 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
var walletForDeduct = await _context.UserWallets
.FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken);
if (walletForDeduct != null)
if (walletForDeduct != null && actualDiscountBalanceUsed > 0)
{
walletForDeduct.DiscountBalance -= actualDiscountBalanceUsed;
// ثبت لاگ تغییرات کیف پول
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
{
WalletId = walletForDeduct.Id,
CurrentBalance = walletForDeduct.Balance,
ChangeValue = 0,
CurrentNetworkBalance = walletForDeduct.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = walletForDeduct.DiscountBalance,
ChangeDiscountValue = -actualDiscountBalanceUsed,
IsIncrease = false,
RefrenceId = transaction.Id
});
}
foreach (var cartItem in cartItems)
{
await _inventoryService.ConfirmSaleAsync(
@@ -114,6 +114,21 @@ public class VerifyDiscountWalletChargeCommandHandler
_context.Transactions.Add(transaction);
await _context.SaveChangesAsync(cancellationToken);
// ثبت لاگ تغییرات کیف پول (بعد از ایجاد Transaction برای داشتن TransactionId)
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = 0,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance,
ChangeDiscountValue = request.Amount,
IsIncrease = true,
RefrenceId = transaction.Id
});
await _context.SaveChangesAsync(cancellationToken);
// لینک PaymentTransaction به Transaction داخلی
if (paymentTx != null)
{