2 コミット 56098cea7f ... 6d5ea727d6

作者 SHA1 メッセージ 日付
  zinab_elgendy 6d5ea727d6 taskAttachments 2 ヶ月 前
  zinab_elgendy 89ad831904 Fix team update 2 ヶ月 前
共有25 個のファイルを変更した7627 個の追加74 個の削除を含む
  1. 3 3
      MTWorkHR.API/Controllers/CompanyController.cs
  2. 3 3
      MTWorkHR.API/Controllers/UserController.cs
  3. 3 3
      MTWorkHR.API/appsettings.Development.json
  4. 3 3
      MTWorkHR.API/appsettings.json
  5. 5 0
      MTWorkHR.Application/Dtos/Identity/AttachmentDto.cs
  6. 3 0
      MTWorkHR.Application/Dtos/Identity/AttachmentResponseDto.cs
  7. 1 0
      MTWorkHR.Application/Dtos/User/TeamUserDto.cs
  8. 6 1
      MTWorkHR.Application/Mapper/MappingProfile.cs
  9. 48 1
      MTWorkHR.Application/Services/Base/BlobFileService.cs
  10. 1 1
      MTWorkHR.Application/Services/Interfaces/ICompanyService.cs
  11. 2 2
      MTWorkHR.Application/Services/Interfaces/IUserService.cs
  12. 57 9
      MTWorkHR.Application/Services/Task/UserTaskAttachmentService.cs
  13. 7 0
      MTWorkHR.Application/Services/Task/UserTaskService.cs
  14. 3 3
      MTWorkHR.Application/Services/User/CompanyService.cs
  15. 24 19
      MTWorkHR.Application/Services/User/TeamService.cs
  16. 13 6
      MTWorkHR.Application/Services/User/UserService.cs
  17. 1 0
      MTWorkHR.Core/Entities/User/TeamUser.cs
  18. 1 1
      MTWorkHR.Core/Entities/User/UserTaskAttachment.cs
  19. 1 0
      MTWorkHR.Core/IRepositories/Task/IUserTaskAttachmentRepository.cs
  20. 27 18
      MTWorkHR.Infrastructure/EmailService/MailSender.cs
  21. 1 1
      MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs
  22. 7360 0
      MTWorkHR.Infrastructure/Migrations/20250529131711_altrTaskAttachment.Designer.cs
  23. 38 0
      MTWorkHR.Infrastructure/Migrations/20250529131711_altrTaskAttachment.cs
  24. 6 0
      MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs
  25. 10 0
      MTWorkHR.Infrastructure/Repositories/Task/TaskAttachmentRepository.cs

+ 3 - 3
MTWorkHR.API/Controllers/CompanyController.cs

@@ -29,15 +29,15 @@ namespace MTWorkHR.API.Controllers
         }
         [HttpGet("Get")]
         [AppAuthorize(Permissions = "Company")]
-        public async Task<ActionResult<CompanyDto>> Get()
+        public async Task<ActionResult<UpdateCompanyDto>> Get()
         {
             return Ok(await _companyService.GetById());
         }
         [HttpGet("GetById")]
         [AppAuthorize(Permissions = "Company")]
-        public async Task<ActionResult<CompanyDto>> GetById(long companyId)
+        public async Task<ActionResult<UpdateCompanyDto>> GetById(long companyId)
         {
-            return Ok(await _companyService.GetById(companyId));
+            return Ok(await _companyService.GetByIdForUpdate(companyId));
         }
 
         [HttpPost("Create")]

+ 3 - 3
MTWorkHR.API/Controllers/UserController.cs

@@ -35,15 +35,15 @@ namespace MTWorkHR.API.Controllers
         }
         [HttpGet("Get")]
         [AppAuthorize(Permissions = "User")]
-        public async Task<ActionResult<UserDto>> Get()
+        public async Task<ActionResult<UserUpdateDto>> Get()
         {
             return Ok(await _userService.GetById());
         }
         [HttpGet("GetById")]
         [AppAuthorize(Permissions = "User")]
-        public async Task<ActionResult<UserDto>> GetById([FromQuery] string userId)
+        public async Task<ActionResult<UserUpdateDto>> GetById([FromQuery] string userId)
         {
-            return Ok(await _userService.GetById(userId));
+            return Ok(await _userService.GetByIdForUpdate(userId));
         }
 
         [HttpGet("GetEmployeeById")]

