Handler.cs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. namespace Application.Features.Api.Stocks.GetEsgIndices;
  5. /// <summary>
  6. /// ESG 지수 목록 — 지정일(미지정 시 최신 TradeDate) 행을 지수명순으로 페이징 (KRX ESG 지수 수집, 익명).
  7. /// </summary>
  8. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
  9. {
  10. private const ushort MaxPerPage = 100;
  11. public async Task<Response> Handle(Query request, CancellationToken ct)
  12. {
  13. var page = request.Page < 1 ? 1 : request.Page;
  14. var perPage = request.PerPage is 0 or > MaxPerPage ? (ushort)20 : request.PerPage;
  15. var targetDate = request.Date;
  16. if (targetDate is null)
  17. {
  18. targetDate = await db.EsgIndexDailyPrice.AsNoTracking()
  19. .OrderByDescending(c => c.TradeDate)
  20. .Select(c => (DateOnly?)c.TradeDate)
  21. .FirstOrDefaultAsync(ct);
  22. }
  23. if (targetDate is null)
  24. {
  25. return new Response
  26. {
  27. Total = 0,
  28. TradeDate = null,
  29. List = []
  30. };
  31. }
  32. var query = db.EsgIndexDailyPrice.AsNoTracking().Where(c => c.TradeDate == targetDate.Value);
  33. var total = await query.CountAsync(ct);
  34. var list = await query
  35. .OrderBy(c => c.IndexName)
  36. .Skip((page - 1) * perPage)
  37. .Take(perPage)
  38. .Select(c => new Response.Row
  39. {
  40. Name = c.IndexName,
  41. Close = c.Close,
  42. ChangeVal = c.ChangeVal,
  43. FlucRateBp = c.FlucRateBp,
  44. ConstituentCount = c.ConstituentCount,
  45. Volume = c.Volume,
  46. Value = c.Value
  47. })
  48. .ToListAsync(ct);
  49. return new Response
  50. {
  51. Total = total,
  52. TradeDate = targetDate.Value,
  53. List = list
  54. };
  55. }
  56. }