Handler.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. namespace Application.Features.Api.Crew.SaveWidgetConfig;
  7. internal sealed class Handler(IAppDbContext db) : ICommandHandler<Command>
  8. {
  9. public async Task Handle(Command r, CancellationToken ct)
  10. {
  11. var theme = (CrewWidgetTheme)r.Theme;
  12. var period = (RankPeriodType)r.Period;
  13. // 기간 중복 검증 (활성 설정만)
  14. if (r.IsActive)
  15. {
  16. if (period == RankPeriodType.Custom && r.StartAt.HasValue && r.EndAt.HasValue)
  17. {
  18. // Custom 기간: 날짜 겹침 체크
  19. var overlapping = await db.CrewWidgetConfig
  20. .AnyAsync(c => c.ChannelID == r.ChannelID
  21. && (!r.ID.HasValue || c.ID != r.ID.Value)
  22. && c.IsActive
  23. && c.Period == RankPeriodType.Custom
  24. && c.StartAt < r.EndAt && c.EndAt > r.StartAt, ct);
  25. if (overlapping)
  26. {
  27. throw new InvalidOperationException("기간이 겹치는 활성 설정이 있습니다.");
  28. }
  29. }
  30. else
  31. {
  32. // 같은 기간 타입에 활성 설정 1개만
  33. var existing = await db.CrewWidgetConfig
  34. .AnyAsync(c => c.ChannelID == r.ChannelID
  35. && (!r.ID.HasValue || c.ID != r.ID.Value)
  36. && c.IsActive
  37. && c.Period == period, ct);
  38. if (existing)
  39. {
  40. throw new InvalidOperationException("같은 기간의 활성 설정이 이미 있습니다.");
  41. }
  42. }
  43. }
  44. if (r.ID.HasValue)
  45. {
  46. var config = await db.CrewWidgetConfig
  47. .FirstOrDefaultAsync(c => c.ID == r.ID.Value && c.ChannelID == r.ChannelID, ct);
  48. if (config is null)
  49. {
  50. throw new KeyNotFoundException("설정을 찾을 수 없습니다.");
  51. }
  52. config.Update(
  53. r.Title, theme, period, r.StartAt, r.EndAt,
  54. r.MaxDisplayCount, r.IsShowAmount, r.IsShowDonationCount,
  55. r.IsShowContributionRate, r.IsShowMemberIcon, r.IsActive, r.BgColor,
  56. r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor,
  57. r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor,
  58. r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor,
  59. r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor,
  60. r.RowFontFamily, r.RowFontSizePx, r.RowFontColor
  61. );
  62. }
  63. else
  64. {
  65. var config = CrewWidgetConfig.Create(
  66. r.ChannelID, r.MemberID, r.Title,
  67. theme, period, r.StartAt, r.EndAt,
  68. r.MaxDisplayCount, r.IsShowAmount, r.IsShowDonationCount,
  69. r.IsShowContributionRate, r.IsShowMemberIcon, r.IsActive, r.BgColor,
  70. r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor,
  71. r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor,
  72. r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor,
  73. r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor,
  74. r.RowFontFamily, r.RowFontSizePx, r.RowFontColor
  75. );
  76. db.CrewWidgetConfig.Add(config);
  77. }
  78. await db.SaveChangesAsync(ct);
  79. }
  80. }