+ 3 - 3
MTWorkHR.API/appsettings.Development.json

@@ -32,10 +32,10 @@
   },
   "MailSettings": {
     "ApiKey": "SendGrid-Key",
-    "FromAddress": "DoNotReply@bc3ee9f1-57df-4a29-b566-a84d72074975.azurecomm.net",
+    "FromAddress": "noreply@mtwork.com",
     "FromName": "MTWork Hr Management System",
-    "Password": "1qU8Q~gt4nex-gO3gWrc3FO~fpv8uGoTGqjyFbHx",
-    "Host": "smtp.azurecomm.net",
+    "Password": "Noreply@1111",
+    "Host": "smtp.gmail.com",
     "SmtpUsername": "SMTP_username", // "MTCommunicationServiceResource.57fe2efd-9859-488f-8313-0acd27450cf0.2ff48a6f-9604-49d0-b338-28e96f91ec99", //"EmailSMTPApp",
     "Port": 587,
     "TemplatePath": "C:\\Attachment\\MailTemp\\EmailTemplate.html"

+ 3 - 3
MTWorkHR.API/appsettings.json

@@ -31,10 +31,10 @@
   },
   "MailSettings": {
     "ApiKey": "SendGrid-Key",
-    "FromAddress": "DoNotReply@bc3ee9f1-57df-4a29-b566-a84d72074975.azurecomm.net",
+    "FromAddress": "noreply@mtwork.com",
     "FromName": "MTWork Hr Management System",
-    "Password": "1qU8Q~gt4nex-gO3gWrc3FO~fpv8uGoTGqjyFbHx",
-    "Host": "smtp.azurecomm.net",
+    "Password": "Noreply@1111",
+    "Host": "smtp.gmail.com",
     "Port": 587,
     "SmtpUsername": "SMTP_username", // "MTCommunicationServiceResource.57fe2efd-9859-488f-8313-0acd27450cf0.2ff48a6f-9604-49d0-b338-28e96f91ec99", //"EmailSMTPApp",
     "TemplatePath": "C:\\Attachment\\MailTemp\\EmailTemplate.html"

+ 5 - 0
MTWorkHR.Application/Dtos/Identity/AttachmentDto.cs

@@ -14,8 +14,13 @@ namespace MTWorkHR.Application.Models
 
         public IFormFile? FileData { get; set; }
         public string? FileName { get; set; }
+        public long? FileSize { get; set; }
 
         public string? CreateDate { get; set; }
+        public string? CreateUser { get; set; }
+        
+        public string? CreatedUserName { get; set; }
+        public string? ProfileImage { get; set; }
         public string? OriginalName { get; set; }
         public string? FilePath { get; set; }
         public byte[]? Content { get; set; }

+ 3 - 0
MTWorkHR.Application/Dtos/Identity/AttachmentResponseDto.cs

@@ -11,6 +11,9 @@ namespace MTWorkHR.Application.Models
         public string? FileName { get; set; }
 
         public string? FilePath { get; set; }
+        public long? FileSize { get; set; }
+        public string? ContentType { get; set; }
+        
 
     }
 }

+ 1 - 0
MTWorkHR.Application/Dtos/User/TeamUserDto.cs

@@ -14,6 +14,7 @@ namespace MTWorkHR.Application.Models
         public string AssignedUserId { get; set; }
         public string? AssignedUserName { get; set; }
         public string? AssignedUserEmail { get; set; }
+        public string? ProfileImage { get; set; }
 
     }
 }

+ 6 - 1
MTWorkHR.Application/Mapper/MappingProfile.cs

@@ -50,7 +50,12 @@ namespace MTWorkHR.Application.Mapper
               //  .ForMember(m => m.UserAddress, op => op.Ignore())
                 .ForMember(m => m.Id, op => op.Ignore());
 
