Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
Build and Deploy to Production / build-and-deploy (push) Has been cancelled
This commit is contained in:
+48
-1
@@ -221,7 +221,54 @@ public class AcceptClubMembershipContractCommandHandler
|
|||||||
_context.ClubMembershipHistories.Add(history);
|
_context.ClubMembershipHistories.Add(history);
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// 9. اضافه کردن مبلغ به Pool هفته جاری
|
// 8.5. آپدیت PackagePurchasedAt سایکل جاری به زمان امضای قرارداد
|
||||||
|
// دلیل: Pool در همین لحظه شارژ میشود — Validation باید به همین هفته اشاره کند
|
||||||
|
// سناریوی cross-week: کاربر هفته ۱۸ پکیج خریده، هفته ۱۹ قرارداد امضا کرده
|
||||||
|
// بدون این Fix: Cycle.PackagePurchasedAt = هفته ۱۸ ولی Pool هفته ۱۹ → اختلاف
|
||||||
|
// با این Fix: Cycle.PackagePurchasedAt = هفته ۱۹ = Pool هفته ۱۹ → درست
|
||||||
|
var currentCycle = await _context.ClubMembershipCycles
|
||||||
|
.FirstOrDefaultAsync(c => c.UserId == userId && c.IsCurrentCycle, cancellationToken);
|
||||||
|
|
||||||
|
if (currentCycle != null)
|
||||||
|
{
|
||||||
|
currentCycle.PackagePurchasedAt = activationDate;
|
||||||
|
_context.ClubMembershipCycles.Update(currentCycle);
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Updated Cycle #{CycleNumber} PackagePurchasedAt to contract-signing time for UserId {UserId}",
|
||||||
|
currentCycle.CycleNumber,
|
||||||
|
userId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// در صورتی که Cycle وجود ندارد (legacy یا مسیر مستقیم AcceptContract)
|
||||||
|
// Cycle را همینجا بساز تا Validation درست کار کند
|
||||||
|
_logger.LogWarning(
|
||||||
|
"No IsCurrentCycle found for UserId {UserId} at AcceptContract — creating Cycle now",
|
||||||
|
userId
|
||||||
|
);
|
||||||
|
|
||||||
|
var maxCycleNumber = await _context.ClubMembershipCycles
|
||||||
|
.Where(c => c.ClubMembershipId == clubMembership.Id)
|
||||||
|
.MaxAsync(c => (int?)c.CycleNumber, cancellationToken) ?? 0;
|
||||||
|
|
||||||
|
var newCycle = new ClubMembershipCycle
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
ClubMembershipId = clubMembership.Id,
|
||||||
|
CycleNumber = maxCycleNumber + 1,
|
||||||
|
PackagePurchasedAt = activationDate,
|
||||||
|
PurchaseMethod = user.PackagePurchaseMethod,
|
||||||
|
PackageAmount = package.Price,
|
||||||
|
PackageId = package.Id,
|
||||||
|
IsCurrentCycle = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.ClubMembershipCycles.Add(newCycle);
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
var currentWeekDefinitionId = GetCurrentWeekDefinitionId();
|
var currentWeekDefinitionId = GetCurrentWeekDefinitionId();
|
||||||
var weeklyPool = await _context.WeeklyCommissionPools
|
var weeklyPool = await _context.WeeklyCommissionPools
|
||||||
.FirstOrDefaultAsync(p => p.WeekDefinitionId == currentWeekDefinitionId && p.PackageId == package.Id, cancellationToken);
|
.FirstOrDefaultAsync(p => p.WeekDefinitionId == currentWeekDefinitionId && p.PackageId == package.Id, cancellationToken);
|
||||||
|
|||||||
+6
@@ -17,4 +17,10 @@ public record ActivateClubMembershipCommand : IRequest<bool>
|
|||||||
/// فعالسازی اجباری توسط ادمین — بدون بررسی سفارش و کیفپول
|
/// فعالسازی اجباری توسط ادمین — بدون بررسی سفارش و کیفپول
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ForceActivation { get; init; }
|
public bool ForceActivation { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج — فقط در ForceActivation استفاده میشود.
|
||||||
|
/// اگر 0 باشد، پکیج پایه (IsBasePackage) استفاده میشود.
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-37
@@ -170,10 +170,19 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// بارگذاری پکیج پایه برای فعالسازی اجباری
|
// بارگذاری پکیج — اگر PackageId مشخص شده همان را لود کن، وگرنه پکیج پایه
|
||||||
package = await _context.Packages
|
if (request.PackageId > 0)
|
||||||
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
|
{
|
||||||
?? throw new NotFoundException("پکیج پایه یافت نشد");
|
package = await _context.Packages
|
||||||
|
.FirstOrDefaultAsync(p => p.Id == request.PackageId && !p.IsDeleted, cancellationToken)
|
||||||
|
?? throw new NotFoundException($"پکیج {request.PackageId} یافت نشد");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
package = await _context.Packages
|
||||||
|
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
|
||||||
|
?? throw new NotFoundException("پکیج پایه یافت نشد");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. بررسی عضویت فعلی
|
// 6. بررسی عضویت فعلی
|
||||||
@@ -226,10 +235,11 @@ 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);
|
||||||
|
|
||||||
if (existingMembership.IsActive && hasCurrentCycle)
|
// اگر چرخه فعال دارد — یعنی Activate قبلاً برای این خرید اجرا شده؛ جلوگیری از ثبت Cycle تکراری
|
||||||
|
if (hasCurrentCycle)
|
||||||
{
|
{
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"User {UserId} is already an active club member with a running cycle",
|
"User {UserId} already has a running cycle — skipping duplicate activation",
|
||||||
user.Id
|
user.Id
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
@@ -307,48 +317,60 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// ⭐ 8. اضافه کردن مبلغ به Pool هفته جاری
|
// ⭐ 8. اضافه کردن مبلغ به Pool هفته جاری
|
||||||
var currentWeekDefinitionId = GetCurrentWeekDefinitionId();
|
// عضو جدید (isNewMembership=true): Pool توسط AcceptClubMembershipContract شارژ میشود
|
||||||
var weeklyPool = await _context.WeeklyCommissionPools
|
// چون کاربر قبل از امضای قرارداد IsActive=false است و قرارداد فقط یکبار امضا میشود.
|
||||||
.FirstOrDefaultAsync(p => p.WeekDefinitionId == currentWeekDefinitionId && p.PackageId == package.Id, cancellationToken);
|
// خرید مجدد (isNewMembership=false): قرارداد مجدد امضا نمیشود — Pool همینجا شارژ میشود.
|
||||||
|
if (!isNewMembership)
|
||||||
if (weeklyPool == null)
|
|
||||||
{
|
{
|
||||||
// ایجاد Pool جدید برای این هفته × این پکیج
|
var currentWeekDefinitionId = GetCurrentWeekDefinitionId();
|
||||||
weeklyPool = new WeeklyCommissionPool
|
var weeklyPool = await _context.WeeklyCommissionPools
|
||||||
|
.FirstOrDefaultAsync(p => p.WeekDefinitionId == currentWeekDefinitionId && p.PackageId == package.Id, cancellationToken);
|
||||||
|
|
||||||
|
if (weeklyPool == null)
|
||||||
{
|
{
|
||||||
WeekDefinitionId = currentWeekDefinitionId,
|
// ایجاد Pool جدید برای این هفته × این پکیج
|
||||||
PackageId = package.Id,
|
weeklyPool = new WeeklyCommissionPool
|
||||||
TotalPoolAmount = activationFeeValue,
|
{
|
||||||
TotalBalances = 0, // در CalculateWeeklyBalances محاسبه میشه
|
WeekDefinitionId = currentWeekDefinitionId,
|
||||||
ValuePerBalance = 0, // در CalculateWeeklyCommissionPool محاسبه میشه
|
PackageId = package.Id,
|
||||||
IsCalculated = false,
|
TotalPoolAmount = activationFeeValue,
|
||||||
CalculatedAt = null
|
TotalBalances = 0,
|
||||||
};
|
ValuePerBalance = 0,
|
||||||
|
IsCalculated = false,
|
||||||
|
CalculatedAt = null
|
||||||
|
};
|
||||||
|
|
||||||
await _context.WeeklyCommissionPools.AddAsync(weeklyPool, cancellationToken);
|
await _context.WeeklyCommissionPools.AddAsync(weeklyPool, cancellationToken);
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Created new WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId} with initial amount: {Amount}",
|
"Created new WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId} with initial amount: {Amount}",
|
||||||
currentWeekDefinitionId,
|
currentWeekDefinitionId,
|
||||||
giftValue
|
activationFeeValue
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weeklyPool.TotalPoolAmount += activationFeeValue;
|
||||||
|
_context.WeeklyCommissionPools.Update(weeklyPool);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Added {Amount} to existing WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId}. New total: {NewTotal}",
|
||||||
|
activationFeeValue,
|
||||||
|
currentWeekDefinitionId,
|
||||||
|
weeklyPool.TotalPoolAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// اضافه کردن به Pool موجود
|
|
||||||
weeklyPool.TotalPoolAmount += activationFeeValue;
|
|
||||||
_context.WeeklyCommissionPools.Update(weeklyPool);
|
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Added {Amount} to existing WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId}. New total: {NewTotal}",
|
"New member — Pool charge deferred to AcceptClubMembershipContract for UserId {UserId}",
|
||||||
activationFeeValue,
|
user.Id
|
||||||
currentWeekDefinitionId,
|
|
||||||
weeklyPool.TotalPoolAmount
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
|
||||||
|
|
||||||
// 9. اعمال ویژگیهای پکیج — DIFF/تفاضل (Q20)
|
// 9. اعمال ویژگیهای پکیج — DIFF/تفاضل (Q20)
|
||||||
await ApplyFeatureDiffAsync(user.Id, entity.Id, package.Id, isNewMembership, activationDate, cancellationToken);
|
await ApplyFeatureDiffAsync(user.Id, entity.Id, package.Id, isNewMembership, activationDate, cancellationToken);
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -266,12 +266,16 @@ public class CalculateWeeklyBalancesCommandHandler : IRequestHandler<CalculateWe
|
|||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
// اگر فرزند در این هفته پکیج خریده (Cycle جدید ساخته شده)، 1 امتیاز
|
// ⭐ بر اساس بازه تاریخی هفته، نه IsCurrentCycle
|
||||||
// ⚠️ از ClubMembershipCycle.PackagePurchasedAt استفاده میکنیم (نه ActivatedAt که overwrite میشد)
|
// IsCurrentCycle فقط آخرین خرید را نشان میدهد — برای تاریخچهای (هفتههای گذشته)
|
||||||
var currentCycle = await _context.ClubMembershipCycles
|
// باید از PackagePurchasedAt استفاده کرد که تاریخ دقیق خرید را نگه میدارد
|
||||||
.FirstOrDefaultAsync(x => x.UserId == child.Id && x.IsCurrentCycle, cancellationToken);
|
var hadCycleInWeek = await _context.ClubMembershipCycles
|
||||||
|
.AnyAsync(x => x.UserId == child.Id
|
||||||
|
&& x.PackagePurchasedAt >= startDate
|
||||||
|
&& x.PackagePurchasedAt <= endDate,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
if (currentCycle?.PackagePurchasedAt >= startDate && currentCycle?.PackagePurchasedAt <= endDate)
|
if (hadCycleInWeek)
|
||||||
{
|
{
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-1
@@ -41,6 +41,61 @@ public class GetWeeklyCommissionPoolQueryHandler : IRequestHandler<GetWeeklyComm
|
|||||||
})
|
})
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
return pool ?? new WeeklyCommissionPoolDto();
|
pool ??= new WeeklyCommissionPoolDto();
|
||||||
|
|
||||||
|
// ── Q29: اعتبارسنجی TotalPoolAmount در برابر فعالسازیهای واقعی ──
|
||||||
|
await ValidatePoolAmountAsync(pool, request, cancellationToken);
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TotalPoolAmount استخر را با تعداد فعالسازیهای ثبتشده (AcceptContract + ActivateClubMembership) مقایسه میکند.
|
||||||
|
/// نتیجه در فیلدهای Validation... ذخیره میشود.
|
||||||
|
/// </summary>
|
||||||
|
private async Task ValidatePoolAmountAsync(WeeklyCommissionPoolDto pool, GetWeeklyCommissionPoolQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var packageId = pool.PackageId > 0 ? pool.PackageId : request.PackageId;
|
||||||
|
if (packageId is null or 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var weekDef = _weekDefinitionRepository.GetWeekById(request.WeekDefinitionId);
|
||||||
|
if (weekDef is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var activationFee = await _context.Packages
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(p => p.Id == packageId.Value)
|
||||||
|
.Select(p => p.ActivationFee)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (activationFee <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// شمارش Cycleهایی که Pool آنها واقعاً شارژ شده:
|
||||||
|
// - عضو جدید: Pool توسط AcceptContract شارژ میشود → UserContract وجود دارد
|
||||||
|
// - خرید مجدد: Pool در ActivateClubMembership شارژ میشود → IsCurrentCycle نبوده (قبلاً active بوده)
|
||||||
|
// - نباید از IsActive استفاده شود: وضعیت تاریخی نیست (عضو ممکن است بعداً غیرفعال شده باشد)
|
||||||
|
//
|
||||||
|
// قانون: Cycle شارژ شده = یا قرارداد دارد (عضو جدید) یا IsActive قبلاً true بوده (خرید مجدد)
|
||||||
|
// سادهترین معادل: Cycle هایی که ClubMembership.ActivatedAt در بازه هفته است (زمان واقعی شارژ Pool)
|
||||||
|
var totalActivations = await _context.ClubMembershipCycles
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(c => c.PackageId == packageId.Value
|
||||||
|
&& c.PackagePurchasedAt >= weekDef.StartDate
|
||||||
|
&& c.PackagePurchasedAt < weekDef.EndDate
|
||||||
|
&& _context.UserContracts.Any(uc =>
|
||||||
|
uc.UserId == c.UserId
|
||||||
|
&& _context.Contracts.Any(con =>
|
||||||
|
con.Id == uc.ContractId
|
||||||
|
&& con.Type == ContractType.ClubMembership)))
|
||||||
|
.CountAsync(cancellationToken);
|
||||||
|
|
||||||
|
var expectedAmount = (long)totalActivations * activationFee;
|
||||||
|
|
||||||
|
pool.ValidationActivationCount = totalActivations;
|
||||||
|
pool.ValidationExpectedAmount = expectedAmount;
|
||||||
|
pool.ValidationDiscrepancy = pool.TotalPoolAmount - expectedAmount;
|
||||||
|
pool.ValidationIsValid = pool.TotalPoolAmount == expectedAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -16,4 +16,14 @@ public class WeeklyCommissionPoolDto
|
|||||||
public DateTimeOffset Created { get; set; }
|
public DateTimeOffset Created { get; set; }
|
||||||
public long PackageId { get; set; }
|
public long PackageId { get; set; }
|
||||||
public string PackageTitle { get; set; } = string.Empty;
|
public string PackageTitle { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
// ── Validation Fields (Q29) ──
|
||||||
|
/// <summary>آیا TotalPoolAmount با تعداد فعالسازیهای ثبتشده در دیتابیس مطابقت دارد؟</summary>
|
||||||
|
public bool ValidationIsValid { get; set; } = true;
|
||||||
|
/// <summary>مبلغ مورد انتظار بر اساس شمارش فعالسازیها × ActivationFee</summary>
|
||||||
|
public long ValidationExpectedAmount { get; set; }
|
||||||
|
/// <summary>اختلاف: TotalPoolAmount - ValidationExpectedAmount</summary>
|
||||||
|
public long ValidationDiscrepancy { get; set; }
|
||||||
|
/// <summary>تعداد فعالسازیهای شناساییشده برای این هفته و پکیج</summary>
|
||||||
|
public int ValidationActivationCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -1,3 +1,4 @@
|
|||||||
|
using CMSMicroservice.Application.ClubMembershipCQ.Commands.ActivateClubMembership;
|
||||||
using CMSMicroservice.Application.Common.Exceptions;
|
using CMSMicroservice.Application.Common.Exceptions;
|
||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Domain.Common;
|
using CMSMicroservice.Domain.Common;
|
||||||
@@ -14,15 +15,18 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
|
|||||||
{
|
{
|
||||||
private readonly IApplicationDbContext _context;
|
private readonly IApplicationDbContext _context;
|
||||||
private readonly ICurrentUserService _currentUser;
|
private readonly ICurrentUserService _currentUser;
|
||||||
|
private readonly ISender _sender;
|
||||||
private readonly ILogger<CreateManualPaymentCommandHandler> _logger;
|
private readonly ILogger<CreateManualPaymentCommandHandler> _logger;
|
||||||
|
|
||||||
public CreateManualPaymentCommandHandler(
|
public CreateManualPaymentCommandHandler(
|
||||||
IApplicationDbContext context,
|
IApplicationDbContext context,
|
||||||
ICurrentUserService currentUser,
|
ICurrentUserService currentUser,
|
||||||
|
ISender sender,
|
||||||
ILogger<CreateManualPaymentCommandHandler> logger)
|
ILogger<CreateManualPaymentCommandHandler> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
|
_sender = sender;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +156,29 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
|
|||||||
// 10. ذخیره همه تغییرات
|
// 10. ذخیره همه تغییرات
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
// 11. فعالسازی باشگاه مشتریان — ساخت Cycle و آمادهسازی برای AcceptContract
|
||||||
|
// این مرحله تضمین میکند که:
|
||||||
|
// الف) ClubMembershipCycle ساخته شود تا والدین امتیاز «عضو جدید» بگیرند
|
||||||
|
// ب) Pool توسط AcceptContract (که کاربر در FO امضا میکند) شارژ شود
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _sender.Send(new ActivateClubMembershipCommand
|
||||||
|
{
|
||||||
|
UserId = request.UserId,
|
||||||
|
ForceActivation = true,
|
||||||
|
PackageId = package.Id
|
||||||
|
}, cancellationToken);
|
||||||
|
}
|
||||||
|
catch (Exception activateEx)
|
||||||
|
{
|
||||||
|
// عضویت باشگاه اختیاری است — خطا نباید پرداخت دستی را برگرداند
|
||||||
|
_logger.LogWarning(
|
||||||
|
activateEx,
|
||||||
|
"Club membership activation failed after manual payment for UserId {UserId} — payment recorded successfully",
|
||||||
|
request.UserId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Manual membership payment created successfully. " +
|
"Manual membership payment created successfully. " +
|
||||||
"ManualPaymentId: {Id}, UserId: {UserId}, TransactionId: {TransactionId}, " +
|
"ManualPaymentId: {Id}, UserId: {UserId}, TransactionId: {TransactionId}, " +
|
||||||
|
|||||||
+8
-2
@@ -118,7 +118,10 @@ public class GetNetworkTreeQueryHandler : IRequestHandler<GetNetworkTreeQuery, N
|
|||||||
ActivationWeekDefinitionId = reader.IsDBNull(reader.GetOrdinal("ActivationWeekDefinitionId")) ? null : reader.GetInt64(reader.GetOrdinal("ActivationWeekDefinitionId")),
|
ActivationWeekDefinitionId = reader.IsDBNull(reader.GetOrdinal("ActivationWeekDefinitionId")) ? null : reader.GetInt64(reader.GetOrdinal("ActivationWeekDefinitionId")),
|
||||||
ActivationWeekDisplayName = reader.IsDBNull(reader.GetOrdinal("ActivationWeekDisplayName")) ? null : reader.GetString(reader.GetOrdinal("ActivationWeekDisplayName")),
|
ActivationWeekDisplayName = reader.IsDBNull(reader.GetOrdinal("ActivationWeekDisplayName")) ? null : reader.GetString(reader.GetOrdinal("ActivationWeekDisplayName")),
|
||||||
IsActivatedInTargetWeek = Convert.ToBoolean(reader.GetValue(reader.GetOrdinal("IsActivatedInTargetWeek"))),
|
IsActivatedInTargetWeek = Convert.ToBoolean(reader.GetValue(reader.GetOrdinal("IsActivatedInTargetWeek"))),
|
||||||
UserCreated = new DateTimeOffset(reader.GetDateTime(reader.GetOrdinal("UserCreated")))
|
UserCreated = new DateTimeOffset(reader.GetDateTime(reader.GetOrdinal("UserCreated"))),
|
||||||
|
IsNewActivation = reader.IsDBNull(reader.GetOrdinal("IsNewActivation")) ? null : (bool?)(reader.GetInt32(reader.GetOrdinal("IsNewActivation")) == 1),
|
||||||
|
PackageName = reader.IsDBNull(reader.GetOrdinal("PackageName")) ? null : reader.GetString(reader.GetOrdinal("PackageName")),
|
||||||
|
PackageId = reader.IsDBNull(reader.GetOrdinal("PackageId")) ? null : reader.GetInt64(reader.GetOrdinal("PackageId"))
|
||||||
};
|
};
|
||||||
|
|
||||||
results.Add(node);
|
results.Add(node);
|
||||||
@@ -160,7 +163,10 @@ public class GetNetworkTreeQueryHandler : IRequestHandler<GetNetworkTreeQuery, N
|
|||||||
ActivationWeekDefinitionId = flatNode.ActivationWeekDefinitionId,
|
ActivationWeekDefinitionId = flatNode.ActivationWeekDefinitionId,
|
||||||
ActivationWeekDisplayName = flatNode.ActivationWeekDisplayName,
|
ActivationWeekDisplayName = flatNode.ActivationWeekDisplayName,
|
||||||
IsActivatedInTargetWeek = flatNode.IsActivatedInTargetWeek,
|
IsActivatedInTargetWeek = flatNode.IsActivatedInTargetWeek,
|
||||||
UserCreated = flatNode.UserCreated
|
UserCreated = flatNode.UserCreated,
|
||||||
|
IsNewActivation = flatNode.IsNewActivation,
|
||||||
|
PackageName = flatNode.PackageName,
|
||||||
|
PackageId = flatNode.PackageId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
@@ -48,6 +48,18 @@ public class NetworkTreeDto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTimeOffset UserCreated { get; set; }
|
public DateTimeOffset UserCreated { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا فعالسازی در هفته هدف اولین بار بوده؟ null = بدون Cycle
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsNewActivation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نام پکیج موثر (هفته هدف یا پکیج فعلی)
|
||||||
|
/// </summary>
|
||||||
|
public string? PackageName { get; set; }
|
||||||
|
|
||||||
|
public long? PackageId { get; set; }
|
||||||
|
|
||||||
public NetworkTreeDto? LeftChild { get; set; }
|
public NetworkTreeDto? LeftChild { get; set; }
|
||||||
public NetworkTreeDto? RightChild { get; set; }
|
public NetworkTreeDto? RightChild { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -21,6 +21,19 @@ public class NetworkTreeNodeDto
|
|||||||
public bool IsActivatedInTargetWeek { get; set; }
|
public bool IsActivatedInTargetWeek { get; set; }
|
||||||
public DateTimeOffset UserCreated { get; set; }
|
public DateTimeOffset UserCreated { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا فعالسازی در هفته هدف اولین بار بوده (true) یا خرید مجدد (false)؟
|
||||||
|
/// null یعنی Cycleای ندارد
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsNewActivation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نام پکیج موثر (هفته هدف یا پکیج فعلی)
|
||||||
|
/// </summary>
|
||||||
|
public string? PackageName { get; set; }
|
||||||
|
|
||||||
|
public long? PackageId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// نام کامل کاربر
|
/// نام کامل کاربر
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+6
-6
@@ -166,10 +166,10 @@ BEGIN
|
|||||||
LeftNewMembers AS (
|
LeftNewMembers AS (
|
||||||
SELECT
|
SELECT
|
||||||
cte.ParentId AS UserId,
|
cte.ParentId AS UserId,
|
||||||
COUNT(*) AS NewMembersCount
|
COUNT(DISTINCT cte.ChildId) AS NewMembersCount
|
||||||
FROM LeftLegCTE cte
|
FROM LeftLegCTE cte
|
||||||
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = cte.ChildId AND cm.IsActive = 1
|
INNER JOIN CMS.ClubMembershipCycles cc ON cc.UserId = cte.ChildId
|
||||||
WHERE cm.ActivatedAt >= @StartDate AND cm.ActivatedAt <= @EndDate
|
WHERE cc.PackagePurchasedAt >= @StartDate AND cc.PackagePurchasedAt <= @EndDate
|
||||||
GROUP BY cte.ParentId
|
GROUP BY cte.ParentId
|
||||||
)
|
)
|
||||||
UPDATE b
|
UPDATE b
|
||||||
@@ -203,10 +203,10 @@ BEGIN
|
|||||||
RightNewMembers AS (
|
RightNewMembers AS (
|
||||||
SELECT
|
SELECT
|
||||||
cte.ParentId AS UserId,
|
cte.ParentId AS UserId,
|
||||||
COUNT(*) AS NewMembersCount
|
COUNT(DISTINCT cte.ChildId) AS NewMembersCount
|
||||||
FROM RightLegCTE cte
|
FROM RightLegCTE cte
|
||||||
INNER JOIN CMS.ClubMemberships cm ON cm.UserId = cte.ChildId AND cm.IsActive = 1
|
INNER JOIN CMS.ClubMembershipCycles cc ON cc.UserId = cte.ChildId
|
||||||
WHERE cm.ActivatedAt >= @StartDate AND cm.ActivatedAt <= @EndDate
|
WHERE cc.PackagePurchasedAt >= @StartDate AND cc.PackagePurchasedAt <= @EndDate
|
||||||
GROUP BY cte.ParentId
|
GROUP BY cte.ParentId
|
||||||
)
|
)
|
||||||
UPDATE b
|
UPDATE b
|
||||||
|
|||||||
+56
-41
@@ -3,10 +3,12 @@
|
|||||||
-- Description: محاسبه استخر کمیسیون هفتگی و توزیع بین کاربران
|
-- Description: محاسبه استخر کمیسیون هفتگی و توزیع بین کاربران
|
||||||
-- Author: System
|
-- Author: System
|
||||||
-- Created: 2025-12-19
|
-- Created: 2025-12-19
|
||||||
|
-- Updated: Q29 — اضافه کردن @PackageId، fix فیلتر pool، مدیریت pool خالی
|
||||||
-- =============================================
|
-- =============================================
|
||||||
|
|
||||||
CREATE OR ALTER PROCEDURE [CMS].[sp_CalculateWeeklyCommissionPool]
|
CREATE OR ALTER PROCEDURE [CMS].[sp_CalculateWeeklyCommissionPool]
|
||||||
@WeekDefinitionId BIGINT,
|
@WeekDefinitionId BIGINT,
|
||||||
|
@PackageId BIGINT, -- هر بار به ازای یک پکیج اجرا میشود
|
||||||
@ForceRecalculate BIT = 0,
|
@ForceRecalculate BIT = 0,
|
||||||
@PoolId BIGINT OUTPUT
|
@PoolId BIGINT OUTPUT
|
||||||
AS
|
AS
|
||||||
@@ -15,7 +17,7 @@ BEGIN
|
|||||||
SET XACT_ABORT ON;
|
SET XACT_ABORT ON;
|
||||||
|
|
||||||
DECLARE @ErrorMessage NVARCHAR(4000);
|
DECLARE @ErrorMessage NVARCHAR(4000);
|
||||||
DECLARE @TotalPoolAmount BIGINT;
|
DECLARE @TotalPoolAmount BIGINT = 0;
|
||||||
DECLARE @TotalBalances INT;
|
DECLARE @TotalBalances INT;
|
||||||
DECLARE @ValuePerBalance BIGINT;
|
DECLARE @ValuePerBalance BIGINT;
|
||||||
DECLARE @CalculatedAt DATETIME = GETDATE();
|
DECLARE @CalculatedAt DATETIME = GETDATE();
|
||||||
@@ -24,33 +26,42 @@ BEGIN
|
|||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 1. پیدا کردن Pool هفته
|
-- 1. پیدا کردن Pool هفته (فیلتر بر اساس PackageId)
|
||||||
-- =============================================
|
-- =============================================
|
||||||
SELECT @PoolId = Id, @TotalPoolAmount = TotalPoolAmount
|
SELECT @PoolId = Id, @TotalPoolAmount = TotalPoolAmount
|
||||||
FROM CMS.WeeklyCommissionPools
|
FROM CMS.WeeklyCommissionPools
|
||||||
WHERE WeekDefinitionId = @WeekDefinitionId;
|
WHERE WeekDefinitionId = @WeekDefinitionId AND PackageId = @PackageId;
|
||||||
|
|
||||||
|
-- اگر Pool وجود ندارد (هیچ فعالسازی در این هفته نبوده)، یک رکورد خالی ایجاد میکنیم
|
||||||
IF @PoolId IS NULL
|
IF @PoolId IS NULL
|
||||||
BEGIN
|
BEGIN
|
||||||
SET @ErrorMessage = N'استخر کمیسیون برای هفته ' + CAST(@WeekDefinitionId AS NVARCHAR(20)) + N' تعریف نشده است';
|
INSERT INTO CMS.WeeklyCommissionPools (
|
||||||
RAISERROR(@ErrorMessage, 16, 1);
|
WeekDefinitionId, PackageId, TotalPoolAmount, TotalBalances,
|
||||||
RETURN;
|
ValuePerBalance, IsCalculated, CalculatedAt,
|
||||||
|
IsDeleted, Created, CreatedBy, LastModified, LastModifiedBy
|
||||||
|
) VALUES (
|
||||||
|
@WeekDefinitionId, @PackageId, 0, 0, 0, 0, NULL,
|
||||||
|
0, @CalculatedAt, 'SP', @CalculatedAt, 'SP'
|
||||||
|
);
|
||||||
|
SET @PoolId = SCOPE_IDENTITY();
|
||||||
|
SET @TotalPoolAmount = 0;
|
||||||
END
|
END
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 2. بررسی محاسبات قبلی
|
-- 2. بررسی محاسبات قبلی (بر اساس همین Pool نه کل هفته)
|
||||||
-- =============================================
|
-- =============================================
|
||||||
IF EXISTS (SELECT 1 FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId)
|
IF EXISTS (SELECT 1 FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
|
||||||
BEGIN
|
BEGIN
|
||||||
IF @ForceRecalculate = 0
|
IF @ForceRecalculate = 0
|
||||||
BEGIN
|
BEGIN
|
||||||
SET @ErrorMessage = N'کمیسیون هفته ' + CAST(@WeekDefinitionId AS NVARCHAR(20)) + N' قبلاً محاسبه شده است. برای محاسبه مجدد از ForceRecalculate استفاده کنید';
|
SET @ErrorMessage = N'کمیسیون هفته ' + CAST(@WeekDefinitionId AS NVARCHAR(20))
|
||||||
|
+ N' (پکیج ' + CAST(@PackageId AS NVARCHAR(20)) + N') قبلاً محاسبه شده است. برای محاسبه مجدد از ForceRecalculate استفاده کنید';
|
||||||
RAISERROR(@ErrorMessage, 16, 1);
|
RAISERROR(@ErrorMessage, 16, 1);
|
||||||
RETURN;
|
RETURN;
|
||||||
END
|
END
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 3. Revert کیف پولها (در صورت ForceRecalculate)
|
-- 3. Revert کیف پولها (در صورت ForceRecalculate، فقط پرداختهای این Pool)
|
||||||
-- =============================================
|
-- =============================================
|
||||||
|
|
||||||
-- کم کردن مقادیر قبلی از NetworkBalance
|
-- کم کردن مقادیر قبلی از NetworkBalance
|
||||||
@@ -59,25 +70,25 @@ BEGIN
|
|||||||
(SELECT SUM(wl.ChangeNerworkValue)
|
(SELECT SUM(wl.ChangeNerworkValue)
|
||||||
FROM CMS.UserWalletChangeLogs wl
|
FROM CMS.UserWalletChangeLogs wl
|
||||||
WHERE wl.WalletId = uw.Id
|
WHERE wl.WalletId = uw.Id
|
||||||
AND wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId)
|
AND wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
|
||||||
), 0)
|
), 0)
|
||||||
FROM CMS.UserWallets uw
|
FROM CMS.UserWallets uw
|
||||||
WHERE uw.Id IN (
|
WHERE uw.Id IN (
|
||||||
SELECT DISTINCT wl.WalletId
|
SELECT DISTINCT wl.WalletId
|
||||||
FROM CMS.UserWalletChangeLogs wl
|
FROM CMS.UserWalletChangeLogs wl
|
||||||
WHERE wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId)
|
WHERE wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- حذف لاگهای تغییرات قبلی
|
-- حذف لاگهای تغییرات قبلی
|
||||||
DELETE FROM CMS.UserWalletChangeLogs
|
DELETE FROM CMS.UserWalletChangeLogs
|
||||||
WHERE RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId);
|
WHERE RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId);
|
||||||
|
|
||||||
-- حذف تاریخچه پرداخت
|
-- حذف تاریخچه پرداخت
|
||||||
DELETE FROM CMS.CommissionPayoutHistories
|
DELETE FROM CMS.CommissionPayoutHistories
|
||||||
WHERE UserCommissionPayoutId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId);
|
WHERE UserCommissionPayoutId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId);
|
||||||
|
|
||||||
-- حذف پرداختهای قبلی
|
-- حذف پرداختهای قبلی این Pool
|
||||||
DELETE FROM CMS.UserCommissionPayouts WHERE WeekDefinitionId = @WeekDefinitionId;
|
DELETE FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId;
|
||||||
|
|
||||||
-- Reset وضعیت Pool
|
-- Reset وضعیت Pool
|
||||||
UPDATE CMS.WeeklyCommissionPools
|
UPDATE CMS.WeeklyCommissionPools
|
||||||
@@ -90,8 +101,12 @@ BEGIN
|
|||||||
-- =============================================
|
-- =============================================
|
||||||
IF NOT EXISTS (SELECT 1 FROM CMS.NetworkWeeklyBalances WHERE WeekDefinitionId = @WeekDefinitionId)
|
IF NOT EXISTS (SELECT 1 FROM CMS.NetworkWeeklyBalances WHERE WeekDefinitionId = @WeekDefinitionId)
|
||||||
BEGIN
|
BEGIN
|
||||||
SET @ErrorMessage = N'ابتدا باید تعادلهای هفتگی محاسبه شوند. sp_CalculateWeeklyBalances را اجرا کنید';
|
-- بالانسی محاسبه نشده — pool را به عنوان "محاسبه شده بدون پرداخت" علامت میزنیم
|
||||||
RAISERROR(@ErrorMessage, 16, 1);
|
UPDATE CMS.WeeklyCommissionPools
|
||||||
|
SET IsCalculated = 1, CalculatedAt = @CalculatedAt
|
||||||
|
WHERE Id = @PoolId;
|
||||||
|
|
||||||
|
COMMIT TRANSACTION;
|
||||||
RETURN;
|
RETURN;
|
||||||
END
|
END
|
||||||
|
|
||||||
@@ -104,7 +119,7 @@ BEGIN
|
|||||||
|
|
||||||
IF @TotalBalances IS NULL OR @TotalBalances = 0
|
IF @TotalBalances IS NULL OR @TotalBalances = 0
|
||||||
BEGIN
|
BEGIN
|
||||||
-- هیچ تعادلی برای توزیع وجود ندارد
|
-- هیچ تعادلی برای توزیع وجود ندارد — pool محاسبه شده اما پرداختی ندارد
|
||||||
UPDATE CMS.WeeklyCommissionPools
|
UPDATE CMS.WeeklyCommissionPools
|
||||||
SET IsCalculated = 1, CalculatedAt = @CalculatedAt
|
SET IsCalculated = 1, CalculatedAt = @CalculatedAt
|
||||||
WHERE Id = @PoolId;
|
WHERE Id = @PoolId;
|
||||||
@@ -143,9 +158,9 @@ BEGIN
|
|||||||
nb.TotalBalances,
|
nb.TotalBalances,
|
||||||
@ValuePerBalance,
|
@ValuePerBalance,
|
||||||
nb.TotalBalances * @ValuePerBalance,
|
nb.TotalBalances * @ValuePerBalance,
|
||||||
0, -- Status: Pending
|
0, -- Status: Pending
|
||||||
NULL, -- PaidAt
|
NULL, -- PaidAt
|
||||||
0, -- IsDeleted
|
0, -- IsDeleted
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
'SP',
|
'SP',
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
@@ -174,23 +189,23 @@ BEGIN
|
|||||||
LastModifiedBy
|
LastModifiedBy
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
cp.Id, -- UserCommissionPayoutId
|
cp.Id,
|
||||||
cp.UserId, -- UserId
|
cp.UserId,
|
||||||
@WeekDefinitionId,
|
@WeekDefinitionId,
|
||||||
0, -- AmountBefore
|
0,
|
||||||
cp.TotalAmount, -- AmountAfter
|
cp.TotalAmount,
|
||||||
0, -- OldStatus: Pending
|
0, -- OldStatus: Pending
|
||||||
0, -- NewStatus: Pending
|
0, -- NewStatus: Pending
|
||||||
0, -- Action: Created (assuming enum value)
|
0, -- Action: Created
|
||||||
'SP', -- PerformedBy
|
'SP',
|
||||||
N'محاسبه اولیه توسط SP', -- Reason
|
N'محاسبه اولیه توسط SP',
|
||||||
0, -- IsDeleted
|
0,
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
'SP',
|
'SP',
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
'SP'
|
'SP'
|
||||||
FROM CMS.UserCommissionPayouts cp
|
FROM CMS.UserCommissionPayouts cp
|
||||||
WHERE cp.WeekDefinitionId = @WeekDefinitionId;
|
WHERE cp.WeeklyPoolId = @PoolId;
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 9. شارژ کیف پول کاربران
|
-- 9. شارژ کیف پول کاربران
|
||||||
@@ -201,7 +216,7 @@ BEGIN
|
|||||||
SET uw.NetworkBalance = uw.NetworkBalance + cp.TotalAmount
|
SET uw.NetworkBalance = uw.NetworkBalance + cp.TotalAmount
|
||||||
FROM CMS.UserWallets uw
|
FROM CMS.UserWallets uw
|
||||||
INNER JOIN CMS.UserCommissionPayouts cp ON cp.UserId = uw.UserId
|
INNER JOIN CMS.UserCommissionPayouts cp ON cp.UserId = uw.UserId
|
||||||
WHERE cp.WeekDefinitionId = @WeekDefinitionId;
|
WHERE cp.WeeklyPoolId = @PoolId;
|
||||||
|
|
||||||
-- ثبت لاگ تغییرات کیف پول
|
-- ثبت لاگ تغییرات کیف پول
|
||||||
INSERT INTO CMS.UserWalletChangeLogs (
|
INSERT INTO CMS.UserWalletChangeLogs (
|
||||||
@@ -222,22 +237,22 @@ BEGIN
|
|||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
uw.Id,
|
uw.Id,
|
||||||
uw.Balance, -- CurrentBalance
|
uw.Balance,
|
||||||
0, -- ChangeValue (no change to main balance)
|
0, -- ChangeValue (no change to main balance)
|
||||||
uw.NetworkBalance, -- CurrentNetworkBalance (after update)
|
uw.NetworkBalance, -- CurrentNetworkBalance (after update)
|
||||||
cp.TotalAmount, -- ChangeNerworkValue
|
cp.TotalAmount, -- ChangeNerworkValue
|
||||||
uw.DiscountBalance, -- CurrentDiscountBalance
|
uw.DiscountBalance,
|
||||||
0, -- ChangeDiscountValue
|
0, -- ChangeDiscountValue
|
||||||
1, -- IsIncrease: true
|
1, -- IsIncrease: true
|
||||||
cp.Id, -- RefrenceId: PayoutId
|
cp.Id, -- RefrenceId: PayoutId
|
||||||
0, -- IsDeleted
|
0,
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
'SP',
|
'SP',
|
||||||
@CalculatedAt,
|
@CalculatedAt,
|
||||||
'SP'
|
'SP'
|
||||||
FROM CMS.UserCommissionPayouts cp
|
FROM CMS.UserCommissionPayouts cp
|
||||||
INNER JOIN CMS.UserWallets uw ON uw.UserId = cp.UserId
|
INNER JOIN CMS.UserWallets uw ON uw.UserId = cp.UserId
|
||||||
WHERE cp.WeekDefinitionId = @WeekDefinitionId;
|
WHERE cp.WeeklyPoolId = @PoolId;
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
-- 10. بروزرسانی Pool
|
-- 10. بروزرسانی Pool
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>0.0.193</Version>
|
<Version>0.0.195</Version>
|
||||||
<DebugType>None</DebugType>
|
<DebugType>None</DebugType>
|
||||||
<DebugSymbols>False</DebugSymbols>
|
<DebugSymbols>False</DebugSymbols>
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
|||||||
@@ -212,6 +212,11 @@ message GetWeeklyCommissionPoolResponse
|
|||||||
google.protobuf.Timestamp created = 9;
|
google.protobuf.Timestamp created = 9;
|
||||||
int64 package_id = 10;
|
int64 package_id = 10;
|
||||||
string package_title = 11;
|
string package_title = 11;
|
||||||
|
// Q29: اعتبارسنجی TotalPoolAmount
|
||||||
|
bool validation_is_valid = 12;
|
||||||
|
int64 validation_expected_amount = 13;
|
||||||
|
int64 validation_discrepancy = 14;
|
||||||
|
int32 validation_activation_count = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserCommissionPayouts Query
|
// GetUserCommissionPayouts Query
|
||||||
|
|||||||
@@ -205,6 +205,10 @@ message NetworkTreeNodeModel
|
|||||||
string position = 16; // Root/Left/Right position indicator
|
string position = 16; // Root/Left/Right position indicator
|
||||||
NetworkTreeNodeModel left_child = 17; // Left child node
|
NetworkTreeNodeModel left_child = 17; // Left child node
|
||||||
NetworkTreeNodeModel right_child = 18; // Right child node
|
NetworkTreeNodeModel right_child = 18; // Right child node
|
||||||
|
// فیلدهای اطلاعات پکیج و نوع فعالسازی
|
||||||
|
google.protobuf.BoolValue is_new_activation = 22; // true=اولین فعالسازی، false=خرید مجدد، null=بدون Cycle
|
||||||
|
string package_name = 23; // نام پکیج موثر
|
||||||
|
google.protobuf.Int64Value package_id = 24; // شناسه پکیج
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHistory Query
|
// GetHistory Query
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ public class CommissionProfile : IRegister
|
|||||||
: null)
|
: null)
|
||||||
.Map(dest => dest.Created, src => Timestamp.FromDateTimeOffset(src.Created))
|
.Map(dest => dest.Created, src => Timestamp.FromDateTimeOffset(src.Created))
|
||||||
.Map(dest => dest.PackageId, src => src.PackageId)
|
.Map(dest => dest.PackageId, src => src.PackageId)
|
||||||
.Map(dest => dest.PackageTitle, src => src.PackageTitle);
|
.Map(dest => dest.PackageTitle, src => src.PackageTitle)
|
||||||
|
.Map(dest => dest.ValidationIsValid, src => src.ValidationIsValid)
|
||||||
|
.Map(dest => dest.ValidationExpectedAmount, src => src.ValidationExpectedAmount)
|
||||||
|
.Map(dest => dest.ValidationDiscrepancy, src => src.ValidationDiscrepancy)
|
||||||
|
.Map(dest => dest.ValidationActivationCount, src => src.ValidationActivationCount);
|
||||||
|
|
||||||
// GetAvailableWeeks Response Mapping
|
// GetAvailableWeeks Response Mapping
|
||||||
config.NewConfig<GetAvailableWeeksResponseDto, GetAvailableWeeksResponse>()
|
config.NewConfig<GetAvailableWeeksResponseDto, GetAvailableWeeksResponse>()
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using CMSMicroservice.Application.Common.Models;
|
||||||
|
using CMSMicroservice.Application.DiscountShopCQ.Queries.GetDiscountProducts;
|
||||||
|
using CMSMicroservice.Protobuf.Protos.DiscountProduct;
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
using Mapster;
|
||||||
|
using ProtoDiscountProductDto = CMSMicroservice.Protobuf.Protos.DiscountProduct.DiscountProductDto;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||||
|
|
||||||
|
public class DiscountProductProfile : IRegister
|
||||||
|
{
|
||||||
|
void IRegister.Register(TypeAdapterConfig config)
|
||||||
|
{
|
||||||
|
// GetDiscountProductsRequest (proto) → GetDiscountProductsQuery (CQRS)
|
||||||
|
config.NewConfig<GetDiscountProductsRequest, GetDiscountProductsQuery>()
|
||||||
|
.Map(dest => dest.SearchTerm,
|
||||||
|
src => string.IsNullOrEmpty(src.SearchQuery) ? null : src.SearchQuery)
|
||||||
|
.Map(dest => dest.CategoryId,
|
||||||
|
src => src.CategoryId != null ? src.CategoryId.Value : (long?)null)
|
||||||
|
.Map(dest => dest.IsActive,
|
||||||
|
src => src.IsActive != null ? src.IsActive.Value : (bool?)null)
|
||||||
|
.Map(dest => dest.MinPrice,
|
||||||
|
src => src.MinPrice != null ? (int?)src.MinPrice.Value : null)
|
||||||
|
.Map(dest => dest.MaxPrice,
|
||||||
|
src => src.MaxPrice != null ? (int?)src.MaxPrice.Value : null)
|
||||||
|
.Map(dest => dest.PaginationQuery, src => new PaginationState
|
||||||
|
{
|
||||||
|
PageNumber = src.PageNumber > 0 ? src.PageNumber : 1,
|
||||||
|
PageSize = src.PageSize > 0 ? src.PageSize : 12
|
||||||
|
});
|
||||||
|
|
||||||
|
// GetDiscountProductsResponseDto (CQRS) → GetDiscountProductsResponse (proto)
|
||||||
|
config.NewConfig<GetDiscountProductsResponseDto, GetDiscountProductsResponse>()
|
||||||
|
.MapWith(src => MapToResponse(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GetDiscountProductsResponse MapToResponse(GetDiscountProductsResponseDto src)
|
||||||
|
{
|
||||||
|
var response = new GetDiscountProductsResponse();
|
||||||
|
|
||||||
|
if (src.MetaData != null)
|
||||||
|
{
|
||||||
|
response.MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||||
|
{
|
||||||
|
TotalCount = src.MetaData.TotalCount,
|
||||||
|
PageSize = src.MetaData.PageSize,
|
||||||
|
CurrentPage = src.MetaData.CurrentPage,
|
||||||
|
TotalPage = src.MetaData.TotalPage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src.Models != null)
|
||||||
|
{
|
||||||
|
foreach (var p in src.Models)
|
||||||
|
{
|
||||||
|
response.Models.Add(new ProtoDiscountProductDto
|
||||||
|
{
|
||||||
|
Id = p.Id,
|
||||||
|
Title = p.Title ?? string.Empty,
|
||||||
|
ShortInfomation = p.ShortInfomation ?? string.Empty,
|
||||||
|
Price = p.Price,
|
||||||
|
MaxDiscountPercent = p.MaxDiscountPercent,
|
||||||
|
ImagePath = p.ImagePath ?? string.Empty,
|
||||||
|
ThumbnailPath = p.ThumbnailPath ?? string.Empty,
|
||||||
|
RemainingCount = p.RemainingCount,
|
||||||
|
ViewCount = p.ViewCount,
|
||||||
|
IsActive = p.IsActive,
|
||||||
|
Created = Timestamp.FromDateTime(DateTime.UtcNow)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,7 +92,10 @@ public class NetworkMembershipProfile : IRegister
|
|||||||
IsActive = true,
|
IsActive = true,
|
||||||
IsClubActive = node.IsClubActive,
|
IsClubActive = node.IsClubActive,
|
||||||
ActivationWeekDefinitionId = node.ActivationWeekDefinitionId ?? 0,
|
ActivationWeekDefinitionId = node.ActivationWeekDefinitionId ?? 0,
|
||||||
IsActivatedInTargetWeek = node.IsActivatedInTargetWeek
|
IsActivatedInTargetWeek = node.IsActivatedInTargetWeek,
|
||||||
|
PackageName = node.PackageName ?? string.Empty,
|
||||||
|
PackageId = node.PackageId.HasValue ? node.PackageId.Value : null,
|
||||||
|
IsNewActivation = node.IsNewActivation.HasValue ? node.IsNewActivation.Value : null
|
||||||
};
|
};
|
||||||
|
|
||||||
if (parentId.HasValue)
|
if (parentId.HasValue)
|
||||||
|
|||||||
Reference in New Issue
Block a user