Handler.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using Domain.Entities.Forum.ValueObject;
  4. using SharedKernel.Results;
  5. using Microsoft.EntityFrameworkCore;
  6. namespace Application.Features.Api.Forum.CommentReaction.Toggle;
  7. public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result>
  8. {
  9. public async Task<Result> Handle(Command request, CancellationToken ct)
  10. {
  11. var comment = await db.Comment.FirstOrDefaultAsync(x => x.ID == request.CommentID, ct);
  12. if (comment is null)
  13. {
  14. return Result.Failure(Error.NotFound("CommentReaction.CommentNotFound", "댓글을 찾을 수 없습니다."));
  15. }
  16. var existing = await db.CommentReaction.FirstOrDefaultAsync(x => x.CommentID == request.CommentID && x.MemberID == request.MemberID, ct);
  17. // MemberStats 조회 (Like만 카운트) — 1회 쿼리로 giver/receiver 동시 로드
  18. var memberIDs = comment.MemberID != request.MemberID ? new[] { request.MemberID, comment.MemberID } : [request.MemberID];
  19. var statsList = await db.MemberStats.Where(x => memberIDs.Contains(x.MemberID)).ToListAsync(ct);
  20. var giverStats = statsList.FirstOrDefault(x => x.MemberID == request.MemberID);
  21. var receiverStats = comment.MemberID != request.MemberID ? statsList.FirstOrDefault(x => x.MemberID == comment.MemberID) : null;
  22. if (existing is not null)
  23. {
  24. if (existing.Reaction == request.Reaction)
  25. {
  26. if (existing.Reaction == Reaction.Like)
  27. {
  28. comment.Likes--;
  29. if (giverStats is not null) { giverStats.LikeGivenCount--; }
  30. if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
  31. }
  32. else
  33. {
  34. comment.Dislikes--;
  35. }
  36. db.CommentReaction.Remove(existing);
  37. }
  38. else
  39. {
  40. if (existing.Reaction == Reaction.Like)
  41. {
  42. comment.Likes--;
  43. comment.Dislikes++;
  44. // Like → Dislike: Like 카운트 감소
  45. if (giverStats is not null) { giverStats.LikeGivenCount--; }
  46. if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
  47. }
  48. else
  49. {
  50. comment.Dislikes--;
  51. comment.Likes++;
  52. // Dislike → Like: Like 카운트 증가
  53. if (giverStats is not null) { giverStats.LikeGivenCount++; }
  54. if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
  55. }
  56. existing.Reaction = request.Reaction;
  57. existing.UpdatedAt = DateTime.UtcNow;
  58. }
  59. }
  60. else
  61. {
  62. var reaction = new Domain.Entities.Forum.Comments.CommentReaction
  63. {
  64. BoardID = comment.BoardID,
  65. PostID = comment.PostID,
  66. CommentID = request.CommentID,
  67. MemberID = request.MemberID,
  68. Reaction = request.Reaction
  69. };
  70. await db.CommentReaction.AddAsync(reaction, ct);
  71. if (request.Reaction == Reaction.Like)
  72. {
  73. comment.Likes++;
  74. if (giverStats is not null) { giverStats.LikeGivenCount++; }
  75. if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
  76. }
  77. else
  78. {
  79. comment.Dislikes++;
  80. }
  81. }
  82. await db.SaveChangesAsync(ct);
  83. return Result.Success();
  84. }
  85. }