Handler.cs 4.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using SharedKernel.Results;
  4. using Microsoft.EntityFrameworkCore;
  5. using MemberEntity = Domain.Entities.Members.Member;
  6. namespace Application.Features.Admin.Member.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 member = await db.Member.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.ID, ct);
  12. if (member is null)
  13. {
  14. return Result.Failure(Error.NotFound("Member.NotFound", "회원을 찾을 수 없습니다."));
  15. }
  16. // 이메일 중복 체크
  17. if (member.Email != request.Email && await db.Member.AnyAsync(x => x.Email == request.Email && x.ID != request.ID, ct))
  18. {
  19. return Result.Failure(Error.Conflict("Member.DuplicateEmail", "이미 등록된 이메일입니다."));
  20. }
  21. // 별명 중복 체크
  22. if (request.Name is not null && member.Name != request.Name && await db.Member.AnyAsync(x => x.Name == request.Name && x.ID != request.ID, ct))
  23. {
  24. return Result.Failure(Error.Conflict("Member.DuplicateName", "이미 등록된 별명입니다."));
  25. }
  26. // Thumb 처리
  27. string? thumbPath = request.IsThumbRemove ? null : (request.ThumbUrl ?? member.Thumb);
  28. // Icon 처리
  29. string? iconPath = request.IsIconRemove ? null : (request.IconUrl ?? member.Icon);
  30. // 기본 정보 + 비밀번호 업데이트 (단일 쿼리)
  31. if (!string.IsNullOrWhiteSpace(request.Password))
  32. {
  33. await db.Member.Where(x => x.ID == request.ID).ExecuteUpdateAsync(s => s
  34. .SetProperty(x => x.MemberGradeID, request.MemberGradeID)
  35. .SetProperty(x => x.Email, request.Email)
  36. .SetProperty(x => x.Name, request.Name)
  37. .SetProperty(x => x.FirstName, request.FirstName)
  38. .SetProperty(x => x.LastName, request.LastName)
  39. .SetProperty(x => x.Intro, request.Intro)
  40. .SetProperty(x => x.Summary, request.Summary)
  41. .SetProperty(x => x.Phone, request.Phone)
  42. .SetProperty(x => x.Birthday, request.Birthday)
  43. .SetProperty(x => x.Gender, request.Gender)
  44. .SetProperty(x => x.Thumb, thumbPath)
  45. .SetProperty(x => x.Icon, iconPath)
  46. .SetProperty(x => x.IsEmailVerified, request.IsEmailVerified)
  47. .SetProperty(x => x.IsAuthCertified, request.IsAuthCertified)
  48. .SetProperty(x => x.IsDenied, request.IsDenied)
  49. .SetProperty(x => x.IsAdmin, request.IsAdmin)
  50. .SetProperty(x => x.IsWithdraw, request.IsWithdraw)
  51. .SetProperty(x => x.PasswordHash, MemberEntity.HashPassword(request.Password!))
  52. .SetProperty(x => x.Password, (string?)null)
  53. .SetProperty(x => x.PasswordUpdatedAt, DateTime.UtcNow)
  54. .SetProperty(x => x.UpdatedAt, DateTime.UtcNow),
  55. ct);
  56. }
  57. else
  58. {
  59. await db.Member.Where(x => x.ID == request.ID).ExecuteUpdateAsync(s => s
  60. .SetProperty(x => x.MemberGradeID, request.MemberGradeID)
  61. .SetProperty(x => x.Email, request.Email)
  62. .SetProperty(x => x.Name, request.Name)
  63. .SetProperty(x => x.FirstName, request.FirstName)
  64. .SetProperty(x => x.LastName, request.LastName)
  65. .SetProperty(x => x.Intro, request.Intro)
  66. .SetProperty(x => x.Summary, request.Summary)
  67. .SetProperty(x => x.Phone, request.Phone)
  68. .SetProperty(x => x.Birthday, request.Birthday)
  69. .SetProperty(x => x.Gender, request.Gender)
  70. .SetProperty(x => x.Thumb, thumbPath)
  71. .SetProperty(x => x.Icon, iconPath)
  72. .SetProperty(x => x.IsEmailVerified, request.IsEmailVerified)
  73. .SetProperty(x => x.IsAuthCertified, request.IsAuthCertified)
  74. .SetProperty(x => x.IsDenied, request.IsDenied)
  75. .SetProperty(x => x.IsAdmin, request.IsAdmin)
  76. .SetProperty(x => x.IsWithdraw, request.IsWithdraw)
  77. .SetProperty(x => x.UpdatedAt, DateTime.UtcNow),
  78. ct);
  79. }
  80. return Result.Success();
  81. }
  82. }