Files
CMS/src/CMSMicroservice.Application/NetworkMembershipCQ/Commands/RemoveFromNetwork/RemoveFromNetworkCommandHandler.cs
masoodafar-web db96a02f89 feat: Add NetworkMembershipCQ - Phase 4 Application Layer
- Implemented 3 Commands with handlers and validators:
  * JoinNetworkCommand: Add user to binary network tree
    - Validates parent exists and is in network
    - Validates leg position is empty
    - Records history with NetworkMembershipAction.Join
  * MoveInNetworkCommand: Move user to different position
    - Validates new parent and leg availability
    - Prevents circular dependencies (IsDescendant check)
    - Records old/new parent and leg in history
  * RemoveFromNetworkCommand: Remove user from network
    - Validates no children exist (must move/remove first)
    - Soft delete (sets NetworkParentId to null)
    - Idempotent design

- Implemented 3 Queries with handlers, validators, and DTOs:
  * GetNetworkTreeQuery: Binary tree visualization
    - Recursive tree building with MaxDepth limit (1-10)
    - Returns nested structure with Left/Right children
  * GetUserNetworkPositionQuery: User position details
    - Parent info, leg position, children counts
    - Left/Right child counts for balance view
  * GetNetworkMembershipHistoryQuery: Complete audit trail
    - Filter by UserId, pagination support
    - Shows Join/Move/Remove actions with full details

- All operations include complete history tracking
- Binary tree validation (parent-child relationships)
- Circular dependency prevention in MoveInNetwork
- 21 new files, ~850 lines of code
- Build successful with 0 errors
2025-11-29 04:19:40 +03:30

70 lines
2.4 KiB
C#

namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.RemoveFromNetwork;
public class RemoveFromNetworkCommandHandler : IRequestHandler<RemoveFromNetworkCommand, Unit>
{
private readonly IApplicationDbContext _context;
public RemoveFromNetworkCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(RemoveFromNetworkCommand 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)
{
// اگر قبلاً حذف شده، هیچ کاری نکن (Idempotent)
return Unit.Value;
}
// بررسی وجود فرزندان
var hasChildren = await _context.Users
.AnyAsync(x => x.NetworkParentId == request.UserId, cancellationToken);
if (hasChildren)
{
throw new InvalidOperationException(
$"کاربر با شناسه {request.UserId} دارای فرزند در شبکه است. ابتدا باید فرزندان جابجا یا حذف شوند");
}
// ذخیره مقادیر قبلی برای History
var oldParentId = user.NetworkParentId;
var oldLegPosition = user.LegPosition;
// حذف از شبکه (Soft Delete)
user.NetworkParentId = null;
user.LegPosition = null;
_context.Users.Update(user);
await _context.SaveChangesAsync(cancellationToken);
// ثبت تاریخچه
var history = new NetworkMembershipHistory
{
UserId = request.UserId,
OldParentId = oldParentId,
NewParentId = null,
OldLegPosition = oldLegPosition,
NewLegPosition = null,
Action = NetworkMembershipAction.Remove,
Reason = request.Reason ?? "حذف از شبکه",
PerformedBy = "System" // TODO: باید از Current User گرفته شود
};
await _context.NetworkMembershipHistories.AddAsync(history, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
}