using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Api.Stocks.GetHistory; internal sealed class Handler(IAppDbContext db) : IQueryHandler> { private const ushort MaxPerPage = 200; public async Task> Handle(Query request, CancellationToken ct) { var stockID = await db.Stock.AsNoTracking().Where(c => c.Code == request.Code).Select(c => (int?)c.ID).FirstOrDefaultAsync(ct); if (stockID is null) { return Result.Failure(Error.NotFound("Stock.NotFound", "종목을 찾을 수 없습니다.")); } var page = request.Page < 1 ? 1 : request.Page; var perPage = request.PerPage is 0 or > MaxPerPage ? (ushort)30 : request.PerPage; var query = db.StockDailyPrice.AsNoTracking().Where(c => c.StockID == stockID.Value); if (request.From.HasValue) { query = query.Where(c => c.TradingDate >= request.From.Value); } if (request.To.HasValue) { query = query.Where(c => c.TradingDate <= request.To.Value); } var total = await query.CountAsync(ct); var list = await query .OrderByDescending(c => c.TradingDate) .Skip((page - 1) * perPage) .Take(perPage) .Select(c => new Response.Row { TradingDate = c.TradingDate, Open = c.Open, High = c.High, Low = c.Low, Close = c.Close, Volume = c.Volume, TradingValue = c.TradingValue, ChangeAmount = c.ChangeAmount, ChangeRate = c.ChangeRate, MarketCap = c.MarketCap }) .ToListAsync(ct); return new Response { Total = total, List = list }; } }