Files
CMS/src/CMSMicroservice.Application/ManualPaymentCQ/Commands/ProcessManualMembershipPayment/ProcessManualMembershipPaymentCommandHandler.cs
T
masoodafar-web 10d2ca20d1
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m11s
refactor: rename UserWalletChangeLog→UserWalletHistory, add History interceptor & migration
- Rename UserWalletChangeLog to UserWalletHistory across 54+ files (entities, configs, DTOs, commands, queries, protos, services)
- Rename 34 files and 11 directories accordingly
- Rename proto file userwalletchangelog.proto → userwallethistory.proto
- Add IHasHistory<T> generic interface for history auto-tracking
- Implement IHasHistory<PackageHistory> on Package entity
- Add HistoryTrackingSaveChangesInterceptor (reflection-based, auto-fills Old* values from OriginalValues)
- Wire interceptor in DI and ApplicationDbContext
- Add EF migration Q27_HistoryTables_And_RenameWalletHistory:
  * RenameTable UserWalletChangeLogs → UserWalletHistories (preserves data)
  * Rename PK, FK constraints and indexes via sp_rename
  * CreateTable ClubMembershipCycleHistories + PackageHistories
2026-02-27 06:22:15 +03:30

147 lines
6.1 KiB
C#

using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Entities.Payment;
using CMSMicroservice.Domain.Enums;
using Microsoft.EntityFrameworkCore;
namespace CMSMicroservice.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<ProcessManualMembershipPaymentCommand, ProcessManualMembershipPaymentResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
private readonly ILogger<ProcessManualMembershipPaymentCommandHandler> _logger;
public ProcessManualMembershipPaymentCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser,
ILogger<ProcessManualMembershipPaymentCommandHandler> logger)
{
_context = context;
_currentUser = currentUser;
_logger = logger;
}
public async Task<ProcessManualMembershipPaymentResponseDto> Handle(
ProcessManualMembershipPaymentCommand request,
CancellationToken cancellationToken)
{
try
{
_logger.LogInformation(
"Processing manual membership payment for UserId: {UserId}, Amount: {Amount}",
request.UserId, request.Amount);
// 1. دریافت شناسه ادمین از کاربر جاری
var currentUserId = _currentUser.UserId;
if (string.IsNullOrEmpty(currentUserId))
{
throw new UnauthorizedAccessException("کاربر احراز هویت نشده است");
}
if (!long.TryParse(currentUserId, out var adminUserId))
{
throw new UnauthorizedAccessException("شناسه کاربر نامعتبر است");
}
// 2. بررسی وجود کاربر
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);
if (user == null)
{
_logger.LogError("User not found: {UserId}", request.UserId);
throw new NotFoundException($"کاربر با شناسه {request.UserId} یافت نشد");
}
// 3. ایجاد ManualPayment با وضعیت Approved
var manualPayment = new ManualPayment
{
UserId = request.UserId,
Amount = request.Amount,
Type = ManualPaymentType.CashDeposit,
Description = request.Description ?? "پرداخت دستی عضویت",
ReferenceNumber = request.ReferenceNumber,
Status = ManualPaymentStatus.Approved,
RequestedBy = adminUserId,
ApprovedBy = adminUserId,
ApprovedAt = DateTime.Now
};
_context.ManualPayments.Add(manualPayment);
await _context.SaveChangesAsync(cancellationToken);
// 4. پیدا کردن یا ایجاد کیف پول
var wallet = await _context.UserWallets
.FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken);
if (wallet == null)
{
_logger.LogError("Wallet not found for UserId: {UserId}", request.UserId);
throw new NotFoundException($"کیف پول کاربر {request.UserId} یافت نشد");
}
// 6. ثبت تراکنش
var transaction = new Transaction
{
Amount = request.Amount,
Description = $"پرداخت دستی عضویت - {manualPayment.Description} - مرجع: {request.ReferenceNumber}",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.Now,
RefId = request.ReferenceNumber,
Type = TransactionType.DepositExternal1
};
_context.Transactions.Add(transaction);
await _context.SaveChangesAsync(cancellationToken);
// 7. اعمال تغییرات بر کیف پول
var oldBalance = wallet.Balance;
var oldDiscountBalance = wallet.DiscountBalance;
wallet.Balance += request.Amount;
wallet.DiscountBalance += request.Amount;
// 8. ثبت لاگ Balance
var balanceLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = request.Amount,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance,
ChangeDiscountValue = request.Amount,
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
// 10. به‌روزرسانی ManualPayment با TransactionId
manualPayment.TransactionId = transaction.Id;
await _context.SaveChangesAsync(cancellationToken);
_logger.LogInformation(
"Manual membership payment processed successfully. UserId: {UserId}, Amount: {Amount}, ManualPaymentId: {ManualPaymentId}, TransactionId: {TransactionId}, AdminUserId: {AdminUserId}",
request.UserId, request.Amount, manualPayment.Id, transaction.Id, adminUserId);
return new ProcessManualMembershipPaymentResponseDto
{
TransactionId = transaction.Id,
NewWalletBalance = wallet.Balance,
Message = "پرداخت دستی با موفقیت ثبت شد"
};
}
catch (Exception ex) when (ex is not NotFoundException)
{
_logger.LogError(ex,
"Error processing manual membership payment for UserId: {UserId}, Amount: {Amount}",
request.UserId, request.Amount);
throw;
}
}
}