| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Member.Items.Equipped;
- /// <summary>
- /// 여러 회원의 장착 지위 아이템을 한 번에 조회한다 (댓글/채팅/프로필 목록 렌더용).
- /// 만료(ExpiresAt 경과)·회수 아이템은 제외한다.
- /// </summary>
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
- {
- private const int MaxIDs = 200;
- public async Task<Response> Handle(Query request, CancellationToken ct)
- {
- var ids = request.MemberIDs.Where(id => id > 0).Distinct().Take(MaxIDs).ToList();
- if (ids.Count == 0)
- {
- return new Response([]);
- }
- var now = DateTime.UtcNow;
- var rows = await db.MemberItem.AsNoTracking()
- .Include(i => i.Product)
- .Where(i => ids.Contains(i.MemberID)
- && i.IsEquipped
- && i.EquipSlot != null
- && i.RevokedAt == null
- && (i.ExpiresAt == null || i.ExpiresAt > now))
- .Select(i => new
- {
- i.MemberID,
- Slot = i.EquipSlot!.Value,
- i.Kind,
- ProductName = i.Product!.Name,
- i.Product.EffectPayload,
- i.Product.Thumbnail
- })
- .ToListAsync(ct);
- var members = rows
- .GroupBy(r => r.MemberID)
- .Select(g => new Response.MemberEquip(
- g.Key,
- g.OrderBy(x => x.Slot)
- .Select(x => new Response.EquippedItem(x.Slot, x.Kind, x.ProductName, x.EffectPayload, x.Thumbnail))
- .ToList()))
- .ToList();
- return new Response(members);
- }
- }
|