namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.MoveInNetwork; public class MoveInNetworkCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly ICurrentUserService _currentUser; public MoveInNetworkCommandHandler( IApplicationDbContext context, ICurrentUserService currentUser) { _context = context; _currentUser = currentUser; } public async Task 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; } /// /// بررسی می‌کند که آیا potentialDescendant فرزند (مستقیم یا غیرمستقیم) userId هست یا خیر /// private async Task 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; } }