| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Stocks.GetMacroIndicators;
- /// <summary>
- /// 거시경제지표 조회 — 지표코드별 최근 시점 추이 + 최신값 (KOSIS 수집, 익명). Codes 비면 적재된 전 지표.
- /// 지표당 최근 Limit 시점을 시점 내림차순으로 뽑은 뒤 오름차순으로 되돌려(Points) 대시보드 차트에 그대로 쓴다.
- /// </summary>
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
- {
- private const int DefaultLimit = 60;
- private const int MaxLimit = 240;
- public async Task<Response> 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
- };
- }
- }
|