Files
CMS/src/CMSMicroservice.Application/NetworkMembershipCQ/Commands/MoveInNetwork/MoveInNetworkCommandHandler.cs

113 lines
4.2 KiB
C#

namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.MoveInNetwork;
public class MoveInNetworkCommandHandler : IRequestHandler<MoveInNetworkCommand, Unit>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public MoveInNetworkCommandHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<Unit> Handle(MoveInNetworkCommand request, CancellationToken cancellationToken)
{
// بررسی وجود کاربر
var user = await _context.Users
.FirstOrDefaultAsync(x => x.Id == request.UserId, cancellationToken);
if (user == null)
{
throw new NotFoundException(nameof(User), request.UserId);
}
// بررسی اینکه کاربر در شبکه باشد
if (!user.NetworkParentId.HasValue)
{
throw new InvalidOperationException($"کاربر با شناسه {request.UserId} در شبکه عضو نیست");
}
// بررسی وجود والد جدید
var newParent = await _context.Users
.FirstOrDefaultAsync(x => x.Id == request.NewParentId, cancellationToken);
if (newParent == null)
{
throw new NotFoundException(nameof(User), $"New Parent with Id {request.NewParentId}");
}
// بررسی اینکه والد جدید خود کاربر یا فرزندان او نباشد (جلوگیری از Loop)
if (await IsDescendant(request.NewParentId, request.UserId, cancellationToken))
{
throw new InvalidOperationException("نمی‌توان کاربر را زیر فرزندان خودش جابجا کرد (ایجاد حلقه)");
}
// بررسی خالی بودن Leg جدید
var legOccupied = await _context.Users
.AnyAsync(x => x.NetworkParentId == request.NewParentId &&
x.LegPosition == request.NewLegPosition &&
x.Id != request.UserId,
cancellationToken);
if (legOccupied)
{
throw new InvalidOperationException(
$"موقعیت {request.NewLegPosition} زیر والد {request.NewParentId} قبلاً پر شده است");
}
// ذخیره مقادیر قبلی برای History
var oldParentId = user.NetworkParentId;
var oldLegPosition = user.LegPosition;
// جابجایی
user.NetworkParentId = request.NewParentId;
user.LegPosition = request.NewLegPosition;
_context.Users.Update(user);
await _context.SaveChangesAsync(cancellationToken);
// ثبت تاریخچه
var history = new NetworkMembershipHistory
{
UserId = request.UserId,
OldParentId = oldParentId,
NewParentId = request.NewParentId,
OldLegPosition = oldLegPosition,
NewLegPosition = request.NewLegPosition,
Action = NetworkMembershipAction.Move,
Reason = request.Reason ?? "جابجایی در شبکه",
PerformedBy = "System" // TODO: باید از Current User گرفته شود
};
await _context.NetworkMembershipHistories.AddAsync(history, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
/// <summary>
/// بررسی می‌کند که آیا potentialDescendant فرزند (مستقیم یا غیرمستقیم) userId هست یا خیر
/// </summary>
private async Task<bool> IsDescendant(long potentialDescendantId, long userId, CancellationToken cancellationToken)
{
var current = await _context.Users
.FirstOrDefaultAsync(x => x.Id == potentialDescendantId, cancellationToken);
while (current?.NetworkParentId != null)
{
if (current.NetworkParentId == userId)
{
return true;
}
current = await _context.Users
.FirstOrDefaultAsync(x => x.Id == current.NetworkParentId, cancellationToken);
}
return false;
}
}