feat: Enhance network membership and withdrawal processing with user tracking and logging

This commit is contained in:
masoodafar-web
2025-12-01 20:52:18 +03:30
parent 4aaf2247ff
commit 25fc73ae28
47 changed files with 9545 additions and 284 deletions

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.ClubMembershipCQ.Commands.ActivateClubMemb
public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClubMembershipCommand, long>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public ActivateClubMembershipCommandHandler(IApplicationDbContext context)
public ActivateClubMembershipCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<long> Handle(ActivateClubMembershipCommand request, CancellationToken cancellationToken)
@@ -21,16 +25,12 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
}
// دریافت مبلغ عضویت از Configuration
var membershipPrice = await _context.SystemConfigurations
.Where(x => x.Key == "club_membership_price" && x.IsActive)
var activationFeeConfig = await _context.SystemConfigurations
.Where(x => x.Key == "Club.ActivationFee" && x.IsActive)
.Select(x => x.Value)
.FirstOrDefaultAsync(cancellationToken);
long initialContribution = 25_000_000; // Default: 25 million Rials
if (!string.IsNullOrEmpty(membershipPrice) && long.TryParse(membershipPrice, out var parsedPrice))
{
initialContribution = parsedPrice;
}
long initialContribution = long.Parse(activationFeeConfig ?? "25000000"); // Default: 25 million Rials
// بررسی عضویت فعلی
var existingMembership = await _context.ClubMemberships
@@ -87,7 +87,7 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
NewIsActive = true,
Action = ClubMembershipAction.Activated,
Reason = request.Reason ?? (isNewMembership ? "Initial activation" : "Reactivated"),
PerformedBy = "System" // TODO: باید از Current User گرفته شود
PerformedBy = _currentUser.GetPerformedBy()
};
await _context.ClubMembershipHistories.AddAsync(history, cancellationToken);

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.ClubMembershipCQ.Commands.DeactivateClubMe
public class DeactivateClubMembershipCommandHandler : IRequestHandler<DeactivateClubMembershipCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public DeactivateClubMembershipCommandHandler(IApplicationDbContext context)
public DeactivateClubMembershipCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(DeactivateClubMembershipCommand request, CancellationToken cancellationToken)
@@ -38,8 +42,8 @@ public class DeactivateClubMembershipCommandHandler : IRequestHandler<Deactivate
OldIsActive = true,
NewIsActive = false,
Action = ClubMembershipAction.Deactivated,
Reason = request.Reason ?? "Membership deactivated",
PerformedBy = "System" // TODO: باید از Current User گرفته شود
Reason = request.Reason ?? "Manual deactivation",
PerformedBy = _currentUser.GetPerformedBy()
};
await _context.ClubMembershipHistories.AddAsync(history, cancellationToken);

View File

@@ -6,10 +6,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Commands.ApproveWithdrawal;
public class ApproveWithdrawalCommandHandler : IRequestHandler<ApproveWithdrawalCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public ApproveWithdrawalCommandHandler(IApplicationDbContext context)
public ApproveWithdrawalCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(ApproveWithdrawalCommand request, CancellationToken cancellationToken)
@@ -30,6 +34,8 @@ public class ApproveWithdrawalCommandHandler : IRequestHandler<ApproveWithdrawal
// Update status to Withdrawn (approved)
payout.Status = CommissionPayoutStatus.Withdrawn;
payout.WithdrawnAt = DateTime.UtcNow;
payout.ProcessedBy = _currentUser.GetPerformedBy();
payout.ProcessedAt = DateTime.UtcNow;
payout.LastModified = DateTime.UtcNow;
// TODO: Add PayoutHistory record

View File

