fix: Phase 0 — critical bugs in package purchase handlers

B1: VerifyGoldenPackagePurchase — DiscountBalance was NOT charged (Amount × 2)
    Now charges DiscountBalance same as all other handlers.

B2: VerifyGoldenPackagePurchase — UserPackagePurchase record was NOT created
    Now creates UPP with OrderId and TransactionId.

B3: VerifyPackagePurchase — UserPackagePurchase record was NOT created
    Now creates UPP after wallet charge.

B4: VerifyBasePackagePayment — UserPackagePurchase record was NOT created
    Now creates UPP after wallet change log.

Also: VerifyGolden WalletChangeLog split into 2 logs (Balance + Discount)
      to match the pattern used by VerifyPackagePurchase.
      Transaction description changed from 'پکیج طلایی' to 'پکیج' (generic).

Impact: Only Daya Loan handler was creating UserPackagePurchase before.
        Now all 4 payment paths create it consistently.
This commit is contained in:
masoodafar-web
2026-02-24 21:52:36 +03:30
parent cbaa20f339
commit 8b9c317de6
3 changed files with 92 additions and 12 deletions
@@ -164,13 +164,33 @@ public class VerifyBasePackagePaymentCommandHandler : IRequestHandler<VerifyBase
await _context.UserWalletChangeLogs.AddAsync(changeLog, cancellationToken);
// 9. به‌روزرسانی Order
// 9. ثبت UserPackagePurchase
if (order.PackageId.HasValue)
{
var packagePurchase = new UserPackagePurchase
{
UserId = order.UserId,
PackageId = order.PackageId.Value,
PurchaseMethod = PackagePurchaseMethod.DirectPurchase,
PurchasedAt = DateTime.Now,
Amount = SystemConstants.BasePackageAmount,
OrderId = order.Id,
TransactionId = transaction.Id
};
await _context.UserPackagePurchases.AddAsync(packagePurchase, cancellationToken);
_logger.LogInformation(
"Created UserPackagePurchase for UserId {UserId}, PackageId {PackageId}",
order.UserId, order.PackageId.Value);
}
// 10. به‌روزرسانی Order
order.TransactionId = transaction.Id;
order.PaymentStatus = PaymentStatus.Success;
order.PaymentDate = DateTime.Now;
order.PaymentMethod = PaymentMethod.IPG;
// 10. به‌روزرسانی User
// 11. به‌روزرسانی User
order.User.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
await _context.SaveChangesAsync(cancellationToken);
@@ -113,17 +113,23 @@ public class VerifyGoldenPackagePurchaseCommandHandler : IRequestHandler<VerifyG
var oldBalance = wallet.Balance;
wallet.Balance += order.Amount;
// شارژ DiscountBalance (موجودی اعتباری) — دو برابر مبلغ سفارش
var oldDiscountBalance = wallet.DiscountBalance;
wallet.DiscountBalance += order.Amount * 2;
_logger.LogInformation(
"Charging wallet Balance for user {UserId} from {OldBalance} to {NewBalance}",
"Charging wallet for user {UserId}. Balance: {OldBalance} -> {NewBalance}, DiscountBalance: {OldDiscount} -> {NewDiscount}",
order.UserId,
oldBalance,
wallet.Balance);
wallet.Balance,
oldDiscountBalance,
wallet.DiscountBalance);
// 5. ثبت Transaction
var transaction = new Transaction
{
Amount = order.Amount,
Description = $"خرید پکیج طلایی از درگاه - سفارش #{order.Id}",
Description = $"خرید پکیج از درگاه - سفارش #{order.Id}",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.Now,
RefId = verifyResult.RefId,
@@ -133,23 +139,57 @@ public class VerifyGoldenPackagePurchaseCommandHandler : IRequestHandler<VerifyG
_context.Transactions.Add(transaction);
await _context.SaveChangesAsync(cancellationToken);
// 6. ثبت لاگ تغییر کیف پول
var changeLog = new UserWalletChangeLog
// 6. ثبت لاگ تغییر Balance
var balanceLog = new UserWalletChangeLog
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = order.Amount,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance,
CurrentDiscountBalance = oldDiscountBalance,
ChangeDiscountValue = 0,
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(balanceLog, cancellationToken);
await _context.UserWalletChangeLogs.AddAsync(changeLog, cancellationToken);
// 7. ثبت لاگ تغییر DiscountBalance
var discountLog = new UserWalletChangeLog
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = 0,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance,
ChangeDiscountValue = order.Amount * 2,
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken);
// 7. به‌روزرسانی سفارش و کاربر
// 8. ثبت UserPackagePurchase
if (order.PackageId.HasValue)
{
var packagePurchase = new UserPackagePurchase
{
UserId = order.UserId,
PackageId = order.PackageId.Value,
PurchaseMethod = PackagePurchaseMethod.DirectPurchase,
PurchasedAt = DateTime.Now,
Amount = order.Amount,
OrderId = order.Id,
TransactionId = transaction.Id
};
await _context.UserPackagePurchases.AddAsync(packagePurchase, cancellationToken);
_logger.LogInformation(
"Created UserPackagePurchase for UserId {UserId}, PackageId {PackageId}",
order.UserId, order.PackageId.Value);
}
// 9. به‌روزرسانی سفارش و کاربر
order.TransactionId = transaction.Id;
order.PaymentStatus = PaymentStatus.Success;
order.PaymentDate = DateTime.Now;
@@ -154,13 +154,33 @@ public class VerifyPackagePurchaseCommandHandler
};
await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken);
// 8. به‌روزرسانی Order
// 8. ثبت UserPackagePurchase
if (order.PackageId.HasValue)
{
var packagePurchase = new UserPackagePurchase
{
UserId = order.UserId,
PackageId = order.PackageId.Value,
PurchaseMethod = PackagePurchaseMethod.DirectPurchase,
PurchasedAt = DateTime.Now,
Amount = order.Amount,
OrderId = order.Id,
TransactionId = transaction.Id
};
await _context.UserPackagePurchases.AddAsync(packagePurchase, cancellationToken);
_logger.LogInformation(
"Created UserPackagePurchase for UserId {UserId}, PackageId {PackageId}",
order.UserId, order.PackageId.Value);
}
// 9. به‌روزرسانی Order
order.TransactionId = transaction.Id;
order.PaymentStatus = PaymentStatus.Success;
order.PaymentDate = DateTime.Now;
order.PaymentMethod = PaymentMethod.IPG;
// 9. تغییر User.PackagePurchaseMethod
// 10. تغییر User.PackagePurchaseMethod
order.User.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
await _context.SaveChangesAsync(cancellationToken);