| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Domain.Entities.Stocks.ValueObject;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Stocks.GetWorldIndices;
- /// <summary>
- /// 세계 주요국 증시지수 병합 — 국내(코스피)는 IndexDailyPrice 최신 거래일 실데이터, 해외는 WorldIndexSnapshot(나라당 1개).
- /// 국가 코드(ISO2)로 프론트가 세계지도 핀 좌표를 매핑한다. 해외 스냅샷에 KR 이 섞여도 중복 방지로 제외.
- /// </summary>
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
- {
- public async Task<Response> Handle(Query request, CancellationToken ct)
- {
- var rows = new List<Response.Row>();
- // 국내(코스피) — IndexDailyPrice 최신 거래일. 한국 핀은 KRX 실데이터 사용.
- var latestKr = await db.IndexDailyPrice.AsNoTracking().OrderByDescending(c => c.TradeDate).Select(c => (DateOnly?)c.TradeDate).FirstOrDefaultAsync(ct);
- if (latestKr is not null)
- {
- var kospi = await db.IndexDailyPrice.AsNoTracking()
- .Where(c => c.TradeDate == latestKr.Value && c.Series == MarketIndexSeries.KOSPI && c.IndexName == "코스피")
- .Select(c => new
- {
- c.Close,
- c.ChangeVal,
- c.FlucRateBp,
- c.TradeDate
- })
- .FirstOrDefaultAsync(ct);
- if (kospi is not null)
- {
- rows.Add(new Response.Row
- {
- CountryCode = "KR",
- Name = "코스피",
- ExchangeName = "KRX",
- Close = kospi.Close,
- ChangeVal = kospi.ChangeVal,
- FlucRateBp = kospi.FlucRateBp,
- TradeDate = kospi.TradeDate
- });
- }
- }
- // 해외 — WorldIndexSnapshot. KR 은 위에서 병합했으므로 제외. 한 국가에 지수가 여러 개면(예: US ^gspc/^ixic)
- // 지도는 나라당 1핀이므로 심볼 오름차순 첫 행만 남긴다(US → ^gspc=S&P500). 요약 카드는 별도 엔드포인트에서 심볼로 조회.
- var foreignRaw = await db.WorldIndexSnapshot.AsNoTracking()
- .Where(c => c.CountryCode != "KR")
- .OrderBy(c => c.CountryCode).ThenBy(c => c.Symbol)
- .Select(c => new
- {
- c.CountryCode,
- c.Name,
- c.ExchangeName,
- c.Close,
- c.ChangeVal,
- c.FlucRateBp,
- c.TradeDate
- })
- .ToListAsync(ct);
- var seenCountry = new HashSet<string>();
- foreach (var c in foreignRaw)
- {
- if (!seenCountry.Add(c.CountryCode))
- {
- continue;
- }
- rows.Add(new Response.Row
- {
- CountryCode = c.CountryCode,
- Name = c.Name,
- ExchangeName = c.ExchangeName,
- Close = c.Close,
- ChangeVal = c.ChangeVal,
- FlucRateBp = c.FlucRateBp,
- TradeDate = c.TradeDate
- });
- }
- return new Response
- {
- List = rows
- };
- }
- }
|