feat: improve package retrieval logic in AcceptClubMembershipContract and ActivateClubMembership handlers
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m0s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m0s
This commit is contained in:
+54
-4
@@ -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("پکیج یافت نشد");
|
||||
|
||||
+3
-2
@@ -235,8 +235,9 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
||||
var hasCurrentCycle = await _context.ClubMembershipCycles
|
||||
.AnyAsync(c => 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",
|
||||
|
||||
+35
-2
@@ -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<long, string>();
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user