| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- using SharedKernel.Results;
- namespace Application.Features.Api.Member.GetLevel;
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
- {
- public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
- {
- var member = await db.Member.AsNoTracking()
- .Where(c => c.ID == request.MemberID)
- .Select(c => new { c.ID, c.MemberGradeID })
- .FirstOrDefaultAsync(ct);
- if (member is null)
- {
- return Result.Failure<Response>(Error.NotFound("Member.NotFound", "회원 정보를 찾을 수 없습니다."));
- }
- var exp = await db.MemberStats.AsNoTracking()
- .Where(c => c.MemberID == request.MemberID)
- .Select(c => (long?)c.Exp)
- .FirstOrDefaultAsync(ct) ?? 0;
- // 활성 등급을 RequiredExp 오름차순으로 로드 (소량)
- var grades = await db.MemberGrade.AsNoTracking()
- .Where(c => c.IsActive)
- .OrderBy(c => c.RequiredExp)
- .Select(c => new { c.ID, c.KorName, c.RequiredExp, c.Image, c.TextColor })
- .ToListAsync(ct);
- // 현재 등급 = 회원 등급 스냅샷 (없으면 충족하는 최고 등급으로 추정)
- var current = member.MemberGradeID is int gid
- ? grades.FirstOrDefault(c => c.ID == gid)
- : grades.LastOrDefault(c => c.RequiredExp <= exp);
- // 다음 등급 = 현재 RequiredExp 초과 첫 등급
- var currentRequired = current?.RequiredExp ?? -1;
- var next = grades.FirstOrDefault(c => c.RequiredExp > currentRequired);
- long? expToNext = next is not null ? Math.Max(0, next.RequiredExp - exp) : null;
- return Result.Success(new Response(
- exp,
- current?.ID,
- current?.KorName,
- current?.Image,
- current?.TextColor,
- next?.ID,
- next?.KorName,
- next?.RequiredExp,
- expToNext
- ));
- }
- }
|