113 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|