@@ -34,30 +34,95 @@ public class CalculateWeeklyBalancesCommandHandler : IRequestHandler<CalculateWe
.Select(x => new { x.Id })
.ToListAsync(cancellationToken);
// دریافت باقیمانده‌های هفته قبل
var previousWeekNumber = GetPreviousWeekNumber(request.WeekNumber);
var previousWeekCarryovers = await _context.NetworkWeeklyBalances
.Where(x => x.WeekNumber == previousWeekNumber)
.Select(x => new
{
x.UserId,
x.LeftLegRemainder,
x.RightLegRemainder
})
.ToDictionaryAsync(x => x.UserId, cancellationToken);
var balancesList = new List<NetworkWeeklyBalance>();
var calculatedAt = DateTime.UtcNow;
// خواندن یکباره Configuration ها (بهینه‌سازی - به جای N query)
var configs = await _context.SystemConfigurations
.Where(x => x.IsActive && (
x.Key == "Club.ActivationFee" ||
x.Key == "Commission.WeeklyPoolContributionPercent" ||
x.Key == "Commission.MaxWeeklyBalancesPerUser"))
.ToDictionaryAsync(x => x.Key, x => x.Value, cancellationToken);
var activationFee = long.Parse(configs.GetValueOrDefault("Club.ActivationFee", "25000000"));
var poolPercent = decimal.Parse(configs.GetValueOrDefault("Commission.WeeklyPoolContributionPercent", "20")) / 100m;
var maxWeeklyBalances = int.Parse(configs.GetValueOrDefault("Commission.MaxWeeklyBalancesPerUser", "300"));
foreach (var user in usersInNetwork)
{
// محاسبه تعادل پای چپ (Left Leg)
var leftLegBalances = (int)await CalculateLegBalances(user.Id, NetworkLeg.Left, cancellationToken);
// دریافت باقیمانده هفته قبل
var leftCarryover = 0;
var rightCarryover = 0;
if (previousWeekCarryovers.ContainsKey(user.Id))
{
leftCarryover = previousWeekCarryovers[user.Id].LeftLegRemainder;
rightCarryover = previousWeekCarryovers[user.Id].RightLegRemainder;
}
// محاسبه تعادل پای راست (Right Leg)
var rightLegBalances = (int)await CalculateLegBalances(user.Id, NetworkLeg.Right, cancellationToken);
// محاسبه تعداد اعضای جدید در این هفته (فقط فرزندان مستقیم که در این هفته فعال شدند)
var leftNewMembers = await CountNewMembersInLeg(user.Id, NetworkLeg.Left, request.WeekNumber, cancellationToken);
var rightNewMembers = await CountNewMembersInLeg(user.Id, NetworkLeg.Right, request.WeekNumber, cancellationToken);
// محاسبه Total Balances (کمترین مقدار دو پا)
var totalBalances = Math.Min(leftLegBalances, rightLegBalances);
// محاسبه مجموع هر پا (جدید + باقیمانده)
var leftTotal = leftNewMembers + leftCarryover;
var rightTotal = rightNewMembers + rightCarryover;
// محاسبه سهم استخر (10% از Total Balances)
var weeklyPoolContribution = (long)(totalBalances * 0.10m);
// محاسبه تعادل (کمترین مقدار)
var totalBalances = Math.Min(leftTotal, rightTotal);
// اعمال محدودیت سقف تعادل هفتگی (مثلاً 300)
var cappedBalances = Math.Min(totalBalances, maxWeeklyBalances);
// محاسبه باقیمانده برای هفته بعد
// اگر تعادل بیش از سقف بود، مازاد هم به remainder اضافه می‌شود
var excessBalances = totalBalances - cappedBalances;
var leftRemainder = (leftTotal - totalBalances) + (leftTotal >= rightTotal ? excessBalances : 0);
var rightRemainder = (rightTotal - totalBalances) + (rightTotal >= leftTotal ? excessBalances : 0);
// محاسبه سهم استخر (20% از مجموع فعال‌سازی‌های جدید کل شبکه)
// طبق گفته دکتر: کل افراد جدید در شبکه × هزینه فعال‌سازی × 20%
var totalNewMembers = leftNewMembers + rightNewMembers;
var weeklyPoolContribution = (long)(totalNewMembers * activationFee * poolPercent);
var balance = new NetworkWeeklyBalance
{
UserId = user.Id,
WeekNumber = request.WeekNumber,
LeftLegBalances = leftLegBalances,
RightLegBalances = rightLegBalances,
TotalBalances = totalBalances,
// اطلاعات جدید
LeftLegNewMembers = leftNewMembers,
RightLegNewMembers = rightNewMembers,
LeftLegCarryover = leftCarryover,
RightLegCarryover = rightCarryover,
// مجموع
LeftLegTotal = leftTotal,
RightLegTotal = rightTotal,
TotalBalances = cappedBalances, // تعادل واقعی بعد از اعمال سقف
// باقیمانده برای هفته بعد
LeftLegRemainder = leftRemainder,
RightLegRemainder = rightRemainder,
// فیلدهای قدیمی (deprecated) - برای سازگاری با کدهای قبلی
#pragma warning disable CS0618
LeftLegBalances = leftTotal,
RightLegBalances = rightTotal,
#pragma warning restore CS0618
WeeklyPoolContribution = weeklyPoolContribution,
CalculatedAt = calculatedAt,
IsExpired = false
@@ -73,23 +138,89 @@ public class CalculateWeeklyBalancesCommandHandler : IRequestHandler<CalculateWe
}
/// <summary>
/// محاسبه تعادل یک پا (Left یا Right) به صورت بازگشتی
/// شماره هفته قبل را محاسبه می‌کند
/// </summary>
private async Task<long> CalculateLegBalances(long userId, NetworkLeg leg, CancellationToken cancellationToken)
private string GetPreviousWeekNumber(string currentWeekNumber)
{
// پیدا کردن فرزند در پای مورد نظر
// مثال: "2025-W48" -> "2025-W47"
var parts = currentWeekNumber.Split('-');
var year = int.Parse(parts[0]);
var week = int.Parse(parts[1].Replace("W", ""));
week--;
if (week < 1)
{
year--;
week = 52; // یا 53 بسته به سال
}
return $"{year}-W{week:D2}";
}
/// <summary>
/// شمارش اعضای جدیدی که در این هفته به یک پا اضافه شدند
/// فقط فرزندان مستقیم که ActivatedAt آنها در این هفته است
/// </summary>
private async Task<int> CountNewMembersInLeg(long userId, NetworkLeg leg, string weekNumber, CancellationToken cancellationToken)
{
// تبدیل WeekNumber به بازه تاریخی
var (startDate, endDate) = GetWeekDateRange(weekNumber);
// شمارش تمام اعضای زیرمجموعه که در این هفته فعال شدند
var count = await CountNewMembersRecursive(userId, leg, startDate, endDate, cancellationToken);
return count;
}
/// <summary>
/// شمارش بازگشتی اعضای جدید در یک پا
/// </summary>
private async Task<int> CountNewMembersRecursive(long userId, NetworkLeg leg, DateTime startDate, DateTime endDate, CancellationToken cancellationToken)
{
// پیدا کردن فرزند مستقیم در پای مورد نظر
var child = await _context.Users
.FirstOrDefaultAsync(x => x.NetworkParentId == userId && x.LegPosition == leg, cancellationToken);
if (child == null)
{
return 0; // اگر فرزندی نداشته باشد، تعادل صفر است
return 0;
}
// محاسبه بازگشتی: مجموع تعادل فرزند چپ + راست + 1 (خود فرزند)
var childLeftLeg = await CalculateLegBalances(child.Id, NetworkLeg.Left, cancellationToken);
var childRightLeg = await CalculateLegBalances(child.Id, NetworkLeg.Right, cancellationToken);
var count = 0;
return 1 + childLeftLeg + childRightLeg;
// اگر فرزند در این هفته فعال شده، 1 امتیاز
var membership = await _context.ClubMemberships
.FirstOrDefaultAsync(x => x.UserId == child.Id && x.IsActive, cancellationToken);
if (membership?.ActivatedAt >= startDate && membership?.ActivatedAt <= endDate)
{
count = 1;
}
// جمع کردن اعضای جدید از پای چپ و راست فرزند
var childLeft = await CountNewMembersRecursive(child.Id, NetworkLeg.Left, startDate, endDate, cancellationToken);
var childRight = await CountNewMembersRecursive(child.Id, NetworkLeg.Right, startDate, endDate, cancellationToken);
return count + childLeft + childRight;
}
/// <summary>
/// تبدیل شماره هفته به بازه تاریخی
/// </summary>
private (DateTime startDate, DateTime endDate) GetWeekDateRange(string weekNumber)
{
// مثال: "2025-W48"
var parts = weekNumber.Split('-');
var year = int.Parse(parts[0]);
var week = int.Parse(parts[1].Replace("W", ""));
// محاسبه اولین روز هفته (شنبه)
var jan1 = new DateTime(year, 1, 1);
var daysOffset = DayOfWeek.Saturday - jan1.DayOfWeek;
var firstSaturday = jan1.AddDays(daysOffset);
var weekStart = firstSaturday.AddDays((week - 1) * 7);
var weekEnd = weekStart.AddDays(6).AddHours(23).AddMinutes(59).AddSeconds(59);
return (weekStart, weekEnd);
}
}

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Commands.ProcessWithdrawal;
public class ProcessWithdrawalCommandHandler : IRequestHandler<ProcessWithdrawalCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public ProcessWithdrawalCommandHandler(IApplicationDbContext context)
public ProcessWithdrawalCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(ProcessWithdrawalCommand request, CancellationToken cancellationToken)

