Handler.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using System.Text.RegularExpressions;
  2. using Application.Abstractions.Data;
  3. using Application.Abstractions.Messaging;
  4. using SharedKernel.Results;
  5. using Microsoft.EntityFrameworkCore;
  6. namespace Application.Features.Admin.Channel.List.Update;
  7. public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result>
  8. {
  9. public async Task<Result> Handle(Command request, CancellationToken ct)
  10. {
  11. var channel = await db.Channel.FirstOrDefaultAsync(c => c.ID == request.ID, ct);
  12. if (channel is null)
  13. {
  14. return Result.Failure(Error.NotFound("Channel.NotFound", "채널을 찾을 수 없습니다."));
  15. }
  16. // 후원 코드 사전 검증 (자기 자신은 중복에서 제외)
  17. string? normalizedDonationCode = null;
  18. if (!string.IsNullOrWhiteSpace(request.DonationCode))
  19. {
  20. var trimmed = request.DonationCode.Trim();
  21. if (!Regex.IsMatch(trimmed, "^[A-Za-z0-9]{4,7}$"))
  22. {
  23. return Result.Failure(Error.Problem("DonationCode.InvalidFormat", "후원 코드는 4~7자 영문/숫자만 가능합니다."));
  24. }
  25. normalizedDonationCode = trimmed.ToUpperInvariant();
  26. var codeTaken = await db.Channel.AnyAsync(c => c.DonationCode == normalizedDonationCode && c.ID != request.ID, ct);
  27. if (codeTaken)
  28. {
  29. return Result.Failure(Error.Conflict("DonationCode.Duplicate", "이미 사용 중인 후원 코드입니다."));
  30. }
  31. }
  32. channel.Update(
  33. request.Name,
  34. request.Handle,
  35. request.YouTubeUrl,
  36. request.PlatformFeeRate,
  37. request.StoreCommissionRate,
  38. request.IsVerified,
  39. request.IsActive
  40. );
  41. channel.SetDonationCodeByAdmin(normalizedDonationCode);
  42. try
  43. {
  44. await db.SaveChangesAsync(ct);
  45. }
  46. catch (DbUpdateException)
  47. {
  48. return Result.Failure(Error.Conflict("DonationCode.Duplicate", "이미 사용 중인 후원 코드입니다."));
  49. }
  50. return Result.Success();
  51. }
  52. }