| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using Application.Abstractions.Messaging;
- using Application.Abstractions.Data;
- using Domain.Entities.Forum.ValueObject;
- using SharedKernel.Results;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Forum.PostReaction.Toggle;
- public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result>
- {
- public async Task<Result> Handle(Command request, CancellationToken ct)
- {
- var post = await db.Post.FirstOrDefaultAsync(x => x.ID == request.PostID, ct);
- if (post is null)
- {
- return Result.Failure(Error.NotFound("PostReaction.PostNotFound", "게시글을 찾을 수 없습니다."));
- }
- var existing = await db.PostReaction.FirstOrDefaultAsync(x => x.PostID == request.PostID && x.MemberID == request.MemberID, ct);
- // MemberStats 조회 (Like만 카운트) — 1회 쿼리로 giver/receiver 동시 로드
- var memberIDs = post.MemberID.HasValue && post.MemberID.Value != request.MemberID
- ? new[] { request.MemberID, post.MemberID.Value }
- : new[] { request.MemberID };
- var statsList = await db.MemberStats
- .Where(x => memberIDs.Contains(x.MemberID))
- .ToListAsync(ct);
- var giverStats = statsList.FirstOrDefault(x => x.MemberID == request.MemberID);
- var receiverStats = post.MemberID.HasValue && post.MemberID.Value != request.MemberID
- ? statsList.FirstOrDefault(x => x.MemberID == post.MemberID.Value)
- : null;
- if (existing is not null)
- {
- // 같은 반응이면 취소
- if (existing.Reaction == request.Reaction)
- {
- if (existing.Reaction == Reaction.Like)
- {
- post.Likes--;
- if (giverStats is not null) { giverStats.LikeGivenCount--; }
- if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
- }
- else
- {
- post.Dislikes--;
- }
- db.PostReaction.Remove(existing);
- }
- else
- {
- // 다른 반응이면 전환
- if (existing.Reaction == Reaction.Like)
- {
- post.Likes--;
- post.Dislikes++;
- // Like → Dislike: Like 카운트 감소
- if (giverStats is not null) { giverStats.LikeGivenCount--; }
- if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
- }
- else
- {
- post.Dislikes--;
- post.Likes++;
- // Dislike → Like: Like 카운트 증가
- if (giverStats is not null) { giverStats.LikeGivenCount++; }
- if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
- }
- existing.Reaction = request.Reaction;
- existing.UpdatedAt = DateTime.UtcNow;
- }
- }
- else
- {
- // 새 반응
- var reaction = new Domain.Entities.Forum.Posts.PostReaction
- {
- BoardID = post.BoardID,
- PostID = request.PostID,
- MemberID = request.MemberID,
- Reaction = request.Reaction
- };
- await db.PostReaction.AddAsync(reaction, ct);
- if (request.Reaction == Reaction.Like)
- {
- post.Likes++;
- if (giverStats is not null) { giverStats.LikeGivenCount++; }
- if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
- }
- else
- {
- post.Dislikes++;
- }
- }
- await db.SaveChangesAsync(ct);
- return Result.Success();
- }
- }
|