| 1234567891011121314151617181920212223242526272829303132333435363738394041424344 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Domain.Entities.Donations.ValueObject;
- using SharedKernel.Results;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.DonationGoal.GetProgress;
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
- {
- public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
- {
- var goal = await db.DonationGoalConfig.AsNoTracking().FirstOrDefaultAsync(g => g.ID == request.GoalConfigID && g.ChannelID == request.ChannelID && g.IsActive, ct);
- if (goal is null)
- {
- return Result.Failure<Response>(Error.NotFound("DonationGoal.NotFound", "목표 설정을 찾을 수 없습니다."));
- }
- // Period 기반 시간 범위 계산
- var now = DateTime.UtcNow;
- DateTime? rangeStart = goal.Period switch
- {
- RankPeriodType.Daily => now.Date,
- RankPeriodType.Weekly => now.Date.AddDays(-(int)now.DayOfWeek),
- RankPeriodType.Monthly => new DateTime(now.Year, now.Month, 1, 0, 0, 0, DateTimeKind.Utc),
- RankPeriodType.Yearly => new DateTime(now.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc),
- RankPeriodType.Custom => goal.StartAt,
- _ => null // AllTime
- };
- DateTime? rangeEnd = goal.Period == RankPeriodType.Custom ? goal.EndAt : null;
- var currentAmount = await db.Donation.AsNoTracking()
- .Where(d => d.ChannelID == request.ChannelID
- && !d.IsTest
- && (rangeStart == null || d.CreatedAt >= rangeStart)
- && (rangeEnd == null || d.CreatedAt <= rangeEnd))
- .SumAsync(d => d.Amount, ct);
- var adjusted = currentAmount + goal.StartAmount;
- var percent = goal.TargetAmount > 0 ? Math.Min((decimal)adjusted / goal.TargetAmount * 100, 100) : 0;
- return Result.Success(new Response(goal.ID, goal.Title, goal.StartAmount, goal.TargetAmount, adjusted, Math.Round(percent, 1)));
- }
- }
|