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:
+3
-3
@@ -64,11 +64,11 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
|
if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
|
||||||
{
|
{
|
||||||
_logger.LogWarning(
|
_logger.LogWarning(
|
||||||
"User {UserId} has not purchased golden package yet",
|
"User {UserId} has not purchased any package yet",
|
||||||
request.UserId
|
request.UserId
|
||||||
);
|
);
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
"برای فعالسازی باشگاه مشتریان ابتدا باید پکیج طلایی خریداری کنید"
|
"برای فعالسازی باشگاه مشتریان ابتدا باید یک پکیج خریداری کنید"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
"No successful package order found for UserId: {UserId}",
|
"No successful package order found for UserId: {UserId}",
|
||||||
request.UserId
|
request.UserId
|
||||||
);
|
);
|
||||||
throw new NotFoundException("سفارش پکیج طلایی یافت نشد");
|
throw new NotFoundException("سفارش پکیج یافت نشد");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. بررسی Transaction
|
// 5. بررسی Transaction
|
||||||
|
|||||||
+1
-1
@@ -143,7 +143,7 @@ public class GetUserNetworkPositionQueryHandler : IRequestHandler<GetUserNetwork
|
|||||||
HasReceivedDayaCredit = user.HasReceivedDayaCredit,
|
HasReceivedDayaCredit = user.HasReceivedDayaCredit,
|
||||||
DayaCreditReceivedAt = user.DayaCreditReceivedAt,
|
DayaCreditReceivedAt = user.DayaCreditReceivedAt,
|
||||||
PackagePurchaseMethod = user.PackagePurchaseMethod,
|
PackagePurchaseMethod = user.PackagePurchaseMethod,
|
||||||
HasPurchasedGoldenPackage = user.PackagePurchaseMethod != PackagePurchaseMethod.None,
|
HasPurchasedPackage = user.PackagePurchaseMethod != PackagePurchaseMethod.None,
|
||||||
|
|
||||||
// آمار مالی
|
// آمار مالی
|
||||||
TotalEarnedCommission = commissionStats?.TotalAmount ?? 0,
|
TotalEarnedCommission = commissionStats?.TotalAmount ?? 0,
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ public class UserNetworkPositionDto
|
|||||||
public bool HasReceivedDayaCredit { get; set; }
|
public bool HasReceivedDayaCredit { get; set; }
|
||||||
public DateTime? DayaCreditReceivedAt { get; set; }
|
public DateTime? DayaCreditReceivedAt { get; set; }
|
||||||
public PackagePurchaseMethod PackagePurchaseMethod { get; set; }
|
public PackagePurchaseMethod PackagePurchaseMethod { get; set; }
|
||||||
public bool HasPurchasedGoldenPackage { get; set; }
|
public bool HasPurchasedPackage { get; set; }
|
||||||
|
|
||||||
// آمار مالی
|
// آمار مالی
|
||||||
public decimal TotalEarnedCommission { get; set; }
|
public decimal TotalEarnedCommission { get; set; }
|
||||||
|
|||||||
+37
-8
@@ -8,6 +8,9 @@
|
|||||||
CREATE OR ALTER PROCEDURE [CMS].[sp_CalculateWeeklyBalances]
|
CREATE OR ALTER PROCEDURE [CMS].[sp_CalculateWeeklyBalances]
|
||||||
@WeekDefinitionId BIGINT,
|
@WeekDefinitionId BIGINT,
|
||||||
@ForceRecalculate BIT = 0,
|
@ForceRecalculate BIT = 0,
|
||||||
|
@PackageId BIGINT = NULL, -- پکیج خاص (اگر NULL از پکیج پایه استفاده میکند)
|
||||||
|
@InputMaxBalancesPerLeg INT = NULL, -- سقف تعادل هر پا (از Package entity)
|
||||||
|
@InputMaxNetworkLevel INT = NULL, -- حداکثر عمق شبکه (از Package entity)
|
||||||
@RowCount INT OUTPUT
|
@RowCount INT OUTPUT
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -18,10 +21,33 @@ BEGIN
|
|||||||
DECLARE @StartDate DATETIME;
|
DECLARE @StartDate DATETIME;
|
||||||
DECLARE @EndDate DATETIME;
|
DECLARE @EndDate DATETIME;
|
||||||
DECLARE @PreviousWeekDefinitionId BIGINT;
|
DECLARE @PreviousWeekDefinitionId BIGINT;
|
||||||
DECLARE @MaxBalancesPerLeg INT = 300;
|
DECLARE @MaxBalancesPerLeg INT;
|
||||||
DECLARE @MaxNetworkLevel INT = 15;
|
DECLARE @MaxNetworkLevel INT;
|
||||||
DECLARE @CalculatedAt DATETIME = GETDATE();
|
DECLARE @CalculatedAt DATETIME = GETDATE();
|
||||||
|
|
||||||
|
-- تعیین PackageId پیشفرض (پکیج پایه)
|
||||||
|
IF @PackageId IS NULL
|
||||||
|
BEGIN
|
||||||
|
SELECT TOP 1 @PackageId = Id
|
||||||
|
FROM CMS.Packages
|
||||||
|
WHERE IsBasePackage = 1 AND IsDeleted = 0;
|
||||||
|
END
|
||||||
|
|
||||||
|
-- خواندن تنظیمات از Package entity اگر پارامتر داده نشده
|
||||||
|
IF @InputMaxBalancesPerLeg IS NOT NULL
|
||||||
|
SET @MaxBalancesPerLeg = @InputMaxBalancesPerLeg;
|
||||||
|
ELSE
|
||||||
|
SELECT @MaxBalancesPerLeg = ISNULL(MaxBalancesPerLeg, 300) FROM CMS.Packages WHERE Id = @PackageId;
|
||||||
|
|
||||||
|
IF @InputMaxNetworkLevel IS NOT NULL
|
||||||
|
SET @MaxNetworkLevel = @InputMaxNetworkLevel;
|
||||||
|
ELSE
|
||||||
|
SELECT @MaxNetworkLevel = ISNULL(MaxNetworkLevel, 15) FROM CMS.Packages WHERE Id = @PackageId;
|
||||||
|
|
||||||
|
-- fallbackهای امن
|
||||||
|
SET @MaxBalancesPerLeg = ISNULL(@MaxBalancesPerLeg, 300);
|
||||||
|
SET @MaxNetworkLevel = ISNULL(@MaxNetworkLevel, 15);
|
||||||
|
|
||||||
BEGIN TRY
|
BEGIN TRY
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
@@ -65,11 +91,9 @@ BEGIN
|
|||||||
AND IsActive = 1;
|
AND IsActive = 1;
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 4. مقادیر ثابت (Hardcoded - از SystemConstants)
|
-- 4. تنظیمات پکیج (از پارامترها خوانده میشود)
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- این مقادیر ثابت هستند و تغییر نمیکنند
|
-- @MaxBalancesPerLeg و @MaxNetworkLevel قبلاً مقداردهی شدهاند
|
||||||
SET @MaxBalancesPerLeg = 300; -- سقف تعادل هر پا
|
|
||||||
SET @MaxNetworkLevel = 15; -- حداکثر عمق شبکه
|
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 5. ایجاد جدول موقت برای نتایج
|
-- 5. ایجاد جدول موقت برای نتایج
|
||||||
@@ -96,7 +120,8 @@ BEGIN
|
|||||||
INSERT INTO #Balances (UserId)
|
INSERT INTO #Balances (UserId)
|
||||||
SELECT DISTINCT u.Id
|
SELECT DISTINCT u.Id
|
||||||
FROM CMS.Users u
|
FROM CMS.Users u
|
||||||
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = u.Id AND cm.IsActive = 1;
|
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = u.Id AND cm.IsActive = 1
|
||||||
|
WHERE cm.PackageId = @PackageId;
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 7. دریافت باقیمانده هفته قبل
|
-- 7. دریافت باقیمانده هفته قبل
|
||||||
@@ -107,7 +132,9 @@ BEGIN
|
|||||||
SET b.LeftLegCarryover = ISNULL(nb.LeftLegRemainder, 0),
|
SET b.LeftLegCarryover = ISNULL(nb.LeftLegRemainder, 0),
|
||||||
b.RightLegCarryover = ISNULL(nb.RightLegRemainder, 0)
|
b.RightLegCarryover = ISNULL(nb.RightLegRemainder, 0)
|
||||||
FROM #Balances b
|
FROM #Balances b
|
||||||
LEFT JOIN CMS.NetworkWeeklyBalances nb ON nb.UserId = b.UserId AND nb.WeekDefinitionId = @PreviousWeekDefinitionId;
|
LEFT JOIN CMS.NetworkWeeklyBalances nb ON nb.UserId = b.UserId
|
||||||
|
AND nb.WeekDefinitionId = @PreviousWeekDefinitionId
|
||||||
|
AND nb.PackageId = @PackageId;
|
||||||
END
|
END
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
@@ -269,6 +296,7 @@ BEGIN
|
|||||||
INSERT INTO CMS.NetworkWeeklyBalances (
|
INSERT INTO CMS.NetworkWeeklyBalances (
|
||||||
UserId,
|
UserId,
|
||||||
WeekDefinitionId,
|
WeekDefinitionId,
|
||||||
|
PackageId,
|
||||||
LeftLegNewMembers,
|
LeftLegNewMembers,
|
||||||
RightLegNewMembers,
|
RightLegNewMembers,
|
||||||
LeftLegCarryover,
|
LeftLegCarryover,
|
||||||
@@ -295,6 +323,7 @@ BEGIN
|
|||||||
SELECT
|
SELECT
|
||||||
UserId,
|
UserId,
|
||||||
@WeekDefinitionId,
|
@WeekDefinitionId,
|
||||||
|
@PackageId,
|
||||||
LeftLegNewMembers,
|
LeftLegNewMembers,
|
||||||
RightLegNewMembers,
|
RightLegNewMembers,
|
||||||
LeftLegCarryover,
|
LeftLegCarryover,
|
||||||
|
|||||||
+40
-25
@@ -62,10 +62,20 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
|||||||
.Select(w => w.UserId)
|
.Select(w => w.UserId)
|
||||||
.ToHashSetAsync(cancellationToken);
|
.ToHashSetAsync(cancellationToken);
|
||||||
|
|
||||||
var activeClubMemberUserIds = await _context.ClubMemberships
|
// دریافت عضویتهای فعال به همراه PackageId هر کاربر
|
||||||
|
var activeClubMemberships = await _context.ClubMemberships
|
||||||
.Where(c => c.IsActive && !magicModeUserIds.Contains(c.UserId))
|
.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)
|
.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
|
var usersInNetwork = await _context.Users
|
||||||
@@ -73,43 +83,52 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
|||||||
.Select(x => new { x.Id })
|
.Select(x => new { x.Id })
|
||||||
.ToListAsync(cancellationToken);
|
.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);
|
var previousWeekDefinitionId = GetPreviousWeekDefinitionId(weekDefinitionId);
|
||||||
Dictionary<long, (int LeftLegRemainder, int RightLegRemainder)> previousWeekCarryovers;
|
Dictionary<(long UserId, long PackageId), (int LeftLegRemainder, int RightLegRemainder)> previousWeekCarryovers;
|
||||||
|
|
||||||
if (previousWeekDefinitionId.HasValue)
|
if (previousWeekDefinitionId.HasValue)
|
||||||
{
|
{
|
||||||
previousWeekCarryovers = await _context.NetworkWeeklyBalances
|
previousWeekCarryovers = await _context.NetworkWeeklyBalances
|
||||||
.Where(x => x.WeekDefinitionId == previousWeekDefinitionId.Value)
|
.Where(x => x.WeekDefinitionId == previousWeekDefinitionId.Value)
|
||||||
.ToDictionaryAsync(
|
.ToDictionaryAsync(
|
||||||
x => x.UserId,
|
x => (x.UserId, x.PackageId),
|
||||||
x => (x.LeftLegRemainder, x.RightLegRemainder),
|
x => (x.LeftLegRemainder, x.RightLegRemainder),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
previousWeekCarryovers = new Dictionary<long, (int, int)>();
|
previousWeekCarryovers = new Dictionary<(long, long), (int, int)>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var balancesList = new List<NetworkWeeklyBalance>();
|
var balancesList = new List<NetworkWeeklyBalance>();
|
||||||
var calculatedAt = DateTime.Now;
|
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))
|
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 leftCarryover = 0;
|
||||||
var rightCarryover = 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;
|
leftCarryover = previousWeekCarryovers[carryoverKey].LeftLegRemainder;
|
||||||
rightCarryover = previousWeekCarryovers[user.Id].RightLegRemainder;
|
rightCarryover = previousWeekCarryovers[carryoverKey].RightLegRemainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// محاسبه تعداد اعضای جدید در این هفته (تا maxNetworkLevel لول پایینتر)
|
// محاسبه تعداد اعضای جدید در این هفته (تا maxNetworkLevel لول پایینتر)
|
||||||
@@ -166,15 +185,16 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
|||||||
await _context.NetworkWeeklyBalances.AddRangeAsync(balancesList, cancellationToken);
|
await _context.NetworkWeeklyBalances.AddRangeAsync(balancesList, cancellationToken);
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// محاسبه تعادل زیرمجموعه
|
// محاسبه تعادل زیرمجموعه — per-user maxNetworkLevel
|
||||||
var balancesDictionary = balancesList.ToDictionary(x => x.UserId);
|
var balancesDictionary = balancesList.ToDictionary(x => x.UserId);
|
||||||
|
|
||||||
foreach (var balance in balancesList)
|
foreach (var balance in balancesList)
|
||||||
{
|
{
|
||||||
|
var balancePackage = allPackages.GetValueOrDefault(balance.PackageId, defaultPackage);
|
||||||
var subordinateBalances = await CalculateSubordinateBalancesAsync(
|
var subordinateBalances = await CalculateSubordinateBalancesAsync(
|
||||||
balance.UserId,
|
balance.UserId,
|
||||||
balancesDictionary,
|
balancesDictionary,
|
||||||
maxNetworkLevel,
|
balancePackage.MaxNetworkLevel,
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -193,11 +213,6 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
|||||||
bool forceRecalculate,
|
bool forceRecalculate,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// بارگذاری پکیج پایه برای تعیین PackageId روی پرداختها
|
|
||||||
var package = await _context.Packages
|
|
||||||
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
|
|
||||||
?? throw new InvalidOperationException("پکیج پایه یافت نشد");
|
|
||||||
|
|
||||||
var weekDefinition = _weekRepository.GetGregorianWeekNumber(weekDefinitionId);
|
var weekDefinition = _weekRepository.GetGregorianWeekNumber(weekDefinitionId);
|
||||||
if (weekDefinition == null)
|
if (weekDefinition == null)
|
||||||
{
|
{
|
||||||
@@ -293,7 +308,7 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
|
|||||||
UserId = balance.UserId,
|
UserId = balance.UserId,
|
||||||
WeekDefinitionId = weekDefinitionId,
|
WeekDefinitionId = weekDefinitionId,
|
||||||
WeeklyPoolId = existingPool.Id,
|
WeeklyPoolId = existingPool.Id,
|
||||||
PackageId = package.Id,
|
PackageId = balance.PackageId, // per-user PackageId از محاسبه تعادل
|
||||||
BalancesEarned = userBalance,
|
BalancesEarned = userBalance,
|
||||||
ValuePerBalance = valuePerBalance,
|
ValuePerBalance = valuePerBalance,
|
||||||
TotalAmount = totalAmount,
|
TotalAmount = totalAmount,
|
||||||
|
|||||||
+40
-3
@@ -6,6 +6,7 @@ namespace CMSMicroservice.Infrastructure.Services.Commission;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// پیادهسازی محاسبه کمیسیون با استفاده از Stored Procedure
|
/// پیادهسازی محاسبه کمیسیون با استفاده از Stored Procedure
|
||||||
/// این روش برای دادههای زیاد بهینهتر است و از CTE استفاده میکند
|
/// این روش برای دادههای زیاد بهینهتر است و از CTE استفاده میکند
|
||||||
|
/// حلقه روی پکیجهای فعال — هر پکیج با تنظیمات خودش
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StoredProcedureCommissionCalculationStrategy : ICommissionCalculationStrategy
|
public class StoredProcedureCommissionCalculationStrategy : ICommissionCalculationStrategy
|
||||||
{
|
{
|
||||||
@@ -22,34 +23,67 @@ public class StoredProcedureCommissionCalculationStrategy : ICommissionCalculati
|
|||||||
bool forceRecalculate,
|
bool forceRecalculate,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// دسترسی به DbContext واقعی برای اجرای SP
|
|
||||||
var dbContext = _context as DbContext;
|
var dbContext = _context as DbContext;
|
||||||
if (dbContext == null)
|
if (dbContext == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("DbContext برای اجرای Stored Procedure در دسترس نیست");
|
throw new InvalidOperationException("DbContext برای اجرای Stored Procedure در دسترس نیست");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// بارگذاری پکیجهای فعال
|
||||||
|
var activePackages = await _context.Packages
|
||||||
|
.Where(p => !p.IsDeleted && p.IsActive)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!activePackages.Any())
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("هیچ پکیج فعالی یافت نشد");
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalRowCount = 0;
|
||||||
|
|
||||||
var connection = dbContext.Database.GetDbConnection();
|
var connection = dbContext.Database.GetDbConnection();
|
||||||
await connection.OpenAsync(cancellationToken);
|
await connection.OpenAsync(cancellationToken);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
// حلقه روی پکیجها — هر پکیج با تنظیمات خودش
|
||||||
|
foreach (var package in activePackages)
|
||||||
{
|
{
|
||||||
using var command = connection.CreateCommand();
|
using var command = connection.CreateCommand();
|
||||||
command.CommandText = "CMS.sp_CalculateWeeklyBalances";
|
command.CommandText = "CMS.sp_CalculateWeeklyBalances";
|
||||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||||
command.CommandTimeout = 300; // 5 دقیقه timeout
|
command.CommandTimeout = 300; // 5 دقیقه timeout
|
||||||
|
|
||||||
// پارامترها
|
// پارامتر WeekDefinitionId
|
||||||
var paramWeekDefinitionId = command.CreateParameter();
|
var paramWeekDefinitionId = command.CreateParameter();
|
||||||
paramWeekDefinitionId.ParameterName = "@WeekDefinitionId";
|
paramWeekDefinitionId.ParameterName = "@WeekDefinitionId";
|
||||||
paramWeekDefinitionId.Value = weekDefinitionId;
|
paramWeekDefinitionId.Value = weekDefinitionId;
|
||||||
command.Parameters.Add(paramWeekDefinitionId);
|
command.Parameters.Add(paramWeekDefinitionId);
|
||||||
|
|
||||||
|
// پارامتر ForceRecalculate
|
||||||
var paramForceRecalculate = command.CreateParameter();
|
var paramForceRecalculate = command.CreateParameter();
|
||||||
paramForceRecalculate.ParameterName = "@ForceRecalculate";
|
paramForceRecalculate.ParameterName = "@ForceRecalculate";
|
||||||
paramForceRecalculate.Value = forceRecalculate;
|
paramForceRecalculate.Value = forceRecalculate;
|
||||||
command.Parameters.Add(paramForceRecalculate);
|
command.Parameters.Add(paramForceRecalculate);
|
||||||
|
|
||||||
|
// پارامتر PackageId — per-package
|
||||||
|
var paramPackageId = command.CreateParameter();
|
||||||
|
paramPackageId.ParameterName = "@PackageId";
|
||||||
|
paramPackageId.Value = package.Id;
|
||||||
|
command.Parameters.Add(paramPackageId);
|
||||||
|
|
||||||
|
// پارامتر MaxBalancesPerLeg — per-package
|
||||||
|
var paramMaxBalances = command.CreateParameter();
|
||||||
|
paramMaxBalances.ParameterName = "@InputMaxBalancesPerLeg";
|
||||||
|
paramMaxBalances.Value = package.MaxBalancesPerLeg;
|
||||||
|
command.Parameters.Add(paramMaxBalances);
|
||||||
|
|
||||||
|
// پارامتر MaxNetworkLevel — per-package
|
||||||
|
var paramMaxLevel = command.CreateParameter();
|
||||||
|
paramMaxLevel.ParameterName = "@InputMaxNetworkLevel";
|
||||||
|
paramMaxLevel.Value = package.MaxNetworkLevel;
|
||||||
|
command.Parameters.Add(paramMaxLevel);
|
||||||
|
|
||||||
// پارامتر خروجی
|
// پارامتر خروجی
|
||||||
var paramRowCount = command.CreateParameter();
|
var paramRowCount = command.CreateParameter();
|
||||||
paramRowCount.ParameterName = "@RowCount";
|
paramRowCount.ParameterName = "@RowCount";
|
||||||
@@ -60,7 +94,10 @@ public class StoredProcedureCommissionCalculationStrategy : ICommissionCalculati
|
|||||||
await command.ExecuteNonQueryAsync(cancellationToken);
|
await command.ExecuteNonQueryAsync(cancellationToken);
|
||||||
|
|
||||||
var rowCount = (int)(paramRowCount.Value ?? 0);
|
var rowCount = (int)(paramRowCount.Value ?? 0);
|
||||||
return rowCount;
|
totalRowCount += rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalRowCount;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ message GetUserNetworkResponse
|
|||||||
bool has_received_daya_credit = 32;
|
bool has_received_daya_credit = 32;
|
||||||
google.protobuf.Timestamp daya_credit_received_at = 33;
|
google.protobuf.Timestamp daya_credit_received_at = 33;
|
||||||
int32 package_purchase_method = 34;
|
int32 package_purchase_method = 34;
|
||||||
bool has_purchased_golden_package = 35;
|
bool has_purchased_package = 35;
|
||||||
|
|
||||||
// آمار مالی
|
// آمار مالی
|
||||||
double total_earned_commission = 36;
|
double total_earned_commission = 36;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class NetworkMembershipProfile : IRegister
|
|||||||
.Map(dest => dest.MaxNetworkDepth, src => src.MaxNetworkDepth)
|
.Map(dest => dest.MaxNetworkDepth, src => src.MaxNetworkDepth)
|
||||||
.Map(dest => dest.HasReceivedDayaCredit, src => src.HasReceivedDayaCredit)
|
.Map(dest => dest.HasReceivedDayaCredit, src => src.HasReceivedDayaCredit)
|
||||||
.Map(dest => dest.PackagePurchaseMethod, src => (int)src.PackagePurchaseMethod)
|
.Map(dest => dest.PackagePurchaseMethod, src => (int)src.PackagePurchaseMethod)
|
||||||
.Map(dest => dest.HasPurchasedGoldenPackage, src => src.HasPurchasedGoldenPackage)
|
.Map(dest => dest.HasPurchasedPackage, src => src.HasPurchasedPackage)
|
||||||
.Map(dest => dest.TotalEarnedCommission, src => (double)src.TotalEarnedCommission)
|
.Map(dest => dest.TotalEarnedCommission, src => (double)src.TotalEarnedCommission)
|
||||||
.Map(dest => dest.TotalPaidCommission, src => (double)src.TotalPaidCommission)
|
.Map(dest => dest.TotalPaidCommission, src => (double)src.TotalPaidCommission)
|
||||||
.Map(dest => dest.PendingCommission, src => (double)src.PendingCommission)
|
.Map(dest => dest.PendingCommission, src => (double)src.PendingCommission)
|
||||||
|
|||||||
Reference in New Issue
Block a user