using Application.Abstractions.Data; using Application.Abstractions.Messaging; using SharedKernel.Results; using Domain.Entities.Donations; using Domain.Entities.Donations.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.DonationGoal.SaveConfig; internal sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command r, CancellationToken ct) { var period = (RankPeriodType)r.Period; // Custom 시 StartAt/EndAt 필수 if (period == RankPeriodType.Custom && (!r.StartAt.HasValue || !r.EndAt.HasValue)) { return Result.Failure(Error.Problem("DonationGoal.CustomPeriodRequired", "사용자 지정 기간은 시작일/종료일이 필요합니다.")); } // 기간 중복 검증: 활성 + Custom 끼리만 if (r.IsActive && period == RankPeriodType.Custom && r.StartAt.HasValue && r.EndAt.HasValue) { var overlap = await db.DonationGoalConfig .AnyAsync(c => c.ChannelID == r.ChannelID && c.IsActive && c.Period == RankPeriodType.Custom && c.ID != (r.ID ?? 0) && c.StartAt != null && c.EndAt != null && c.StartAt < r.EndAt && c.EndAt > r.StartAt, ct ); if (overlap) { return Result.Failure(Error.Conflict("DonationGoal.PeriodOverlap", "해당 기간에 이미 활성화된 목표가 존재합니다.")); } } if (r.ID.HasValue) { var config = await db.DonationGoalConfig.FirstOrDefaultAsync(c => c.ID == r.ID.Value && c.ChannelID == r.ChannelID, ct); if (config is null) { return Result.Failure(Error.NotFound("DonationGoal.NotFound", "설정을 찾을 수 없습니다.")); } config.Update( r.Title, (GoalWidgetStyle)r.Style, r.StartAmount, r.TargetAmount, r.StartAt, r.EndAt, r.IsShowPercent, r.BarColor, r.BarBackgroundColor, r.BarHeightPx, r.TitleFontSizePx, r.TitleFontColor, r.AmountFontSizePx, r.AmountFontColor, r.TitleFontFamily, r.AmountFontFamily, period, r.IsActive ); } else { var config = DonationGoalConfig.Create(r.ChannelID, r.MemberID, r.Title, r.TargetAmount); config.Update( r.Title, (GoalWidgetStyle)r.Style, r.StartAmount, r.TargetAmount, r.StartAt, r.EndAt, r.IsShowPercent, r.BarColor, r.BarBackgroundColor, r.BarHeightPx, r.TitleFontSizePx, r.TitleFontColor, r.AmountFontSizePx, r.AmountFontColor, r.TitleFontFamily, r.AmountFontFamily, period, r.IsActive ); db.DonationGoalConfig.Add(config); } await db.SaveChangesAsync(ct); return Result.Success(); } }