using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Admin.Store.Settlement.MarkSettled; public sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.AdminUserId)) { return Result.Failure(Error.Problem("GameSettlement.AdminRequired", "처리 관리자 정보가 누락되었습니다.")); } if (request.AdminMemo is { Length: > 500 }) { return Result.Failure(Error.Problem("GameSettlement.AdminMemoTooLong", "관리자 메모는 500자 이하여야 합니다.")); } var settlement = await db.GameSettlement .FirstOrDefaultAsync(s => s.ID == request.ID, ct); if (settlement is null) { return Result.Failure(Error.NotFound("GameSettlement.NotFound", "정산 정보를 찾을 수 없습니다.")); } if (settlement.Status != GameSettlementStatus.Pending) { return Result.Failure(Error.Problem("GameSettlement.AlreadySettled", "이미 정산 완료된 항목입니다.")); } try { settlement.MarkSettled(request.AdminUserId, request.AdminEmail, request.AdminMemo); } catch (InvalidOperationException ex) { return Result.Failure(Error.Problem("GameSettlement.InvalidTransition", ex.Message)); } catch (ArgumentOutOfRangeException ex) { return Result.Failure(Error.Problem("GameSettlement.InvalidArgument", ex.Message)); } await db.SaveChangesAsync(ct); return Result.Success(); } }