CrewSessionConsent.cs 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Application.Abstractions.Hub;
  2. using Infrastructure.Hubs;
  3. using Web.Api.Common;
  4. using MediatR;
  5. using Microsoft.AspNetCore.SignalR;
  6. namespace Web.Api.Endpoints.Donation;
  7. /// <summary>크루원 참여 동의 — 동의 후 전원 동의 시 세션 활성화</summary>
  8. internal sealed class CrewSessionConsent : IEndpoint
  9. {
  10. public void MapEndpoint(IEndpointRouteBuilder app)
  11. {
  12. app.MapPost("api/crew/session/consent", async (
  13. Application.Features.Api.Crew.ConsentSession.Command body,
  14. ISender sender,
  15. IHubContext<AppHub, IAppHubClient> appHub,
  16. Application.Abstractions.Data.IAppDbContext db,
  17. CancellationToken ct
  18. ) => {
  19. var result = await sender.Send(body, ct);
  20. if (result.IsFailure)
  21. {
  22. return CustomResults.Problem(result);
  23. }
  24. var data = result.Value;
  25. // 세션의 크루 채널SID 조회
  26. var session = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  27. .FirstOrDefaultAsync(
  28. Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  29. .AsNoTracking(db.CrewSession)
  30. .Where(s => s.ID == body.CrewSessionID),
  31. ct
  32. );
  33. if (session is not null)
  34. {
  35. var crew = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  36. .FirstOrDefaultAsync(
  37. Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  38. .AsNoTracking(db.Crew)
  39. .Where(c => c.ID == session.CrewID),
  40. ct
  41. );
  42. if (crew is not null)
  43. {
  44. var channel = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  45. .FirstOrDefaultAsync(
  46. Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  47. .AsNoTracking(db.Channel)
  48. .Where(c => c.ID == crew.ChannelID),
  49. ct
  50. );
  51. var channelSID = channel?.SID ?? "";
  52. // 동의 현황 브로드캐스트 (크루장에게)
  53. var consents = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  54. .ToListAsync(
  55. Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions
  56. .AsNoTracking(db.CrewSessionConsent)
  57. .Where(c => c.CrewSessionID == body.CrewSessionID)
  58. .Join(db.CrewMember, c => c.CrewMemberID, m => m.ID, (c, m) => new {
  59. c.CrewMemberID, m.Nickname, c.IsConsented, c.ConsentedAt
  60. }),
  61. ct
  62. );
  63. await appHub.Clients.Group($"channel:{channelSID}").ReceiveCrewConsentUpdate(new
  64. {
  65. CrewSessionID = body.CrewSessionID,
  66. Consents = consents,
  67. AllConsented = data.AllConsented
  68. });
  69. // 전원 동의 시 세션 시작 브로드캐스트
  70. if (data.AllConsented)
  71. {
  72. await appHub.Clients.Group($"channel:{channelSID}").ReceiveCrewStarted(new
  73. {
  74. CrewSessionID = body.CrewSessionID,
  75. Title = session.Title,
  76. CrewName = crew.Name
  77. });
  78. }
  79. }
  80. }
  81. return ApiResponse.Ok(data);
  82. })
  83. .WithTags("Crew")
  84. .RequireAuthorization();
  85. }
  86. }