feat: add IsActive field to UserClubFeatures for admin management

This commit is contained in:
masoodafar-web
2025-12-12 01:40:26 +03:30
parent aa66ca10c8
commit ff1c1d5d61
68 changed files with 11456 additions and 198 deletions
@@ -11,11 +11,19 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
public async Task<long> Handle(CalculateWeeklyCommissionPoolCommand request, CancellationToken cancellationToken)
{
// بررسی وجود استخر قبلی
// بررسی وجود استخر
var existingPool = await _context.WeeklyCommissionPools
.FirstOrDefaultAsync(x => x.WeekNumber == request.WeekNumber, cancellationToken);
if (existingPool != null && existingPool.IsCalculated && !request.ForceRecalculate)
if (existingPool == null)
{
throw new InvalidOperationException(
$"Pool هفته {request.WeekNumber} وجود ندارد. " +
"Pool باید در هنگام فعالسازی باشگاه مشتریان ایجاد شده باشد"
);
}
if (existingPool.IsCalculated && !request.ForceRecalculate)
{
throw new InvalidOperationException($"استخر کمیسیون هفته {request.WeekNumber} قبلاً محاسبه شده است");
}
@@ -30,48 +38,122 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
throw new InvalidOperationException($"تعادل‌های هفته {request.WeekNumber} هنوز محاسبه نشده است. ابتدا CalculateWeeklyBalances را اجرا کنید");
}
// محاسبه مجموع مشارکت‌ها در استخر
var totalPoolAmount = weeklyBalances.Sum(x => x.WeeklyPoolContribution);
// ⭐ Pool از قبل پُر شده (توسط ActivateClubMembership)
var totalPoolAmount = existingPool.TotalPoolAmount;
// محاسبه مجموع Balances
var totalBalances = weeklyBalances.Sum(x => x.TotalBalances);
// محاسبه مجموع تعادل‌های کل شبکه
// نکته: SubordinateBalances اضافه نمی‌کنیم چون وقتی همه TotalBalances رو جمع می‌زنیم،
// خودش شامل بالانس‌های زیرمجموعه‌ها هم هست (تکراری نشه)
var totalBalancesInNetwork = weeklyBalances.Sum(x => x.TotalBalances);
// محاسبه ارزش هر Balance (تقسیم صحیح برای ریال)
// محاسبه ارزش هر امتیاز
long valuePerBalance = 0;
if (totalBalances > 0)
if (totalBalancesInNetwork > 0)
{
valuePerBalance = totalPoolAmount / totalBalances;
valuePerBalance = totalPoolAmount / totalBalancesInNetwork;
}
if (existingPool != null)
{
// به‌روزرسانی
existingPool.TotalPoolAmount = totalPoolAmount;
existingPool.TotalBalances = totalBalances;
existingPool.ValuePerBalance = valuePerBalance;
existingPool.IsCalculated = true;
existingPool.CalculatedAt = DateTime.UtcNow;
// به‌روزرسانی Pool
existingPool.TotalBalances = totalBalancesInNetwork;
existingPool.ValuePerBalance = valuePerBalance;
existingPool.IsCalculated = true;
existingPool.CalculatedAt = DateTime.Now;
_context.WeeklyCommissionPools.Update(existingPool);
}
else
_context.WeeklyCommissionPools.Update(existingPool);
await _context.SaveChangesAsync(cancellationToken);
// حذف پرداخت‌های قبلی در صورت ForceRecalculate
if (request.ForceRecalculate)
{
// ایجاد جدید
var pool = new WeeklyCommissionPool
var oldPayouts = await _context.UserCommissionPayouts
.Where(p => p.WeekNumber == request.WeekNumber)
.ToListAsync(cancellationToken);
if (oldPayouts.Any())
{
var oldPayoutIds = oldPayouts.Select(p => p.Id).ToList();
// ⭐ اول باید تاریخچه‌ها حذف بشن (به خاطر FK constraint)
var oldHistories = await _context.CommissionPayoutHistories
.Where(h => oldPayoutIds.Contains(h.UserCommissionPayoutId))
.ToListAsync(cancellationToken);
if (oldHistories.Any())
{
_context.CommissionPayoutHistories.RemoveRange(oldHistories);
}
// بعد پرداخت‌ها حذف می‌شن
_context.UserCommissionPayouts.RemoveRange(oldPayouts);
await _context.SaveChangesAsync(cancellationToken);
}
}
// ⭐ ثبت پرداخت برای کاربرانی که تعادل دارند
// تعادل شخصی + زیرمجموعه قبلاً در CalculateWeeklyBalances محاسبه شده
var payouts = new List<UserCommissionPayout>();
foreach (var balance in weeklyBalances)
{
// فقط تعادل شخصی (SubordinateBalances اضافه نمی‌شه چون در SUM کل شبکه خودش حساب میشه)
var userBalance = balance.TotalBalances;
// اگر تعادل صفر است، نیازی به ثبت نیست
if (userBalance <= 0)
{
continue;
}
// محاسبه مبلغ کمیسیون
var totalAmount = (long)(userBalance * valuePerBalance);
var payout = new UserCommissionPayout
{
UserId = balance.UserId,
WeekNumber = request.WeekNumber,
TotalPoolAmount = totalPoolAmount,
TotalBalances = totalBalances,
WeeklyPoolId = existingPool.Id,
BalancesEarned = userBalance,
ValuePerBalance = valuePerBalance,
IsCalculated = true,
CalculatedAt = DateTime.UtcNow
TotalAmount = totalAmount,
Status = CommissionPayoutStatus.Pending,
PaidAt = null,
WithdrawalMethod = null,
IbanNumber = null,
WithdrawnAt = null
};
await _context.WeeklyCommissionPools.AddAsync(pool, cancellationToken);
existingPool = pool;
payouts.Add(payout);
}
await _context.SaveChangesAsync(cancellationToken);
if (payouts.Any())
{
await _context.UserCommissionPayouts.AddRangeAsync(payouts, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
// ثبت تاریخچه برای هر پرداخت
var historyList = new List<CommissionPayoutHistory>();
foreach (var payout in payouts)
{
var history = new CommissionPayoutHistory
{
UserCommissionPayoutId = payout.Id,
UserId = payout.UserId,
WeekNumber = request.WeekNumber,
AmountBefore = 0,
AmountAfter = payout.TotalAmount,
OldStatus = default(CommissionPayoutStatus),
NewStatus = CommissionPayoutStatus.Pending,
Action = CommissionPayoutAction.Created,
PerformedBy = "System",
Reason = "پردازش خودکار کمیسیون هفتگی"
};
historyList.Add(history);
}
await _context.CommissionPayoutHistories.AddRangeAsync(historyList, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
}
return existingPool.Id;
}