Handler.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.Stocks.ValueObject;
  4. using Microsoft.EntityFrameworkCore;
  5. namespace Application.Features.Api.Stocks.GetWorldIndices;
  6. /// <summary>
  7. /// 세계 주요국 증시지수 병합 — 국내(코스피)는 IndexDailyPrice 최신 거래일 실데이터, 해외는 WorldIndexSnapshot(나라당 1개).
  8. /// 국가 코드(ISO2)로 프론트가 세계지도 핀 좌표를 매핑한다. 해외 스냅샷에 KR 이 섞여도 중복 방지로 제외.
  9. /// </summary>
  10. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
  11. {
  12. public async Task<Response> Handle(Query request, CancellationToken ct)
  13. {
  14. var rows = new List<Response.Row>();
  15. // 국내(코스피) — IndexDailyPrice 최신 거래일. 한국 핀은 KRX 실데이터 사용.
  16. var latestKr = await db.IndexDailyPrice.AsNoTracking().OrderByDescending(c => c.TradeDate).Select(c => (DateOnly?)c.TradeDate).FirstOrDefaultAsync(ct);
  17. if (latestKr is not null)
  18. {
  19. var kospi = await db.IndexDailyPrice.AsNoTracking()
  20. .Where(c => c.TradeDate == latestKr.Value && c.Series == MarketIndexSeries.KOSPI && c.IndexName == "코스피")
  21. .Select(c => new
  22. {
  23. c.Close,
  24. c.ChangeVal,
  25. c.FlucRateBp,
  26. c.TradeDate
  27. })
  28. .FirstOrDefaultAsync(ct);
  29. if (kospi is not null)
  30. {
  31. rows.Add(new Response.Row
  32. {
  33. CountryCode = "KR",
  34. Name = "코스피",
  35. ExchangeName = "KRX",
  36. Close = kospi.Close,
  37. ChangeVal = kospi.ChangeVal,
  38. FlucRateBp = kospi.FlucRateBp,
  39. TradeDate = kospi.TradeDate
  40. });
  41. }
  42. }
  43. // 해외 — WorldIndexSnapshot (config Items 로 나라당 1개). KR 은 위에서 병합했으므로 제외.
  44. var foreign = await db.WorldIndexSnapshot.AsNoTracking()
  45. .Where(c => c.CountryCode != "KR")
  46. .OrderBy(c => c.CountryCode)
  47. .Select(c => new Response.Row
  48. {
  49. CountryCode = c.CountryCode,
  50. Name = c.Name,
  51. ExchangeName = c.ExchangeName,
  52. Close = c.Close,
  53. ChangeVal = c.ChangeVal,
  54. FlucRateBp = c.FlucRateBp,
  55. TradeDate = c.TradeDate
  56. })
  57. .ToListAsync(ct);
  58. rows.AddRange(foreign);
  59. return new Response
  60. {
  61. List = rows
  62. };
  63. }
  64. }