Handler.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. using SharedKernel.Results;
  5. namespace Application.Features.Api.Member.Follow.Toggle;
  6. public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result<Response>>
  7. {
  8. public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
  9. {
  10. var followee = await db.Member.AsNoTracking().Where(x => x.SID == request.FolloweeSID && !x.IsWithdraw).Select(x => new { x.ID }).FirstOrDefaultAsync(ct);
  11. if (followee is null)
  12. {
  13. return Result.Failure<Response>(Error.NotFound("Follow.MemberNotFound", "회원을 찾을 수 없습니다."));
  14. }
  15. if (followee.ID == request.FollowerMemberID)
  16. {
  17. return Result.Failure<Response>(Error.Problem("Follow.Self", "자기 자신을 팔로우할 수 없습니다."));
  18. }
  19. var existing = await db.MemberFollow.FirstOrDefaultAsync(x => x.FollowerMemberID == request.FollowerMemberID && x.FolloweeMemberID == followee.ID, ct);
  20. var followerStats = await db.MemberStats.FirstOrDefaultAsync(x => x.MemberID == request.FollowerMemberID, ct);
  21. var followeeStats = await db.MemberStats.FirstOrDefaultAsync(x => x.MemberID == followee.ID, ct);
  22. // 기존 회원이 MemberStats 없는 경우 자가 복구 — 과거 가입 경로에서 누락된 데이터 메우기
  23. if (followerStats is null)
  24. {
  25. followerStats = Domain.Entities.Members.MemberStats.Create(request.FollowerMemberID);
  26. await db.MemberStats.AddAsync(followerStats, ct);
  27. }
  28. if (followeeStats is null)
  29. {
  30. followeeStats = Domain.Entities.Members.MemberStats.Create(followee.ID);
  31. await db.MemberStats.AddAsync(followeeStats, ct);
  32. }
  33. bool isFollowing;
  34. if (existing is not null)
  35. {
  36. db.MemberFollow.Remove(existing);
  37. followerStats.FollowingCount = Math.Max(0, followerStats.FollowingCount - 1);
  38. followeeStats.FollowerCount = Math.Max(0, followeeStats.FollowerCount - 1);
  39. isFollowing = false;
  40. }
  41. else
  42. {
  43. var follow = Domain.Entities.Members.MemberFollow.Create(request.FollowerMemberID, followee.ID);
  44. db.MemberFollow.Add(follow);
  45. followerStats.FollowingCount += 1;
  46. followeeStats.FollowerCount += 1;
  47. isFollowing = true;
  48. }
  49. await db.SaveChangesAsync(ct);
  50. return new Response(isFollowing, followeeStats.FollowerCount);
  51. }
  52. }