using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Store.Coupon.ListCodes; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var baseQuery = db.CouponCode.AsNoTracking().Where(c => c.CouponID == request.CouponID); // 상태별 카운트 (필터 무관, 전체 통계) var counts = await db.CouponCode .AsNoTracking() .Where(c => c.CouponID == request.CouponID) .GroupBy(c => c.Status) .Select(g => new { Status = g.Key, Count = g.Count() }) .ToListAsync(ct); var available = counts.FirstOrDefault(x => x.Status == CouponCodeStatus.Available)?.Count ?? 0; var reserved = counts.FirstOrDefault(x => x.Status == CouponCodeStatus.Reserved)?.Count ?? 0; var issued = counts.FirstOrDefault(x => x.Status == CouponCodeStatus.Issued)?.Count ?? 0; var used = counts.FirstOrDefault(x => x.Status == CouponCodeStatus.Used)?.Count ?? 0; var expired = counts.FirstOrDefault(x => x.Status == CouponCodeStatus.Expired)?.Count ?? 0; // 필터 적용 var query = baseQuery; if (request.Status.HasValue) { query = query.Where(c => c.Status == request.Status.Value); } var total = await query.CountAsync(ct); var list = await query .Include(c => c.IssuedToMember) .OrderByDescending(c => c.ID) .Skip((request.Page - 1) * request.PerPage) .Take(request.PerPage) .Select(c => new { c.ID, c.Code, c.Status, c.IssuedToMemberID, IssuedToMemberName = c.IssuedToMember != null ? c.IssuedToMember.Name : null, IssuedToMemberEmail = c.IssuedToMember != null ? c.IssuedToMember.Email : null, c.IssuedAt, c.UsedAt, c.CreatedAt }) .ToListAsync(ct); var startNum = total - ((request.Page - 1) * request.PerPage); return new Response( Total: total, AvailableCount: available, ReservedCount: reserved, IssuedCount: issued, UsedCount: used, ExpiredCount: expired, List: [.. list.Select((c, i) => new Response.Row( Num: startNum - i, c.ID, c.Code, c.Status, c.IssuedToMemberID, c.IssuedToMemberName, c.IssuedToMemberEmail, c.IssuedAt, c.UsedAt, c.CreatedAt ))] ); } }