using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Stocks.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Stocks.GetIndices; /// /// 대표 시장지수 — 최신 거래일의 코스피/코스닥(+KRX 100)만 반환 (헤더 티커 + /market, d0 §3-D). /// 지수명이 정확히 대표명과 일치하는 행만 취하고, 계열 순서(KOSPI→KOSDAQ→KRX)로 정렬한다. /// internal sealed class Handler(IAppDbContext db) : IQueryHandler { // (계열, 대표 지수명) — KRX OpenAPI IDX_NM 기준 private static readonly (MarketIndexSeries Series, string Name)[] KeyIndices = [ (MarketIndexSeries.KOSPI, "코스피"), (MarketIndexSeries.KOSDAQ, "코스닥"), (MarketIndexSeries.KRX, "KRX 100") ]; public async Task Handle(Query request, CancellationToken ct) { var latest = await db.IndexDailyPrice.AsNoTracking().OrderByDescending(c => c.TradeDate).Select(c => (DateOnly?)c.TradeDate).FirstOrDefaultAsync(ct); if (latest is null) { return new Response { List = [] }; } var names = KeyIndices.Select(c => c.Name).ToArray(); var rows = await db.IndexDailyPrice.AsNoTracking() .Where(c => c.TradeDate == latest.Value && names.Contains(c.IndexName)) .Select(c => new Response.Row { Series = c.Series, Name = c.IndexName, Close = c.Close, ChangeVal = c.ChangeVal, FlucRateBp = c.FlucRateBp, TradeDate = c.TradeDate }) .ToListAsync(ct); // 대표 지수명 순서(KOSPI→KOSDAQ→KRX)로 정렬 var ordered = KeyIndices .Select(k => rows.FirstOrDefault(r => r.Series == k.Series && r.Name == k.Name)) .Where(r => r is not null) .Select(r => r!) .ToList(); return new Response { List = ordered }; } }