using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Application.Abstractions.Forum; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Api.Forum.Post.Delete; public sealed class Handler(IAppDbContext db, IBoardPermissionService permissionService) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { var post = await db.Post.FirstOrDefaultAsync(x => x.ID == request.ID, ct); if (post is null) { return Result.Failure(Error.NotFound("Post.NotFound", "게시글을 찾을 수 없습니다.")); } if (post.MemberID != request.MemberID) { var reqMember = await db.Member.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.MemberID, ct); if (reqMember is null || !reqMember.IsAdmin) { var mgr = await permissionService.GetBoardManagerAsync(post.BoardID, request.MemberID, ct); if (mgr is null || !mgr.CanDelete) { return Result.Failure(Error.Forbidden("Post.Forbidden", "삭제 권한이 없습니다.")); } } } post.IsDeleted = true; post.DeletedAt = DateTime.UtcNow; // Board 게시글 카운트 감소 var board = await db.Board.FirstOrDefaultAsync(x => x.ID == post.BoardID, ct); if (board is not null) { board.Posts--; board.UpdatedAt = DateTime.UtcNow; var boardGroup = await db.BoardGroup.FirstOrDefaultAsync(x => x.ID == board.BoardGroupID, ct); if (boardGroup is not null) { boardGroup.Posts--; boardGroup.UpdatedAt = DateTime.UtcNow; } } // MemberStats 게시글 수 감소 if (post.MemberID.HasValue) { var memberStats = await db.MemberStats.FirstOrDefaultAsync(x => x.MemberID == post.MemberID.Value, ct); if (memberStats is not null) { memberStats.PostCount--; } } await db.SaveChangesAsync(ct); return Result.Success(); } }