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);
|
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
|
var latestPurchase = await _context.UserPackagePurchases
|
||||||
.Where(p => p.UserId == userId)
|
.Where(p => p.UserId == userId)
|
||||||
.OrderByDescending(p => p.PurchasedAt)
|
.OrderByDescending(p => p.PurchasedAt)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
var package = latestPurchase != null
|
Package? package = null;
|
||||||
? await _context.Packages.FirstOrDefaultAsync(p => p.Id == latestPurchase.PackageId && !p.IsDeleted, cancellationToken)
|
|
||||||
: await _context.Packages.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken);
|
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)
|
if (package == null)
|
||||||
throw new NotFoundException("پکیج یافت نشد");
|
throw new NotFoundException("پکیج یافت نشد");
|
||||||
|
|||||||
+3
-2
@@ -235,8 +235,9 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
var hasCurrentCycle = await _context.ClubMembershipCycles
|
var hasCurrentCycle = await _context.ClubMembershipCycles
|
||||||
.AnyAsync(c => c.UserId == user.Id && c.IsCurrentCycle, cancellationToken);
|
.AnyAsync(c => c.UserId == user.Id && c.IsCurrentCycle, cancellationToken);
|
||||||
|
|
||||||
// اگر چرخه فعال دارد — یعنی Activate قبلاً برای این خرید اجرا شده؛ جلوگیری از ثبت Cycle تکراری
|
// اگر چرخه فعال دارد و درخواست Force نیست — احتمال اجرای تکراری همان خرید
|
||||||
if (hasCurrentCycle)
|
// در حالت ForceActivation (مثل پرداخت دستی)، باید چرخه جدید ساخته شود تا پکیج جدید ثبت شود.
|
||||||
|
if (hasCurrentCycle && !request.ForceActivation)
|
||||||
{
|
{
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"User {UserId} already has a running cycle — skipping duplicate activation",
|
"User {UserId} already has a running cycle — skipping duplicate activation",
|
||||||
|
|||||||
+35
-2
@@ -70,7 +70,7 @@ public class GetAllManualPaymentsQueryHandler
|
|||||||
// Pagination
|
// Pagination
|
||||||
var skip = (request.PageNumber - 1) * request.PageSize;
|
var skip = (request.PageNumber - 1) * request.PageSize;
|
||||||
|
|
||||||
// دریافت PackageName از آخرین خرید پکیج کاربر
|
// دریافت PackageName پیشفرض از آخرین خرید پکیج کاربر (fallback برای دادههای قدیمی)
|
||||||
var userPackageNames = await _context.UserPackagePurchases
|
var userPackageNames = await _context.UserPackagePurchases
|
||||||
.Include(p => p.Package)
|
.Include(p => p.Package)
|
||||||
.GroupBy(p => p.UserId)
|
.GroupBy(p => p.UserId)
|
||||||
@@ -103,12 +103,45 @@ public class GetAllManualPaymentsQueryHandler
|
|||||||
Created = m.Created
|
Created = m.Created
|
||||||
})
|
})
|
||||||
.ToListAsync(cancellationToken);
|
.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
|
// تکمیل PackageName
|
||||||
foreach (var item in data)
|
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;
|
item.PackageName = pkgName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var metaData = new MetaData
|
var metaData = new MetaData
|
||||||
|
|||||||
Reference in New Issue
Block a user