using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Donations; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Crew.JoinByCode; internal sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { var crew = await db.Crew .FirstOrDefaultAsync(c => c.InviteCode == request.InviteCode && c.IsActive, ct); if (crew is null) { throw new KeyNotFoundException("유효하지 않은 초대 코드입니다."); } // 이미 등록된 크루원인지 확인 var exists = await db.CrewMember .AnyAsync(m => m.CrewID == crew.ID && m.MemberID == request.MemberID, ct); if (exists) { throw new InvalidOperationException("이미 등록된 크루원입니다."); } var channel = await db.Channel.AsNoTracking() .FirstOrDefaultAsync(c => c.MemberID == request.MemberID, ct); var nextOrder = await db.CrewMember .Where(m => m.CrewID == crew.ID) .MaxAsync(m => (int?)m.SortOrder, ct) ?? 0; var member = CrewMember.Create( crew.ID, request.MemberID, request.Nickname, channel?.ID, sortOrder: nextOrder + 1 ); db.CrewMember.Add(member); await db.SaveChangesAsync(ct); return new Response(member.ID, crew.Name); } }