-            CreateMap<ApplicationUser, UserUpdateDto>().ForMember(m => m.Password, op => op.Ignore());
+            CreateMap<ApplicationUser, UserUpdateDto>().ForMember(m => m.Password, op => op.Ignore())
+                .ForMember(s => s.QualificationName, o => o.MapFrom(s => s.Qualification == null ? "" : GlobalInfo.lang == "ar" ? s.Qualification.NameAr : s.Qualification.NameEn))
+                .ForMember(s => s.JobTitleName, o => o.MapFrom(s => s.JobTitle == null ? "" : GlobalInfo.lang == "ar" ? s.JobTitle.NameAr : s.JobTitle.NameEn))
+                .ForMember(s => s.IndustryName, o => o.MapFrom(s => s.Industry == null ? "" : GlobalInfo.lang == "ar" ? s.Industry.NameAr : s.Industry.NameEn))
+                .ForMember(s => s.CountryName, o => o.MapFrom(s => s.Country == null ? "" : GlobalInfo.lang == "ar" ? s.Country.NameAr : s.Country.NameEn))
+                .ForMember(s => s.UniversityName, o => o.MapFrom(s => s.University == null ? "" : GlobalInfo.lang == "ar" ? s.University.NameAr : s.University.NameEn));
             CreateMap<UserDto, UserUpdateDto>()
                 //.ForMember(m => m.CVAttach, op => op.Ignore())
                 //.ForMember(m => m.EduCertificateAttach, op => op.Ignore())

+ 48 - 1
MTWorkHR.Application/Services/Base/BlobFileService.cs

@@ -31,7 +31,7 @@ namespace MTWorkHR.Application.Services
             _logger = logger;
         }
 
-        public async Task<AttachmentResponseDto> UploadFile(IFormFile file)
+        public async Task<AttachmentResponseDto> UploadFile2(IFormFile file)
         {
             AttachmentResponseDto result = new AttachmentResponseDto();
             try
@@ -46,6 +46,8 @@ namespace MTWorkHR.Application.Services
                         uniqueFileName = GenerateUniqueFileName(file.FileName);
                     }
                     var status = await blobClient.UploadAsync(file.OpenReadStream(), true);
+                    result.ContentType = file.ContentType;
+                    result.FileSize = file.Length;
                     result.OriginalName = file.FileName;
                     result.FileName = uniqueFileName;
                     result.FilePath = blobClient.Uri.AbsoluteUri;
@@ -60,6 +62,51 @@ namespace MTWorkHR.Application.Services
                 return result;
             }
         }
+
+        public async Task<AttachmentResponseDto> UploadFile(IFormFile file)
+        {
+            AttachmentResponseDto result = new AttachmentResponseDto();
+            try
+            {
+                if (file == null || file.Length == 0)
+                {
+                    _logger.LogWarning("No file uploaded or file is empty.");
+                    throw new AppException(ExceptionEnum.InCorrectFileLength);
+                }
+
+                _logger.LogInformation("Received file: Name={FileName}, ContentType={ContentType}, Length={Length}",
+                    file.FileName, file.ContentType, file.Length);
+
+                string uniqueFileName = GenerateUniqueFileName(file.FileName);
+                var blobClient = _containerClient.GetBlobClient(uniqueFileName);
+
+                if (await blobClient.ExistsAsync())
+                {
+                    uniqueFileName = GenerateUniqueFileName(file.FileName);
+                    blobClient = _containerClient.GetBlobClient(uniqueFileName);
+                }
+
+                using var stream = file.OpenReadStream();
+                if (stream.Length == 0)
+                {
+                    _logger.LogWarning("File stream is empty for file: {FileName}", file.FileName);
+                    throw new AppException(ExceptionEnum.InCorrectFileLength);
+                }
+
+                var status = await blobClient.UploadAsync(stream, true);
+                result.ContentType = file.ContentType;
+                result.FileSize = file.Length; // Should now reflect the correct size
+                result.OriginalName = file.FileName;
+                result.FileName = uniqueFileName;
+                result.FilePath = blobClient.Uri.AbsoluteUri;
+                return result;
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Failed to upload file: {Message}", ex.Message);
+                throw new AppException(ExceptionEnum.CouldNotMoveFiles);
+            }
+        }
         public async Task<string> UploadFileCloud(AttachmentDto file)
         {
             try

+ 1 - 1
MTWorkHR.Application/Services/Interfaces/ICompanyService.cs

@@ -13,7 +13,7 @@ namespace MTWorkHR.Application.Services.Interfaces
     {
       
         Task<List<CompanyDto>> GetAllCompanies();
-        Task<CompanyDto> GetById();
+        Task<UpdateCompanyDto> GetById();
         Task<CompanyDto> GetById(long companyId);
         Task<UpdateCompanyDto> GetByIdForUpdate(long companyId);
         Task Suspend(long companyId);

+ 2 - 2
MTWorkHR.Application/Services/Interfaces/IUserService.cs

@@ -15,7 +15,7 @@ namespace MTWorkHR.Application.Identity
         Task<UserUpdateDto> GetByIdForUpdate(string userId);
 
         Task<UserDto> GetByEmail(string email);
-        Task<UserDto> GetById();
+        Task<UserUpdateDto> GetById();
         Task<List<UserDto>> GetAllEmployees();
 
         Task<UserDto> GetUserById(string id);
@@ -42,7 +42,7 @@ namespace MTWorkHR.Application.Identity
         Task<bool> Update(string userId, long companyId);
         Task Suspend(string id);
         Task<bool> UnAssignCompanyEmployees(long companyId);
-        Task<(string FullName, string Email)> GetUserNameEmail(string userId);
+        Task<(string FullName, string Email, string ProfileImage)> GetUserNameEmail(string userId);
 
     }
 }

