using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Stocks.GetMacroIndicators; /// /// 거시경제지표 조회 — 지표코드별 최근 시점 추이 + 최신값 (KOSIS 수집, 익명). Codes 비면 적재된 전 지표. /// 지표당 최근 Limit 시점을 시점 내림차순으로 뽑은 뒤 오름차순으로 되돌려(Points) 대시보드 차트에 그대로 쓴다. /// internal sealed class Handler(IAppDbContext db) : IQueryHandler { private const int DefaultLimit = 60; private const int MaxLimit = 240; public async Task Handle(Query request, CancellationToken ct) { var limit = request.Limit > 0 ? Math.Min(request.Limit, MaxLimit) : DefaultLimit; var codes = request.Codes?.Where(c => !string.IsNullOrWhiteSpace(c)).Select(c => c.Trim()).ToList() ?? []; var query = db.MacroIndicator.AsNoTracking(); if (codes.Count > 0) { query = query.Where(c => codes.Contains(c.Code)); } var rows = await query .Select(c => new { c.Code, c.Name, c.Period, c.Value, c.Unit }) .ToListAsync(ct); var indicators = rows .GroupBy(c => c.Code) .Select(g => { var ordered = g.OrderByDescending(c => c.Period).Take(limit).OrderBy(c => c.Period).ToList(); var latest = ordered.Count > 0 ? ordered[^1] : null; return new Response.Indicator { Code = g.Key, Name = latest?.Name ?? g.First().Name, Unit = latest?.Unit, LatestPeriod = latest?.Period, LatestValue = latest?.Value, Points = ordered.Select(c => new Response.Point { Period = c.Period, Value = c.Value }).ToList() }; }) .OrderBy(c => c.Code) .ToList(); return new Response { Total = indicators.Count, List = indicators }; } }