Handler.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.Donations;
  4. using Domain.Entities.Donations.ValueObject;
  5. using Microsoft.EntityFrameworkCore;
  6. using SharedKernel.Results;
  7. namespace Application.Features.Api.DonationRemote.ResendAlert;
  8. internal sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result<Response>>
  9. {
  10. public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
  11. {
  12. var alert = await db.DonationAlert
  13. .Include(a => a.Donation)
  14. .ThenInclude(d => d!.Channel)
  15. .Include(a => a.Donation)
  16. .ThenInclude(d => d!.CrewMember)
  17. .FirstOrDefaultAsync(a => a.ID == request.AlertID, ct);
  18. if (alert is null || alert.Donation is null || alert.Donation.Channel is null)
  19. {
  20. return Result.Failure<Response>(Error.NotFound("DonationAlert.NotFound", "알림을 찾을 수 없습니다."));
  21. }
  22. // 권한 체크 — 본인 채널 알림만 재전송 가능 (PlayNow 와 동일 패턴)
  23. if (alert.Donation.Channel.MemberID != request.RequesterMemberID)
  24. {
  25. return Result.Failure<Response>(Error.Forbidden("Remote.Forbidden", "권한이 없습니다."));
  26. }
  27. // 이미 큐에 있거나 재생 중이면 거부 — 그 외 종결 상태(Failed/Skipped/Ignored/Delivered) 전부 재전송 허용
  28. if (alert.Status is AlertStatus.Queued or AlertStatus.Playing)
  29. {
  30. return Result.Failure<Response>(Error.Problem("DonationAlert.AlreadyActive", "이미 대기 중이거나 재생 중인 알림입니다."));
  31. }
  32. alert.Resend();
  33. var attempt = DonationAlertAttempt.Create(alert.DonationID, alert.ID);
  34. await db.DonationAlertAttempt.AddAsync(attempt, ct);
  35. await db.SaveChangesAsync(ct);
  36. return Result.Success(new Response(
  37. alert.ID,
  38. alert.DonationID,
  39. alert.CorrelationID,
  40. alert.Donation.SendName,
  41. alert.Donation.Amount,
  42. alert.Donation.NetAmount,
  43. alert.Donation.Message,
  44. alert.Donation.ChannelID,
  45. alert.Donation.Channel.Name,
  46. alert.Donation.Channel.WidgetToken!,
  47. alert.Donation.CrewMemberID,
  48. alert.Donation.CrewMember?.Nickname,
  49. alert.Donation.IsTest
  50. ));
  51. }
  52. }