+ 57 - 9
MTWorkHR.Application/Services/Task/UserTaskAttachmentService.cs

@@ -12,20 +12,26 @@ using MTWorkHR.Infrastructure.UnitOfWorks;
 using MTWorkHR.Core.IRepositories.Base;
 using Microsoft.AspNetCore.Http;
 using System.IO;
+using System.Linq.Dynamic.Core;
+using Microsoft.EntityFrameworkCore;
+using MTWorkHR.Application.Identity;
+
 
 namespace MTWorkHR.Application.Services
 {
     public class UserTaskAttachmentService : BaseService<UserTaskAttachment, AttachmentDto, AttachmentDto>, IUserTaskAttachmentService
     {
         private readonly IUnitOfWork _unitOfWork;
-        //private readonly AppSettingsConfiguration _configuration;
-        //private readonly GlobalInfo _globalInfo;
+        private readonly IUserService _userService;
         private readonly IFileService _fileService;
+        private readonly GlobalInfo _globalInfo;
 
-        public UserTaskAttachmentService(IUnitOfWork unitOfWork, IFileService fileService) : base(unitOfWork)
+        public UserTaskAttachmentService(IUnitOfWork unitOfWork, IFileService fileService, GlobalInfo globalInfo, IUserService userService) : base(unitOfWork)
         {
             _unitOfWork = unitOfWork;
             _fileService = fileService;
+            _globalInfo = globalInfo;
+            _userService = userService;
         }
 
 
@@ -36,6 +42,41 @@ namespace MTWorkHR.Application.Services
             return response;
         }
 
+        public override async Task<PagingResultDto<AttachmentDto>> GetAll(PagingInputDto PagingInputDto)
+        {
+            var res = await _unitOfWork.UserTaskAttachment.GetAllWithChildrenAsync();
+            var query = res.Item1;
+          
+            if (PagingInputDto.Filter != null)
+            {
+                var filter = PagingInputDto.Filter;
+                query = query.Where(u => u.FileName.Contains(filter));
+            }
+
+            var order = query.OrderBy(PagingInputDto.OrderByField + " " + PagingInputDto.OrderType);
+
+            var page = order.Skip((PagingInputDto.PageNumber * PagingInputDto.PageSize) - PagingInputDto.PageSize).Take(PagingInputDto.PageSize);
+
+            var total = await query.CountAsync();
+
+            var list = MapperObject.Mapper
+                .Map<IList<AttachmentDto>>(await page.ToListAsync());
+            // Fetch user data for all employees
+            foreach (var attach in list)
+            {
+                var user = await _userService.GetUserNameEmail(attach.CreateUser);
+                attach.ProfileImage = user.ProfileImage;
+                attach.CreatedUserName = user.FullName;
+            }
+            var response = new PagingResultDto<AttachmentDto>
+            {
+                Result = list,
+                Total = total
+            };
+
+            return response;
+        }
+
         public override async Task<AttachmentDto> Create(AttachmentDto input)
         {
             //if (input.FileData != null)
@@ -54,26 +95,33 @@ namespace MTWorkHR.Application.Services
                 throw new AppException(ExceptionEnum.MapperIssue);
             }
 
-            var task = await _unitOfWork.UserTaskAttachment.AddAsync(entity);
+            var attach = await _unitOfWork.UserTaskAttachment.AddAsync(entity);
             await _unitOfWork.CompleteAsync();
 
-            var response = MapperObject.Mapper.Map<AttachmentDto>(task);
-           
+            var response = MapperObject.Mapper.Map<AttachmentDto>(attach);
+            var user = await _userService.GetUserNameEmail(attach.CreateUser);
+            response.ProfileImage = user.ProfileImage;
+            response.CreatedUserName = user.FullName;
             return response;
         }
 
 
         public override async Task<AttachmentDto> Update(AttachmentDto input)
         {
-            var entitiy = await _unitOfWork.UserTaskAttachment.GetByIdAsync(input.Id);
+            var attach = await _unitOfWork.UserTaskAttachment.GetByIdAsync(input.Id);
 
-            if (entitiy == null)
+            if (attach == null)
                 throw new AppException(ExceptionEnum.RecordNotExist);
 
-            MapperObject.Mapper.Map(input, entitiy, typeof(AttachmentDto), typeof(UserTaskAttachment));
+            MapperObject.Mapper.Map(input, attach, typeof(AttachmentDto), typeof(UserTaskAttachment));
 
             await _unitOfWork.CompleteAsync();
 
+            var response = MapperObject.Mapper.Map<AttachmentDto>(attach);
+
+            var user = await _userService.GetUserNameEmail(attach.CreateUser);
+            response.ProfileImage = user.ProfileImage;
+            response.CreatedUserName = user.FullName;
             return input;
         }
     }

