Handler.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using Microsoft.EntityFrameworkCore;
  4. using Domain.Entities.Page.Faq;
  5. namespace Application.Features.Faq.Category.Save
  6. {
  7. public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Response>
  8. {
  9. public async Task<Response> Handle(Command request, CancellationToken ct)
  10. {
  11. var items = request.Items;
  12. var dbRows = await db.FaqCategory.ToListAsync(ct);
  13. var dbByID = dbRows.ToDictionary(c => c.ID);
  14. // 값이 있는 것만 추출
  15. var requestIDs = items.Where(c => c.ID.HasValue && c.ID.Value > 0).Select(c => c.ID!.Value).ToHashSet();
  16. // 삭제 대상 조회
  17. var deleteTargets = dbRows.Where(x => !requestIDs.Contains(x.ID)).ToList();
  18. if (deleteTargets.Count > 0)
  19. {
  20. var deleteIDs = deleteTargets.Select(c => c.ID).ToList();
  21. var hasItems = await db.FaqItem.AsNoTracking().AnyAsync(c => deleteIDs.Contains(c.CategoryID), ct);
  22. if (hasItems)
  23. {
  24. throw new InvalidOperationException("FAQ가 등록된 분류는 삭제할 수 없습니다. 먼저 해당 FAQ를 삭제하세요.");
  25. }
  26. db.FaqCategory.RemoveRange(deleteTargets);
  27. }
  28. ushort inserted = 0;
  29. ushort updated = 0;
  30. ushort deleted = 0;
  31. foreach(var row in items)
  32. {
  33. // 신규 추가
  34. if (!row.ID.HasValue || row.ID.Value <= 0)
  35. {
  36. // Code 중복 검사
  37. if (await db.FaqCategory.AnyAsync(c => c.Code == row.Code && c.ID != row.ID, ct))
  38. {
  39. throw new InvalidOperationException($"`{row.Code}`는 이미 등록되었습니다.");
  40. }
  41. db.FaqCategory.Add(
  42. FaqCategory.Create(row.Code, row.Subject, row.Order, row.IsActive)
  43. );
  44. inserted++;
  45. continue;
  46. }
  47. // 수정
  48. if (!dbByID.TryGetValue(row.ID.Value, out var existing))
  49. {
  50. throw new InvalidOperationException($"존재하지 않는 ID: {row.ID.Value}");
  51. }
  52. // Code가 변경된 경우에만 중복 검사
  53. if (existing.Code != row.Code && await db.FaqCategory.AnyAsync(c => c.Code == row.Code, ct))
  54. {
  55. throw new InvalidOperationException($"`{row.Code}`는 이미 등록되었습니다.");
  56. }
  57. existing.Update(row.Code, row.Subject, row.Order, row.IsActive);
  58. updated++;
  59. }
  60. deleted = (ushort)deleteTargets.Count;
  61. await db.SaveChangesAsync(ct);
  62. return new Response(inserted, updated, deleted);
  63. }
  64. }
  65. }