Phase 5: Per-package commission + golden ref cleanup
- Fix golden/طلایی string refs in user-facing messages (ActivateClubMembership) - Rename HasPurchasedGoldenPackage → HasPurchasedPackage (DTO, Handler, Proto, Mapping) - ORM commission: per-user-package calculation via ClubMembership.LastPackageId - Build userPackageMap, per-user maxBalancesPerLeg/maxNetworkLevel - Carryover keyed by (UserId, PackageId) tuple - SP commission: loop over packages, pass @PackageId/@InputMaxBalancesPerLeg/@InputMaxNetworkLevel - sp_CalculateWeeklyBalances: accept 3 new params, filter by PackageId, insert PackageId column
This commit is contained in:
+40
-25
@@ -62,10 +62,20 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||
.Select(w => w.UserId)
|
||||
.ToHashSetAsync(cancellationToken);
|
||||
|
||||
var activeClubMemberUserIds = await _context.ClubMemberships
|
||||
// دریافت عضویتهای فعال به همراه PackageId هر کاربر
|
||||
var activeClubMemberships = await _context.ClubMemberships
|
||||
.Where(c => c.IsActive && !magicModeUserIds.Contains(c.UserId))
|
||||
.Select(c => new { c.UserId, PackageId = c.LastPackageId })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var activeClubMemberUserIds = activeClubMemberships
|
||||
.Select(c => c.UserId)
|
||||
.ToHashSetAsync(cancellationToken);
|
||||
.ToHashSet();
|
||||
|
||||
// نگاشت کاربر → PackageId
|
||||
var userPackageMap = activeClubMemberships
|
||||
.Where(c => c.PackageId.HasValue)
|
||||
.ToDictionary(c => c.UserId, c => c.PackageId!.Value);
|
||||
|
||||
// دریافت کاربران فعال در شبکه که عضو باشگاه هستند
|
||||
var usersInNetwork = await _context.Users
|
||||
@@ -73,43 +83,52 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||
.Select(x => new { x.Id })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
// دریافت باقیماندههای هفته قبل
|
||||
// بارگذاری همه پکیجهای فعال (bulk load)
|
||||
var allPackages = await _context.Packages
|
||||
.Where(p => !p.IsDeleted)
|
||||
.ToDictionaryAsync(p => p.Id, cancellationToken);
|
||||
|
||||
// پکیج پیشفرض (fallback برای کاربرانی که PackageId ندارند)
|
||||
var defaultPackage = allPackages.Values
|
||||
.FirstOrDefault(p => p.IsBasePackage)
|
||||
?? throw new InvalidOperationException("پکیج پایه یافت نشد");
|
||||
|
||||
// دریافت باقیماندههای هفته قبل — شامل PackageId
|
||||
var previousWeekDefinitionId = GetPreviousWeekDefinitionId(weekDefinitionId);
|
||||
Dictionary<long, (int LeftLegRemainder, int RightLegRemainder)> previousWeekCarryovers;
|
||||
Dictionary<(long UserId, long PackageId), (int LeftLegRemainder, int RightLegRemainder)> previousWeekCarryovers;
|
||||
|
||||
if (previousWeekDefinitionId.HasValue)
|
||||
{
|
||||
previousWeekCarryovers = await _context.NetworkWeeklyBalances
|
||||
.Where(x => x.WeekDefinitionId == previousWeekDefinitionId.Value)
|
||||
.ToDictionaryAsync(
|
||||
x => x.UserId,
|
||||
x => (x.UserId, x.PackageId),
|
||||
x => (x.LeftLegRemainder, x.RightLegRemainder),
|
||||
cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
previousWeekCarryovers = new Dictionary<long, (int, int)>();
|
||||
previousWeekCarryovers = new Dictionary<(long, long), (int, int)>();
|
||||
}
|
||||
|
||||
var balancesList = new List<NetworkWeeklyBalance>();
|
||||
var calculatedAt = DateTime.Now;
|
||||
|
||||
// بارگذاری پکیج پایه برای خواندن سقفها
|
||||
var package = await _context.Packages
|
||||
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
|
||||
?? throw new InvalidOperationException("پکیج پایه یافت نشد");
|
||||
var maxBalancesPerLeg = package.MaxBalancesPerLeg;
|
||||
var maxNetworkLevel = package.MaxNetworkLevel;
|
||||
|
||||
foreach (var user in usersInNetwork.OrderBy(o => o.Id))
|
||||
{
|
||||
// دریافت باقیمانده هفته قبل
|
||||
// تعیین پکیج هر کاربر (per-user)
|
||||
var userPackageId = userPackageMap.GetValueOrDefault(user.Id, defaultPackage.Id);
|
||||
var package = allPackages.GetValueOrDefault(userPackageId, defaultPackage);
|
||||
var maxBalancesPerLeg = package.MaxBalancesPerLeg;
|
||||
var maxNetworkLevel = package.MaxNetworkLevel;
|
||||
// دریافت باقیمانده هفته قبل — فیلتر per-package
|
||||
var leftCarryover = 0;
|
||||
var rightCarryover = 0;
|
||||
if (previousWeekCarryovers.ContainsKey(user.Id))
|
||||
var carryoverKey = (UserId: user.Id, PackageId: userPackageId);
|
||||
if (previousWeekCarryovers.ContainsKey(carryoverKey))
|
||||
{
|
||||
leftCarryover = previousWeekCarryovers[user.Id].LeftLegRemainder;
|
||||
rightCarryover = previousWeekCarryovers[user.Id].RightLegRemainder;
|
||||
leftCarryover = previousWeekCarryovers[carryoverKey].LeftLegRemainder;
|
||||
rightCarryover = previousWeekCarryovers[carryoverKey].RightLegRemainder;
|
||||
}
|
||||
|
||||
// محاسبه تعداد اعضای جدید در این هفته (تا maxNetworkLevel لول پایینتر)
|
||||
@@ -166,15 +185,16 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||
await _context.NetworkWeeklyBalances.AddRangeAsync(balancesList, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// محاسبه تعادل زیرمجموعه
|
||||
// محاسبه تعادل زیرمجموعه — per-user maxNetworkLevel
|
||||
var balancesDictionary = balancesList.ToDictionary(x => x.UserId);
|
||||
|
||||
foreach (var balance in balancesList)
|
||||
{
|
||||
var balancePackage = allPackages.GetValueOrDefault(balance.PackageId, defaultPackage);
|
||||
var subordinateBalances = await CalculateSubordinateBalancesAsync(
|
||||
balance.UserId,
|
||||
balancesDictionary,
|
||||
maxNetworkLevel,
|
||||
balancePackage.MaxNetworkLevel,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
@@ -193,11 +213,6 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||
bool forceRecalculate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// بارگذاری پکیج پایه برای تعیین PackageId روی پرداختها
|
||||
var package = await _context.Packages
|
||||
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
|
||||
?? throw new InvalidOperationException("پکیج پایه یافت نشد");
|
||||
|
||||
var weekDefinition = _weekRepository.GetGregorianWeekNumber(weekDefinitionId);
|
||||
if (weekDefinition == null)
|
||||
{
|
||||
@@ -293,7 +308,7 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||
UserId = balance.UserId,
|
||||
WeekDefinitionId = weekDefinitionId,
|
||||
WeeklyPoolId = existingPool.Id,
|
||||
PackageId = package.Id,
|
||||
PackageId = balance.PackageId, // per-user PackageId از محاسبه تعادل
|
||||
BalancesEarned = userBalance,
|
||||
ValuePerBalance = valuePerBalance,
|
||||
TotalAmount = totalAmount,
|
||||
|
||||
Reference in New Issue
Block a user