+ 7 - 0
MTWorkHR.Application/Services/Task/UserTaskService.cs

@@ -33,6 +33,13 @@ namespace MTWorkHR.Application.Services
         {
             var entity = await _unitOfWork.UserTask.GetByIdWithAllChildren(id);
             var response = MapperObject.Mapper.Map<UserTaskDto>(entity);
+
+            foreach (var attach in response.TaskAttachments)
+            {
+                var user = await _userService.GetUserNameEmail(attach.CreateUser);
+                attach.ProfileImage = user.ProfileImage;
+                attach.CreatedUserName = user.FullName;
+            }
             await GetUserData(response);
             return response;
         }

+ 3 - 3
MTWorkHR.Application/Services/User/CompanyService.cs

@@ -45,12 +45,12 @@ namespace MTWorkHR.Application.Services
 
        
 
-        public async Task<CompanyDto> GetById()
+        public async Task<UpdateCompanyDto> GetById()
         {
             if (_globalInfo.CompanyId.HasValue)
-                return await GetById(_globalInfo.CompanyId.Value);
+                return await GetByIdForUpdate(_globalInfo.CompanyId.Value);
             else 
-                return new CompanyDto();
+                return new UpdateCompanyDto();
         }
         public override async Task<CompanyDto> GetById(long companyId)
         {

+ 24 - 19
MTWorkHR.Application/Services/User/TeamService.cs

@@ -82,18 +82,20 @@ namespace MTWorkHR.Application.Services
             }
             //entity.TeamUsers = input.TeamUserIds?.Select(s => new TeamUser { AssignedUserId = s,AssignedUserName = _userService.GetUserFullName(s).Result, IsAdmin = false }).ToList();
 
-
-            entity.TeamUsers = (await Task.WhenAll(input.TeamUserIds?.Select(async s =>
+            foreach(var teamUserId in input.TeamUserIds)
             {
-                var userInfo = await _userService.GetUserNameEmail(s);
-                return new TeamUser
+                var userInfo = await _userService.GetUserNameEmail(teamUserId);
+                if (entity.TeamUsers == null)
+                    entity.TeamUsers = new List<TeamUser>();
+                entity.TeamUsers.Add( new TeamUser
                 {
-                    AssignedUserId = s,
+                    AssignedUserId = teamUserId,
                     AssignedUserName = userInfo.FullName,
                     AssignedUserEmail = userInfo.Email,
+                    ProfileImage = userInfo.ProfileImage,
                     IsAdmin = false
-                };
-            }) ?? Enumerable.Empty<Task<TeamUser>>())).ToList();
+                });
+            }         
 
             var team = await _unitOfWork.Team.AddAsync(entity);
             await _unitOfWork.CompleteAsync();
