Handler.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using Application.Abstractions.Cache;
  4. using Domain.Entities.Crypto;
  5. using SharedKernel.Storage;
  6. using Microsoft.EntityFrameworkCore;
  7. namespace Application.Features.Admin.Crypto.List.Update
  8. {
  9. public sealed class Handler(IAppDbContext db, IFileStorage fileStorage, ICacheService cache) : ICommandHandler<Command>
  10. {
  11. public async Task Handle(Command request, CancellationToken ct)
  12. {
  13. var coin = await db.Coin.Include(c => c.CoinCategoryMap).FirstOrDefaultAsync(c => c.ID == request.ID, ct);
  14. if (coin is null)
  15. {
  16. throw new KeyNotFoundException("코인을 찾을 수 없습니다.");
  17. }
  18. if (await db.Coin.AnyAsync(c => c.Symbol == request.Symbol.ToUpper() && c.ID != request.ID, ct))
  19. {
  20. throw new InvalidOperationException($"`{request.Symbol.ToUpper()}`는 이미 등록된 심볼입니다.");
  21. }
  22. FileStoragePath uploadPath = new FileStoragePath(UploadTarget.Upload, UploadFolder.Crypto, coin.ID);
  23. string[] allowedFileExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];
  24. string? logoImagePath = coin.LogoImage;
  25. if (request.DeleteLogoImage && !string.IsNullOrEmpty(coin.LogoImage))
  26. {
  27. fileStorage.DeleteByUrl(coin.LogoImage);
  28. logoImagePath = null;
  29. }
  30. // 로고 이미지 파일이 제공된 경우 기존 이미지를 삭제하고 새 이미지 저장
  31. if (request.LogoImageFile is not null)
  32. {
  33. if (!string.IsNullOrEmpty(coin.LogoImage))
  34. {
  35. fileStorage.DeleteByUrl(coin.LogoImage);
  36. }
  37. logoImagePath = (await fileStorage.SaveFileAsync(request.LogoImageFile, uploadPath, allowedFileExtensions, ct))?.Url;
  38. }
  39. coin.Update(
  40. request.Symbol,
  41. request.KorName,
  42. request.EngName,
  43. request.Description,
  44. request.ContractAddress,
  45. request.WebsiteUrl,
  46. request.WhitepaperUrl,
  47. request.TwitterUrl,
  48. request.TelegramUrl,
  49. request.IsActive,
  50. request.IsWarning,
  51. request.IsNew,
  52. request.IsDelisted
  53. );
  54. coin.SetLogoImage(logoImagePath);
  55. var existingMaps = coin.CoinCategoryMap.ToList();
  56. db.CoinCategoryMap.RemoveRange(existingMaps);
  57. foreach (var categoryID in request.CategoryIDs)
  58. {
  59. db.CoinCategoryMap.Add(new CoinCategoryMap { CoinID = coin.ID, CategoryID = categoryID });
  60. }
  61. await db.SaveChangesAsync(ct);
  62. await cache.RemoveByPrefixAsync("crypto:", ct);
  63. }
  64. }
  65. }