Handler.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Hub;
  3. using Application.Abstractions.Messaging;
  4. using SharedKernel;
  5. using SharedKernel.Results;
  6. using Domain.Entities.Donations.ValueObject;
  7. using Microsoft.EntityFrameworkCore;
  8. namespace Application.Features.Api.Crew.RemoveMember;
  9. internal sealed class Handler(
  10. IAppDbContext db,
  11. ICrewHubBroadcaster crewBroadcaster
  12. ) : ICommandHandler<Command, Result>
  13. {
  14. public async Task<Result> Handle(Command request, CancellationToken ct)
  15. {
  16. var member = await db.CrewMember
  17. .FirstOrDefaultAsync(m => m.ID == request.CrewMemberID, ct);
  18. if (member is null)
  19. {
  20. return Result.Failure(Error.NotFound("Crew.MemberNotFound", "크루원을 찾을 수 없습니다."));
  21. }
  22. // 진행 중인 세션이 있으면 삭제 불가
  23. var hasActiveSession = await db.CrewSession
  24. .AnyAsync(s => s.CrewID == member.CrewID && s.Status != CrewSessionStatus.Ended, ct);
  25. if (hasActiveSession)
  26. {
  27. return Result.Failure(Error.Conflict("Crew.ActiveSessionExists", "진행 중인 크루 방송이 있어 삭제할 수 없습니다."));
  28. }
  29. // EF Remove 후 추적 해제될 수 있으니 broadcast 에 필요한 ID 미리 캐싱
  30. var crewID = member.CrewID;
  31. var crewMemberID = member.ID;
  32. var memberID = member.MemberID;
  33. db.CrewMember.Remove(member);
  34. await db.SaveChangesAsync(ct);
  35. // 운영자 그룹에 삭제 broadcast
  36. await crewBroadcaster.BroadcastMemberChangeAsync(
  37. crewID: crewID,
  38. kind: "removed",
  39. data: new
  40. {
  41. crewMemberID,
  42. memberID
  43. },
  44. ct: ct
  45. );
  46. return Result.Success();
  47. }
  48. }