Handler.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. namespace Application.Features.Api.Stocks.GetMacroIndicators;
  5. /// <summary>
  6. /// 거시경제지표 조회 — 지표코드별 최근 시점 추이 + 최신값 (KOSIS 수집, 익명). Codes 비면 적재된 전 지표.
  7. /// 지표당 최근 Limit 시점을 시점 내림차순으로 뽑은 뒤 오름차순으로 되돌려(Points) 대시보드 차트에 그대로 쓴다.
  8. /// </summary>
  9. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
  10. {
  11. private const int DefaultLimit = 60;
  12. private const int MaxLimit = 240;
  13. public async Task<Response> Handle(Query request, CancellationToken ct)
  14. {
  15. var limit = request.Limit > 0 ? Math.Min(request.Limit, MaxLimit) : DefaultLimit;
  16. var codes = request.Codes?.Where(c => !string.IsNullOrWhiteSpace(c)).Select(c => c.Trim()).ToList() ?? [];
  17. var query = db.MacroIndicator.AsNoTracking();
  18. if (codes.Count > 0)
  19. {
  20. query = query.Where(c => codes.Contains(c.Code));
  21. }
  22. var rows = await query
  23. .Select(c => new
  24. {
  25. c.Code,
  26. c.Name,
  27. c.Period,
  28. c.Value,
  29. c.Unit
  30. })
  31. .ToListAsync(ct);
  32. var indicators = rows
  33. .GroupBy(c => c.Code)
  34. .Select(g =>
  35. {
  36. var ordered = g.OrderByDescending(c => c.Period).Take(limit).OrderBy(c => c.Period).ToList();
  37. var latest = ordered.Count > 0 ? ordered[^1] : null;
  38. return new Response.Indicator
  39. {
  40. Code = g.Key,
  41. Name = latest?.Name ?? g.First().Name,
  42. Unit = latest?.Unit,
  43. LatestPeriod = latest?.Period,
  44. LatestValue = latest?.Value,
  45. Points = ordered.Select(c => new Response.Point
  46. {
  47. Period = c.Period,
  48. Value = c.Value
  49. }).ToList()
  50. };
  51. })
  52. .OrderBy(c => c.Code)
  53. .ToList();
  54. return new Response
  55. {
  56. Total = indicators.Count,
  57. List = indicators
  58. };
  59. }
  60. }