using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Microsoft.EntityFrameworkCore; namespace Application.Features.Director.AccessLog.Search; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.AdminAccessLog.AsNoTracking().AsQueryable(); // 키워드 검색 if (!string.IsNullOrWhiteSpace(request.Keyword)) { var kw = request.Keyword.Trim(); query = request.Search switch { 1 => query.Where(x => x.UserID.Contains(kw)), 2 => query.Where(x => x.Path.Contains(kw)), 3 => query.Where(x => x.IpAddress != null && x.IpAddress.Contains(kw)), 4 => query.Where(x => x.MenuName != null && x.MenuName.Contains(kw)), _ => query.Where(x => x.UserID.Contains(kw)) }; } // Method 필터 if (!string.IsNullOrWhiteSpace(request.Method)) { query = query.Where(x => x.Method == request.Method); } // 날짜 필터 if (!string.IsNullOrWhiteSpace(request.StartAt) && DateTime.TryParse(request.StartAt, out var startAt)) { query = query.Where(x => x.CreatedAt >= startAt); } if (!string.IsNullOrWhiteSpace(request.EndAt) && DateTime.TryParse(request.EndAt, out var endAt)) { query = query.Where(x => x.CreatedAt <= endAt); } var total = await query.CountAsync(ct); var skip = (request.PageNum - 1) * request.PerPage; var list = await query .OrderByDescending(x => x.ID) .Skip(skip) .Take(request.PerPage) .Select(x => new { x.ID, x.UserID, x.UserName, x.Method, x.Path, x.QueryString, x.StatusCode, x.ElapsedMs, x.MenuName, x.IpAddress, x.UserAgent, x.CreatedAt }) .ToListAsync(ct); var rows = list.Select((x, idx) => new Response.Row { Num = total - skip - idx, ID = x.ID, UserID = x.UserID, UserName = x.UserName, Method = x.Method, Path = x.Path, QueryString = x.QueryString, StatusCode = x.StatusCode, ElapsedMs = x.ElapsedMs, MenuName = x.MenuName, IpAddress = x.IpAddress, UserAgent = x.UserAgent, CreatedAt = x.CreatedAt }).ToList(); return new Response { Total = total, List = rows }; } }