View File

@@ -6,10 +6,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Commands.RejectWithdrawal;
public class RejectWithdrawalCommandHandler : IRequestHandler<RejectWithdrawalCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public RejectWithdrawalCommandHandler(IApplicationDbContext context)
public RejectWithdrawalCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(RejectWithdrawalCommand request, CancellationToken cancellationToken)
@@ -29,6 +33,9 @@ public class RejectWithdrawalCommandHandler : IRequestHandler<RejectWithdrawalCo
// Update status to Cancelled (rejected)
payout.Status = CommissionPayoutStatus.Cancelled;
payout.ProcessedBy = _currentUser.GetPerformedBy();
payout.ProcessedAt = DateTime.UtcNow;
payout.RejectionReason = request.Reason;
payout.LastModified = DateTime.UtcNow;
// TODO: Add PayoutHistory record with rejection reason

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Commands.RequestWithdrawal;
public class RequestWithdrawalCommandHandler : IRequestHandler<RequestWithdrawalCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public RequestWithdrawalCommandHandler(IApplicationDbContext context)
public RequestWithdrawalCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(RequestWithdrawalCommand request, CancellationToken cancellationToken)

View File

@@ -16,78 +16,51 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
GetWorkerExecutionLogsQuery request,
CancellationToken cancellationToken)
{
// TODO: این باید از یک entity واقعی لاگ‌ها را بگیرد
// فعلاً mock data برمی‌گرداند
await Task.CompletedTask;
var mockLogs = new List<WorkerExecutionLogModel>
{
new WorkerExecutionLogModel
{
ExecutionId = Guid.NewGuid().ToString(),
WeekNumber = "2025-W48",
Step = "Full",
Success = true,
ErrorMessage = null,
StartedAt = DateTime.UtcNow.AddHours(-24),
CompletedAt = DateTime.UtcNow.AddHours(-24).AddMinutes(15),
DurationMs = 900000, // 15 minutes
RecordsProcessed = 1523,
Details = "محاسبات کامل هفته 2025-W48 با موفقیت انجام شد"
},
new WorkerExecutionLogModel
{
ExecutionId = Guid.NewGuid().ToString(),
WeekNumber = "2025-W47",
Step = "Full",
Success = true,
ErrorMessage = null,
StartedAt = DateTime.UtcNow.AddDays(-7),
CompletedAt = DateTime.UtcNow.AddDays(-7).AddMinutes(12),
DurationMs = 720000,
RecordsProcessed = 1489,
Details = "محاسبات کامل هفته 2025-W47 با موفقیت انجام شد"
},
new WorkerExecutionLogModel
{
ExecutionId = Guid.NewGuid().ToString(),
WeekNumber = "2025-W46",
Step = "Pool",
Success = false,
ErrorMessage = "خطا در محاسبه استخر کمیسیون",
StartedAt = DateTime.UtcNow.AddDays(-14),
CompletedAt = DateTime.UtcNow.AddDays(-14).AddSeconds(30),
DurationMs = 30000,
RecordsProcessed = 0,
Details = "محاسبه استخر با خطا مواجه شد"
}
};
// Query from database
var query = _context.WorkerExecutionLogs.AsQueryable();
// Apply filters
if (!string.IsNullOrEmpty(request.WeekNumber))
{
mockLogs = mockLogs.Where(x => x.WeekNumber == request.WeekNumber).ToList();
query = query.Where(x => x.WeekNumber == request.WeekNumber);
}
if (request.SuccessOnly == true)
{
mockLogs = mockLogs.Where(x => x.Success).ToList();
query = query.Where(x => x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Success ||
x.Status == Domain.Entities.Commission.WorkerExecutionStatus.SuccessWithWarnings);
}
if (request.FailedOnly == true)
{
mockLogs = mockLogs.Where(x => !x.Success).ToList();
query = query.Where(x => x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Failed);
}
var totalCount = mockLogs.Count;
// Order by most recent first
query = query.OrderByDescending(x => x.StartedAt);
var totalCount = await query.CountAsync(cancellationToken);
var pageSize = request.PaginationState?.PageSize ?? 10;
var pageNumber = request.PaginationState?.PageNumber ?? 1;
var pagedLogs = mockLogs
var logs = await query
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
.Select(x => new WorkerExecutionLogModel
{
ExecutionId = x.ExecutionId.ToString(),
WeekNumber = x.WeekNumber,
Step = "Full", // We only have full execution now
Success = x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Success ||
x.Status == Domain.Entities.Commission.WorkerExecutionStatus.SuccessWithWarnings,
ErrorMessage = x.ErrorMessage,
StartedAt = x.StartedAt,
CompletedAt = x.CompletedAt ?? x.StartedAt,
DurationMs = x.DurationMs ?? 0,
RecordsProcessed = x.ProcessedCount,
Details = x.Details ?? $"Worker execution: {x.Status}"
})
.ToListAsync(cancellationToken);
return new GetWorkerExecutionLogsResponseDto
{
@@ -100,7 +73,7 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
HasPrevious = pageNumber > 1,
HasNext = pageNumber < (int)Math.Ceiling(totalCount / (double)pageSize)
},
Models = pagedLogs
Models = logs
};
}
}

