| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Attendance.GetList;
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
- {
- public async Task<Response> Handle(Query request, CancellationToken ct)
- {
- // 로컬(서버 KST) 기준 날짜를 UTC 범위로 환산
- var targetDateLocal = DateTime.SpecifyKind(request.Date?.Date ?? DateTime.Now.Date, DateTimeKind.Local);
- var startUtc = targetDateLocal.ToUniversalTime();
- var endUtc = startUtc.AddDays(1);
- var query = db.Attendance.AsNoTracking()
- .Where(x => x.CreatedAt >= startUtc && x.CreatedAt < endUtc);
- var total = await query.CountAsync(ct);
- // 시간순 Rank 사전 계산 (정렬 옵션과 무관하게 항상 시간 기준)
- var rankList = await query
- .OrderBy(x => x.CreatedAt)
- .Select(x => new { x.MemberID, x.CreatedAt })
- .ToListAsync(ct);
- var rankMap = new Dictionary<int, int>();
- for (var i = 0; i < rankList.Count; i++)
- {
- rankMap[rankList[i].MemberID] = i + 1;
- }
- // 정렬 분기
- var sortBy = request.SortBy ?? "time";
- IQueryable<Domain.Entities.Members.Attendance> sortedQuery = sortBy switch
- {
- "count" => from a in query
- join stats in db.MemberStats.AsNoTracking() on a.MemberID equals stats.MemberID
- orderby stats.AttendanceCount descending, a.CreatedAt
- select a,
- "streak" => query.OrderByDescending(x => x.ConsecutiveDays).ThenBy(x => x.CreatedAt),
- _ => query.OrderBy(x => x.CreatedAt)
- };
- var list = await sortedQuery
- .Skip((request.Page - 1) * request.PerPage)
- .Take(request.PerPage)
- .Select(x => new AttendanceItem(
- 0,
- x.MemberID,
- x.Member.SID,
- x.Member.Name ?? "",
- x.Member.Thumb,
- x.Greeting,
- x.ConsecutiveDays,
- x.ExpRewarded,
- x.PointRewarded,
- x.CreatedAt
- ))
- .ToListAsync(ct);
- // Rank 주입 + UTC → 로컬 변환
- var ranked = list.Select(item => item with {
- Rank = rankMap.GetValueOrDefault(item.MemberID),
- CreatedAt = DateTime.SpecifyKind(item.CreatedAt, DateTimeKind.Utc).ToLocalTime()
- }).ToList();
- return new Response(total, ranked);
- }
- }
|