@@ -120,18 +122,22 @@ namespace MTWorkHR.Application.Services
             var NewItems = input.TeamUserIds?.Where(u => !oldUsers.Contains(u));
           //  var newTeamUsers = NewItems?.Select(s => new TeamUser {TeamId = input.Id, AssignedUserId = s, AssignedUserName = _userService.GetUserFullName(s).Result, IsAdmin = false }).ToList();
 
-            var newTeamUsers = (await Task.WhenAll(NewItems?.Select(async s =>
+            var newTeamUsers = new List<TeamUser>();
+            foreach (var teamUserId in NewItems)
             {
-                var (fullName, email) = await _userService.GetUserNameEmail(s);
-                return new TeamUser
+                var userInfo = await _userService.GetUserNameEmail(teamUserId);
+                if (entity.TeamUsers == null)
+                    entity.TeamUsers = new List<TeamUser>();
+                entity.TeamUsers.Add(new TeamUser
                 {
                     TeamId = input.Id,
-                    AssignedUserId = s,
-                    AssignedUserName = fullName,
-                    AssignedUserEmail = email,
+                    AssignedUserId = teamUserId,
+                    AssignedUserName = userInfo.FullName,
+                    AssignedUserEmail = userInfo.Email,
+                    ProfileImage = userInfo.ProfileImage,
                     IsAdmin = false
-                };
-            }) ?? Enumerable.Empty<Task<TeamUser>>())).ToList();
+                });
+            }
 
             var DeletedItems = oldUsers?.Where(u => !input.TeamUserIds.Contains(u));
             _unitOfWork.BeginTran();
@@ -140,15 +146,14 @@ namespace MTWorkHR.Application.Services
                 var removeItem = entity.TeamUsers?.FirstOrDefault(u => u.AssignedUserId == delUser);
                 if(removeItem != null) await _unitOfWork.TeamUser.DeleteAsync(removeItem);
             }
-            foreach (var newUsr in newTeamUsers)
-            {
-                await _unitOfWork.TeamUser.AddAsync(newUsr);
-            }
+          
 
             await _unitOfWork.CompleteAsync();
             _unitOfWork.CommitTran();
 
             var response = Mapper.MapperObject.Mapper.Map<TeamDto>(entity);
+            response.TeamUserIds = input.TeamUserIds;
+
             return response;
         }
 

+ 13 - 6
MTWorkHR.Application/Services/User/UserService.cs

@@ -28,6 +28,7 @@ using System.ComponentModel.Design;
 using static iText.StyledXmlParser.Jsoup.Select.Evaluator;
 using static iText.IO.Util.IntHashtable;
 using Microsoft.Extensions.Logging;
+using iText.IO.Image;
 
 namespace MTWorkHR.Application.Services
 {
@@ -60,9 +61,9 @@ namespace MTWorkHR.Application.Services
             _logger = logger;
         }
 
-        public async Task<UserDto> GetById()
+        public async Task<UserUpdateDto> GetById()
         {
-            return await GetById(_globalInfo.UserId);
+            return await GetByIdForUpdate(_globalInfo.UserId);
         }
         public async Task<UserDto> GetByEmail(string email)
         {
@@ -264,7 +265,7 @@ namespace MTWorkHR.Application.Services
         }
         public async Task<UserDto> GetUserById(string id)
         {
-            var entity = await _userManager.Users
+            var entity = await _userManager.Users.Include(u=> u.UserAttachments)
                 .FirstOrDefaultAsync(x => x.Id == id);
             var response = MapperObject.Mapper.Map<UserDto>(entity);
 
@@ -277,17 +278,23 @@ namespace MTWorkHR.Application.Services
             return name;
         }
 