View File

@@ -34,5 +34,6 @@ public interface IApplicationDbContext
DbSet<WeeklyCommissionPool> WeeklyCommissionPools { get; }
DbSet<UserCommissionPayout> UserCommissionPayouts { get; }
DbSet<CommissionPayoutHistory> CommissionPayoutHistories { get; }
DbSet<WorkerExecutionLog> WorkerExecutionLogs { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,6 +1,27 @@
namespace CMSMicroservice.Application.Common.Interfaces;
/// <summary>
/// سرویس دریافت اطلاعات کاربر فعلی از Authentication Context
/// </summary>
public interface ICurrentUserService
{
/// <summary>
/// شناسه کاربر فعلی (از JWT Claims)
/// </summary>
string? UserId { get; }
/// <summary>
/// نام کاربری (Username یا Email)
/// </summary>
string? Username { get; }
/// <summary>
/// آیا کاربر Authenticated است؟
/// </summary>
bool IsAuthenticated { get; }
/// <summary>
/// دریافت string برای PerformedBy (UserId:Username یا "System")
/// </summary>
string GetPerformedBy();
}

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.ConfigurationCQ.Commands.DeactivateConfigu
public class DeactivateConfigurationCommandHandler : IRequestHandler<DeactivateConfigurationCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public DeactivateConfigurationCommandHandler(IApplicationDbContext context)
public DeactivateConfigurationCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(DeactivateConfigurationCommand request, CancellationToken cancellationToken)
@@ -36,7 +40,7 @@ public class DeactivateConfigurationCommandHandler : IRequestHandler<DeactivateC
OldValue = oldValue,
NewValue = entity.Value,
Reason = request.Reason ?? "Configuration deactivated",
PerformedBy = "System" // TODO: باید از Current User گرفته شود
PerformedBy = _currentUser.GetPerformedBy()
};
await _context.SystemConfigurationHistories.AddAsync(history, cancellationToken);

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.ConfigurationCQ.Commands.SetConfigurationV
public class SetConfigurationValueCommandHandler : IRequestHandler<SetConfigurationValueCommand, long>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public SetConfigurationValueCommandHandler(IApplicationDbContext context)
public SetConfigurationValueCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<long> Handle(SetConfigurationValueCommand request, CancellationToken cancellationToken)

