diff --git a/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/AcceptClubMembershipContract/AcceptClubMembershipContractCommandHandler.cs b/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/AcceptClubMembershipContract/AcceptClubMembershipContractCommandHandler.cs index a73731f..caec452 100644 --- a/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/AcceptClubMembershipContract/AcceptClubMembershipContractCommandHandler.cs +++ b/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/AcceptClubMembershipContract/AcceptClubMembershipContractCommandHandler.cs @@ -135,15 +135,65 @@ public class AcceptClubMembershipContractCommandHandler }; await _context.UserContracts.AddAsync(userContract, cancellationToken); - // 6. بارگذاری پکیج از آخرین خرید کاربر یا پکیج پایه + // 6. بارگذاری پکیج موثر برای امضای قرارداد + // اولویت: + // 1) پکیج Cycle جاری (مسیر صحیح برای پرداخت دستی) + // 2) آخرین خرید پکیج + // 3) پکیج پایه + var currentCyclePackageId = await _context.ClubMembershipCycles + .Where(c => c.UserId == userId && c.IsCurrentCycle) + .OrderByDescending(c => c.CycleNumber) + .Select(c => (long?)c.PackageId) + .FirstOrDefaultAsync(cancellationToken); + var latestPurchase = await _context.UserPackagePurchases .Where(p => p.UserId == userId) .OrderByDescending(p => p.PurchasedAt) .FirstOrDefaultAsync(cancellationToken); - var package = latestPurchase != null - ? await _context.Packages.FirstOrDefaultAsync(p => p.Id == latestPurchase.PackageId && !p.IsDeleted, cancellationToken) - : await _context.Packages.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken); + Package? package = null; + + if (currentCyclePackageId.HasValue && currentCyclePackageId.Value > 0) + { + package = await _context.Packages + .FirstOrDefaultAsync(p => p.Id == currentCyclePackageId.Value && !p.IsDeleted, cancellationToken); + + if (package != null) + { + _logger.LogInformation( + "AcceptContract package source: CurrentCycle (UserId={UserId}, PackageId={PackageId})", + userId, + package.Id); + } + } + + if (package == null && latestPurchase != null) + { + package = await _context.Packages + .FirstOrDefaultAsync(p => p.Id == latestPurchase.PackageId && !p.IsDeleted, cancellationToken); + + if (package != null) + { + _logger.LogInformation( + "AcceptContract package source: LatestPurchase (UserId={UserId}, PackageId={PackageId})", + userId, + package.Id); + } + } + + if (package == null) + { + package = await _context.Packages + .FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken); + + if (package != null) + { + _logger.LogInformation( + "AcceptContract package source: BasePackage (UserId={UserId}, PackageId={PackageId})", + userId, + package.Id); + } + } if (package == null) throw new NotFoundException("پکیج یافت نشد"); diff --git a/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/ActivateClubMembership/ActivateClubMembershipCommandHandler.cs b/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/ActivateClubMembership/ActivateClubMembershipCommandHandler.cs index d3c1c14..15006e1 100644 --- a/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/ActivateClubMembership/ActivateClubMembershipCommandHandler.cs +++ b/src/CMSMicroservice.Application/ClubMembershipCQ/Commands/ActivateClubMembership/ActivateClubMembershipCommandHandler.cs @@ -235,8 +235,9 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler c.UserId == user.Id && c.IsCurrentCycle, cancellationToken); - // اگر چرخه فعال دارد — یعنی Activate قبلاً برای این خرید اجرا شده؛ جلوگیری از ثبت Cycle تکراری - if (hasCurrentCycle) + // اگر چرخه فعال دارد و درخواست Force نیست — احتمال اجرای تکراری همان خرید + // در حالت ForceActivation (مثل پرداخت دستی)، باید چرخه جدید ساخته شود تا پکیج جدید ثبت شود. + if (hasCurrentCycle && !request.ForceActivation) { _logger.LogInformation( "User {UserId} already has a running cycle — skipping duplicate activation", diff --git a/src/CMSMicroservice.Application/ManualPaymentCQ/Queries/GetAllManualPayments/GetAllManualPaymentsQueryHandler.cs b/src/CMSMicroservice.Application/ManualPaymentCQ/Queries/GetAllManualPayments/GetAllManualPaymentsQueryHandler.cs index 2a087ba..782fec3 100644 --- a/src/CMSMicroservice.Application/ManualPaymentCQ/Queries/GetAllManualPayments/GetAllManualPaymentsQueryHandler.cs +++ b/src/CMSMicroservice.Application/ManualPaymentCQ/Queries/GetAllManualPayments/GetAllManualPaymentsQueryHandler.cs @@ -70,7 +70,7 @@ public class GetAllManualPaymentsQueryHandler // Pagination var skip = (request.PageNumber - 1) * request.PageSize; - // دریافت PackageName از آخرین خرید پکیج کاربر + // دریافت PackageName پیش‌فرض از آخرین خرید پکیج کاربر (fallback برای داده‌های قدیمی) var userPackageNames = await _context.UserPackagePurchases .Include(p => p.Package) .GroupBy(p => p.UserId) @@ -103,12 +103,45 @@ public class GetAllManualPaymentsQueryHandler Created = m.Created }) .ToListAsync(cancellationToken); + + // PackageName دقیق هر پرداخت دستی از UserWalletHistories بر اساس TransactionId همان پرداخت + var transactionIds = data + .Where(x => x.TransactionId.HasValue) + .Select(x => x.TransactionId!.Value) + .Distinct() + .ToList(); + + var packageNamesByTransaction = new Dictionary(); + if (transactionIds.Count > 0) + { + packageNamesByTransaction = await _context.UserWalletHistories + .AsNoTracking() + .Include(h => h.Package) + .Where(h => h.RefrenceId.HasValue + && transactionIds.Contains(h.RefrenceId.Value) + && h.PackageId.HasValue) + .GroupBy(h => h.RefrenceId!.Value) + .Select(g => new + { + TransactionId = g.Key, + PackageName = g.OrderByDescending(x => x.Created) + .Select(x => x.Package != null ? x.Package.Title : string.Empty) + .FirstOrDefault() + }) + .ToDictionaryAsync(x => x.TransactionId, x => x.PackageName ?? string.Empty, cancellationToken); + } // تکمیل PackageName foreach (var item in data) { - if (userPackageNames.TryGetValue(item.UserId, out var pkgName)) + if (item.TransactionId.HasValue && packageNamesByTransaction.TryGetValue(item.TransactionId.Value, out var txPkgName)) + { + item.PackageName = txPkgName; + } + else if (userPackageNames.TryGetValue(item.UserId, out var pkgName)) + { item.PackageName = pkgName; + } } var metaData = new MetaData