| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- using SharedKernel.Results;
- namespace Application.Features.Api.Stocks.GetMeetingCalendar;
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
- {
- private const ushort MaxPerPage = 200;
- public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
- {
- var page = request.Page < 1 ? 1 : request.Page;
- var perPage = request.PerPage is 0 or > MaxPerPage ? (ushort)30 : request.PerPage;
- var query = db.GeneralMeeting.AsNoTracking();
- if (request.From.HasValue)
- {
- query = query.Where(c => c.GmetDt >= request.From.Value);
- }
- if (request.To.HasValue)
- {
- query = query.Where(c => c.GmetDt <= request.To.Value);
- }
- var total = await query.CountAsync(ct);
- var meetings = await query
- .OrderByDescending(c => c.GmetDt)
- .ThenBy(c => c.IssucoCustno)
- .ThenBy(c => c.GmetKacd)
- .Skip((page - 1) * perPage)
- .Take(perPage)
- .Select(c => new
- {
- c.IssucoCustno,
- c.RgtStdDt,
- c.GmetDt,
- c.GmetTtm,
- c.GmetKacd,
- c.GmetPlace,
- c.EvoteYn,
- c.DferYn
- })
- .ToListAsync(ct);
- if (meetings.Count == 0)
- {
- return new Response { Total = total, List = [] };
- }
- var custnos = meetings.Select(c => c.IssucoCustno).Distinct().ToList();
- var stdDts = meetings.Select(c => c.RgtStdDt).Distinct().ToList();
- // 종목명·단축코드 (IssucoCustno 조인 — 한 회사에 여러 종목이면 대표 1개)
- var stockRows = await db.Stock.AsNoTracking()
- .Where(c => c.IssucoCustno != null && custnos.Contains(c.IssucoCustno.Value))
- .Select(c => new { Custno = c.IssucoCustno!.Value, c.Name, c.Code })
- .ToListAsync(ct);
- var stockByCustno = stockRows.GroupBy(c => c.Custno).ToDictionary(g => g.Key, g => g.First());
- // 안건수 집계 (회사, 기준일) 단위
- var agendaCounts = await db.MeetingAgenda.AsNoTracking()
- .Where(c => custnos.Contains(c.IssucoCustno) && stdDts.Contains(c.RgtStdDt))
- .GroupBy(c => new { c.IssucoCustno, c.RgtStdDt })
- .Select(g => new { g.Key.IssucoCustno, g.Key.RgtStdDt, Count = g.Count() })
- .ToListAsync(ct);
- var agendaLookup = agendaCounts.ToDictionary(c => (c.IssucoCustno, c.RgtStdDt), c => c.Count);
- var list = meetings.Select(c =>
- {
- stockByCustno.TryGetValue(c.IssucoCustno, out var stock);
- agendaLookup.TryGetValue((c.IssucoCustno, c.RgtStdDt), out var agendaCount);
- return new Response.Row
- {
- IssucoCustno = c.IssucoCustno,
- Name = stock?.Name,
- Code = stock?.Code,
- RgtStdDt = c.RgtStdDt,
- GmetDt = c.GmetDt,
- GmetTtm = c.GmetTtm,
- MeetingKind = c.GmetKacd,
- Place = c.GmetPlace,
- Evote = c.EvoteYn,
- Deferred = c.DferYn,
- AgendaCount = agendaCount
- };
- }).ToList();
- return new Response
- {
- Total = total,
- List = list
- };
- }
- }
|