using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Application.Common; using Domain.Entities.Wallets.ValueObject; using SharedKernel.Results; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.MyPage.DonationLogs; internal sealed class Handler(IAppDbContext db) : IQueryHandler> { public async Task> Handle(Query request, CancellationToken ct) { var page = request.Page < 1 ? 1 : request.Page; var perPage = request.PerPage is < 1 or > 50 ? 20 : request.PerPage; var now = DateTime.UtcNow; var startDate = request.Type switch { SearchDateType.Week => now.AddDays(-7), SearchDateType.Month => now.AddMonths(-1), SearchDateType.QuarterYear => now.AddMonths(-3), SearchDateType.HalfYear => now.AddMonths(-6), _ => now.Date }; var baseQuery = db.Donation.AsNoTracking().Where(d => d.SponsorMemberID == request.MemberID && d.CreatedAt >= startDate); var total = await baseQuery.CountAsync(ct); // Donation ↔ WalletTransaction 매칭: TxType=DonationOut, BalanceType=PgCharged, RefID == Donation.ID.ToString() var list = await baseQuery .OrderByDescending(d => d.CreatedAt) .Skip((page - 1) * perPage) .Take(perPage) .Select(d => new DonationLogItem( d.ID, d.CreatedAt, d.SendName, d.Channel != null ? d.Channel.Name : null, d.Message, d.Amount, db.WalletTransaction .Where(t => t.TxType == WalletTransactionType.DonationOut && t.BalanceType == WalletBalanceType.PgCharged && t.RefID == d.ID.ToString()) .OrderByDescending(t => t.CreatedAt) .Select(t => (long?)t.BalanceAfter.Value) .FirstOrDefault(), d.CrewSessionID != null, d.IsTest )) .ToListAsync(ct); return Result.Success(new Response(list, total, page, perPage)); } }