-        public async Task<(string FullName, string Email)> GetUserNameEmail(string userId)
+        public async Task<(string FullName, string Email, string ProfileImage)> GetUserNameEmail(string userId)
         {
             var entity = await GetUserById(userId);
+            var imagePath = "";
 
             if (entity == null)
-                return (string.Empty, string.Empty);
+                return (string.Empty, string.Empty, string.Empty);
 
+            if (entity != null)
+            {
+                var imageAtt = entity.UserAttachments?.FirstOrDefault(a => a.AttachmentTypeId == 9);
+                imagePath = imageAtt != null ? imageAtt.FilePath : "";
+            }
             var name = $"{entity.FirstName} {entity.LastName}".Trim();
             var email = entity.Email ?? string.Empty;
 
-            return (name, email);
+            return (name, email, imagePath);
         }
 
         public async Task<UserDto> GetUserWithAttachmentById(string id)

+ 1 - 0
MTWorkHR.Core/Entities/User/TeamUser.cs

@@ -19,6 +19,7 @@ namespace MTWorkHR.Core.Entities
         public string AssignedUserId { get; set; }
         public string AssignedUserName { get; set; }
         public string AssignedUserEmail { get; set; }
+        public string? ProfileImage { get; set; }
         public bool IsAdmin { get; set; }
 
     }

+ 1 - 1
MTWorkHR.Core/Entities/User/UserTaskAttachment.cs

@@ -21,7 +21,7 @@ namespace MTWorkHR.Core.Entities
 
         [MaxLength(250)]
         public string? OriginalName { get; set; }
-
+        public long? FileSize { get; set; }
         public byte[] Content { get; set; }
         public string? FilePath { get; set; }
         public string? ContentType { get; set; }

+ 1 - 0
MTWorkHR.Core/IRepositories/Task/IUserTaskAttachmentRepository.cs

@@ -11,5 +11,6 @@ namespace MTWorkHR.Core.IRepositories
 {
     public interface IUserTaskAttachmentRepository : IRepository<UserTaskAttachment>
     {
+        Task<Tuple<IQueryable<UserTaskAttachment>, int>> GetAllWithChildrenAsync();
     }
 }

+ 27 - 18
MTWorkHR.Infrastructure/EmailService/MailSender.cs

@@ -42,7 +42,13 @@ namespace MTWorkHR.Infrastructure.EmailService
 
         //    return response.IsSuccessStatusCode;
         //}
-        public async Task<bool> SendEmail(EmailMessage email)
+
+        /// <summary>
+        /// Send Email using an azure email address, smtpUserName and password
+        /// </summary>
+        /// <param name="email"></param>
+        /// <returns></returns>
+        public async Task<bool> SendEmailAzure(EmailMessage email)
         {
             var mailTo = email.To;
             var settings = _configuration.MailSettings;
@@ -99,22 +105,16 @@ namespace MTWorkHR.Infrastructure.EmailService
                 _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
                 settings.SmtpUsername, ex.Message);
                 throw ex;
