Handler.cs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. using SharedKernel.Results;
  5. namespace Application.Features.Api.Stocks.GetHistory;
  6. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  7. {
  8. private const ushort MaxPerPage = 200;
  9. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  10. {
  11. var stockID = await db.Stock.AsNoTracking().Where(c => c.Code == request.Code).Select(c => (int?)c.ID).FirstOrDefaultAsync(ct);
  12. if (stockID is null)
  13. {
  14. return Result.Failure<Response>(Error.NotFound("Stock.NotFound", "종목을 찾을 수 없습니다."));
  15. }
  16. var page = request.Page < 1 ? 1 : request.Page;
  17. var perPage = request.PerPage is 0 or > MaxPerPage ? (ushort)30 : request.PerPage;
  18. var query = db.StockDailyPrice.AsNoTracking().Where(c => c.StockID == stockID.Value);
  19. if (request.From.HasValue)
  20. {
  21. query = query.Where(c => c.TradingDate >= request.From.Value);
  22. }
  23. if (request.To.HasValue)
  24. {
  25. query = query.Where(c => c.TradingDate <= request.To.Value);
  26. }
  27. var total = await query.CountAsync(ct);
  28. var list = await query
  29. .OrderByDescending(c => c.TradingDate)
  30. .Skip((page - 1) * perPage)
  31. .Take(perPage)
  32. .Select(c => new Response.Row
  33. {
  34. TradingDate = c.TradingDate,
  35. Open = c.Open,
  36. High = c.High,
  37. Low = c.Low,
  38. Close = c.Close,
  39. Volume = c.Volume,
  40. TradingValue = c.TradingValue,
  41. ChangeAmount = c.ChangeAmount,
  42. ChangeRate = c.ChangeRate,
  43. MarketCap = c.MarketCap
  44. })
  45. .ToListAsync(ct);
  46. return new Response
  47. {
  48. Total = total,
  49. List = list
  50. };
  51. }
  52. }