View File

@@ -3,7 +3,7 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.JoinNetwork;
/// <summary>
/// Command برای افزودن کاربر به شبکه دوتایی (Binary Network)
/// </summary>
public record JoinNetworkCommand : IRequest<Unit>
public record JoinNetworkCommand : IRequest<long>
{
/// <summary>
/// شناسه کاربر که می‌خواهد به شبکه بپیوندد

View File

@@ -1,15 +1,19 @@
namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.JoinNetwork;
public class JoinNetworkCommandHandler : IRequestHandler<JoinNetworkCommand, Unit>
public class JoinNetworkCommandHandler : IRequestHandler<JoinNetworkCommand, long>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public JoinNetworkCommandHandler(IApplicationDbContext context)
public JoinNetworkCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(JoinNetworkCommand request, CancellationToken cancellationToken)
public async Task<long> Handle(JoinNetworkCommand request, CancellationToken cancellationToken)
{
// بررسی وجود کاربر
var user = await _context.Users
@@ -69,12 +73,12 @@ public class JoinNetworkCommandHandler : IRequestHandler<JoinNetworkCommand, Uni
NewLegPosition = request.LegPosition,
Action = NetworkMembershipAction.Join,
Reason = request.Reason ?? "عضویت در شبکه",
PerformedBy = "System" // TODO: باید از Current User گرفته شود
PerformedBy = _currentUser.GetPerformedBy()
};
await _context.NetworkMembershipHistories.AddAsync(history, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
return user.Id;
}
}

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.MoveInNetwork
public class MoveInNetworkCommandHandler : IRequestHandler<MoveInNetworkCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public MoveInNetworkCommandHandler(IApplicationDbContext context)
public MoveInNetworkCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(MoveInNetworkCommand request, CancellationToken cancellationToken)

View File

@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.RemoveFromNet
public class RemoveFromNetworkCommandHandler : IRequestHandler<RemoveFromNetworkCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public RemoveFromNetworkCommandHandler(IApplicationDbContext context)
public RemoveFromNetworkCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(RemoveFromNetworkCommand request, CancellationToken cancellationToken)