-                Console.WriteLine($"Authentication failed: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
-                return false;
             }
             catch (SmtpCommandException ex)
             {
                 _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
                 throw ex;
-                Console.WriteLine($"SMTP error: {ex.Message}, Status: {ex.StatusCode}, Inner Exception: {ex.InnerException?.Message}");
-                return false;
             }
             catch (Exception ex)
             {
                 _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
                 throw ex;
-                Console.WriteLine($"Error sending email: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
-                return false;
             }
             finally
             {
@@ -128,7 +128,9 @@ namespace MTWorkHR.Infrastructure.EmailService
 
             return true;
         }
-        public async Task<bool> SendEmailSMTP(EmailMessage email)
+
+        //Send Email using an email address and password
+        public async Task<bool> SendEmail(EmailMessage email)
         {
             var mailTo = email.To;
             var settings = _configuration.MailSettings;
@@ -158,25 +160,32 @@ namespace MTWorkHR.Infrastructure.EmailService
             using var smtp = new SmtpClient(logger);
             try
             {
-               
-
-                smtp.Connect(_configuration.MailSettings.Host, _configuration.MailSettings.Port, MailKit.Security.SecureSocketOptions.StartTls);
-                smtp.Authenticate(_configuration.MailSettings.FromAddress, _configuration.MailSettings.Password);
+                await smtp.ConnectAsync(_configuration.MailSettings.Host, _configuration.MailSettings.Port, MailKit.Security.SecureSocketOptions.StartTls);
+                await smtp.AuthenticateAsync(_configuration.MailSettings.FromAddress, _configuration.MailSettings.Password);
+                _logger.LogInformation("Sending email to {To} with subject {Subject}", mailTo, email.Subject);
                 await smtp.SendAsync(emailObj);
-                //smtp.Disconnect(true);
+                _logger.LogInformation("Email sent successfully to {To}", mailTo);
+
             }
-            catch (MailKit.Security.AuthenticationException ex)
+            catch (AuthenticationException ex)
             {
-                Console.WriteLine($"Authentication failed: {ex.Message}");
-                throw;
+                _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
+                settings.SmtpUsername, ex.Message);
+                throw ex;
+            }
+            catch (SmtpCommandException ex)
+            {
+                _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
+                throw ex;
             }
             catch (Exception ex)
             {
-                Console.WriteLine($"Error sending email: {ex.Message}");
-                throw;
+                _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
+                throw ex;
             }
             finally
             {
+                _logger.LogInformation("Disconnected from SMTP server");
                 await smtp.DisconnectAsync(true);
             }
             return true;

+ 1 - 1
MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs

@@ -32,7 +32,7 @@ namespace MTWorkHR.Infrastructure
             
             services.AddDbContext<HRDataContext>(options =>
                 options.UseSqlServer(
-                    config.ConnectionStrings.MTWorkHRConnectionString  //configuration.GetSection("ConnectionString:MTWorkHRConnectionString").Value
+                    config.ConnectionStrings.LocalConnectionString  //configuration.GetSection("ConnectionString:MTWorkHRConnectionString").Value
                     ));
            
             services.AddIdentity<ApplicationUser, ApplicationRole>().AddEntityFrameworkStores<HRDataContext>().AddDefaultTokenProviders();

ファイルの差分が大きいため隠しています
+ 7360 - 0
MTWorkHR.Infrastructure/Migrations/20250529131711_altrTaskAttachment.Designer.cs


+ 38 - 0
MTWorkHR.Infrastructure/Migrations/20250529131711_altrTaskAttachment.cs

@@ -0,0 +1,38 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrTaskAttachment : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<long>(
+                name: "FileSize",
+                table: "UserTaskAttachments",
+                type: "bigint",
+                nullable: true);
+
+            migrationBuilder.AddColumn<string>(
+                name: "ProfileImage",
+                table: "TeamUser",
+                type: "nvarchar(max)",
+                nullable: true);
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "FileSize",
+                table: "UserTaskAttachments");
+
+            migrationBuilder.DropColumn(
+                name: "ProfileImage",
+                table: "TeamUser");
+        }
+    }
+}

+ 6 - 0
MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs

@@ -4845,6 +4845,9 @@ namespace MTWorkHR.Infrastructure.Migrations
                     b.Property<bool>("IsAdmin")
                         .HasColumnType("bit");
 
+                    b.Property<string>("ProfileImage")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<long>("TeamId")
                         .HasColumnType("bigint");
 
@@ -5162,6 +5165,9 @@ namespace MTWorkHR.Infrastructure.Migrations
                     b.Property<string>("FilePath")
                         .HasColumnType("nvarchar(max)");
 
+                    b.Property<long?>("FileSize")
+                        .HasColumnType("bigint");
+
                     b.Property<string>("OriginalName")
                         .HasMaxLength(250)
                         .HasColumnType("nvarchar(250)");

+ 10 - 0
MTWorkHR.Infrastructure/Repositories/Task/TaskAttachmentRepository.cs

@@ -9,9 +9,19 @@ namespace MTWorkHR.Infrastructure.Repositories
 {
     public class UserTaskAttachmentRepository : Repository<UserTaskAttachment>, IUserTaskAttachmentRepository
     {
+        private readonly DbSet<UserTaskAttachment> dbSet;
+
         public UserTaskAttachmentRepository(HRDataContext context) : base(context)
         {
+            dbSet = context.Set<UserTaskAttachment>();
+
         }
+        public async Task<Tuple<IQueryable<UserTaskAttachment>, int>> GetAllWithChildrenAsync()
+        {
+            var query = dbSet.AsQueryable();
+            var total = await query.CountAsync();
 
+            return new Tuple<IQueryable<UserTaskAttachment>, int>(query, total);
+        }
     }
 }