zinab_elgendy 1 неделя назад
Родитель
Сommit
8125d9c8c3
28 измененных файлов с 15502 добавлено и 29 удалено
  1. 34 2
      MTWorkHR.API/Controllers/ContractController.cs
  2. 4 12
      MTWorkHR.API/MTWorkHR.API.csproj
  3. BIN
      MTWorkHR.API/contract.pdf
  4. 1 0
      MTWorkHR.Application/ApplicationServiceRegistration.cs
  5. 23 7
      MTWorkHR.Application/Chat/ChatHub.cs
  6. 2 0
      MTWorkHR.Application/Dtos/Attendance/OverTimeDayDto.cs
  7. 1 0
      MTWorkHR.Application/Dtos/Contract/ContractDto.cs
  8. 1 0
      MTWorkHR.Application/Dtos/User/EmployeeDto.cs
  9. 5 1
      MTWorkHR.Application/Mapper/MappingProfile.cs
  10. 41 1
      MTWorkHR.Application/Services/Base/BlobFileService.cs
  11. 5 0
      MTWorkHR.Application/Services/Base/FileService.cs
  12. 73 0
      MTWorkHR.Application/Services/Contract/ContractPdfService.cs
  13. 118 1
      MTWorkHR.Application/Services/Contract/ContractService.cs
  14. 12 0
      MTWorkHR.Application/Services/Interfaces/IContractPdfService.cs
  15. 8 0
      MTWorkHR.Application/Services/Interfaces/IContractService.cs
  16. 1 0
      MTWorkHR.Application/Services/Interfaces/IFileService.cs
  17. 1 1
      MTWorkHR.Application/Services/User/OrderRequestService.cs
  18. 1 0
      MTWorkHR.Core/Entities/Attendance/OverTimeDay.cs
  19. 1 0
      MTWorkHR.Core/Entities/Contract/Contract.cs
  20. 90 0
      MTWorkHR.Core/Entities/Contract/ContractDetail.cs
  21. 97 0
      MTWorkHR.Infrastructure/Entities/ContractDetail.cs
  22. 2 4
      MTWorkHR.Infrastructure/MTWorkHR.Infrastructure.csproj
  23. 7260 0
      MTWorkHR.Infrastructure/Migrations/20250324091142_altrContractFile.Designer.cs
  24. 28 0
      MTWorkHR.Infrastructure/Migrations/20250324091142_altrContractFile.cs
  25. 7263 0
      MTWorkHR.Infrastructure/Migrations/20250326203251_altrOvertimeDay.Designer.cs
  26. 28 0
      MTWorkHR.Infrastructure/Migrations/20250326203251_altrOvertimeDay.cs
  27. 6 0
      MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs
  28. 396 0
      MTWorkHR.Infrastructure/Reports/ContractPdfGenerator.cs

+ 34 - 2
MTWorkHR.API/Controllers/ContractController.cs

@@ -6,6 +6,7 @@ using MTWorkHR.Application.Filters;
 using MTWorkHR.Application.Models;
 using MTWorkHR.Application.Services;
 using MTWorkHR.Application.Services.Interfaces;
+using System.IO;
 
 namespace MTWorkHR.API.Controllers
 {
@@ -16,11 +17,13 @@ namespace MTWorkHR.API.Controllers
     {
         private readonly IContractService _ContractService;
         private readonly IFileService _fileService;
+      //  private readonly IContractPdfService _pdfService;
 
-        public ContractController(IContractService UserContractService, IFileService fileService)
+        public ContractController(IContractService UserContractService, IFileService fileService/*, IContractPdfService pdfService*/)
         {
             _ContractService = UserContractService;
             _fileService = fileService;
+      //      _pdfService = pdfService;
         }
         [HttpGet("GetAll")]
         [ProducesResponseType(StatusCodes.Status200OK)]
@@ -71,7 +74,36 @@ namespace MTWorkHR.API.Controllers
             return await _ContractService.ChangeStatus(input.ContractId, input.StatusId);
         }
 
-       
+
+        [HttpPost("generate")]
+        public async Task <AttachmentResponseDto> GenerateContract([FromQuery] long contractId)
+        {
+            string outputPath = Path.Combine(Directory.GetCurrentDirectory(), "contract.pdf");
+           var response = await _ContractService.GenerateContractPdf(outputPath, contractId);
+         //   return File(stream, "application/pdf", "example.pdf");
+
+            //string blobUrl = _pdfService.GenerateContractPdf(contractData);
+
+            //// Return the URL to the client
+            return (response);
+
+            //return  PhysicalFile(outputPath, "application/pdf", "contract.pdf");
+        }
+
+        [HttpGet("generate-pdf")]
+        public IActionResult GeneratePdf()
+        {
+            try
+            {
+                var stream = _ContractService.generatePdfTest();
+                return File(stream, "application/pdf", "example.pdf");
+            }
+            catch (Exception ex)
+            {
+                throw;
+            }
+        }
+
         //[HttpPost("CreateTaskAttachment")]
         //[ProducesResponseType(StatusCodes.Status200OK)]
         //[Consumes("multipart/form-data")]

+ 4 - 12
MTWorkHR.API/MTWorkHR.API.csproj

@@ -30,18 +30,10 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Compile Update="Reports\ProjectStages.cs">
-      <SubType>XtraReport</SubType>
-    </Compile>
-    <Compile Update="Reports\ContractTasks.cs">
-      <SubType>XtraReport</SubType>
-    </Compile>
-    <Compile Update="Reports\ContractReport.cs">
-      <SubType>XtraReport</SubType>
-    </Compile>
-    <Compile Update="Reports\ContractAllowances.cs">
-      <SubType>XtraReport</SubType>
-    </Compile>
+    <Compile Update="Reports\ProjectStages.cs" />
+    <Compile Update="Reports\ContractTasks.cs" />
+    <Compile Update="Reports\ContractReport.cs" />
+    <Compile Update="Reports\ContractAllowances.cs" />
   </ItemGroup>
 
 </Project>

BIN
MTWorkHR.API/contract.pdf


+ 1 - 0
MTWorkHR.Application/ApplicationServiceRegistration.cs

@@ -44,6 +44,7 @@ namespace MTWorkHR.Application
             services.AddScoped<ISubscriptionService, SubscriptionService>();
             services.AddScoped<IMatchMoveService, MatchMoveService>();
             services.AddScoped<IAmazonPayService, AmazonPayService>();
+           // services.AddScoped<IContractPdfService, ContractPdfService>();
 
             services.AddHttpClient<AmazonPayService>();
 

+ 23 - 7
MTWorkHR.Application/Chat/ChatHub.cs

@@ -38,16 +38,16 @@ namespace MTWorkHR.API.Chat
             _logger = logger;
         }
 
-        public async Task GetUsers()
+        public async Task GetUsers(bool internalUsers)
         {
-            var myCompanyUsers = await GetAllCompanyEmployees();
+            var myCompanyUsers = await GetAllCompanyEmployees(internalUsers);
 
             await Clients.Caller.SendAsync("UpdateUserList", myCompanyUsers);
         }
 
 
 
-        public async Task<List<ChatUserDto>> GetAllCompanyEmployees()
+        public async Task<List<ChatUserDto>> GetAllCompanyEmployees(bool internalUsers)
         {
             var response = new List<ChatUserDto>();
 
@@ -71,11 +71,27 @@ namespace MTWorkHR.API.Chat
                     .Distinct()
                     .ToHashSet();
 
-                // Filter all employees by CompanyId or if they have messaged the user
+
                 var employeesToChat = allEmployees
-                    .Where(e => e.Id != userId &&
-                               (e.CompanyId == CompanyId || companyUserIds.Contains(e.Id)))
-                    .ToList();
+                       .Where(e => e.Id != userId && (e.CompanyId == CompanyId || companyUserIds.Contains(e.Id)));
+                if (internalUsers)
+                {
+                    // Filter all employees by inside Company or if they have messaged the user
+                    employeesToChat = employeesToChat
+                        .Where(e => e.CompanyId == CompanyId)
+                        .ToList();
+                }
+                else
+                {// Filter all employees outside  user Company or if they have messaged the user
+                    employeesToChat = employeesToChat
+                      .Where(e => e.CompanyId != CompanyId)
+                      .ToList();
+                }
+                // Filter all employees by CompanyId or if they have messaged the user
+                //var employeesToChat = allEmployees
+                //    .Where(e => e.Id != userId &&
+                //               (e.CompanyId == CompanyId || companyUserIds.Contains(e.Id)))
+                //    .ToList();
 
                 // Get online users and map to a dictionary for faster lookups
                 var allConnections = await _unitOfWork.HubConnection.GetAllAsync();

+ 2 - 0
MTWorkHR.Application/Dtos/Attendance/OverTimeDayDto.cs

@@ -17,6 +17,8 @@ namespace MTWorkHR.Application.Models
         public string? StartTime { get; set; }
         public string? EndTime { get; set; }
         public decimal? TotalHours { get; set; }
+        public string? OverTimeDetail { get; set; }
+
         public OrderAttachmentDto? OverTimeAttachment { get; set; }
     }
 }

+ 1 - 0
MTWorkHR.Application/Dtos/Contract/ContractDto.cs

@@ -77,6 +77,7 @@ namespace MTWorkHR.Application.Models
         public decimal? LastPatchAmount { get; set; }
         public string? Teams{ get; set; }
         public string? Vacations{ get; set; }
+        public string? FilePath { get; set; }// on cloud
 
         //__________________HR data_________-
         public List<TeamDto>? TeamList { get; set; }

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

@@ -15,6 +15,7 @@ namespace MTWorkHR.Application.Models
 
         public string? LastName { get; set; }
         public string? Email { get; set; }
+        public string? Position { get; set; }
         public string? ProfileImagePath { get; set; }
     }
 }

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

@@ -162,6 +162,7 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<Contract, ContractDto>().ForMember(d => d.WorkingDays, o => o.Ignore());
             CreateMap<Contract, ContractHRDto>().ForMember(d => d.WorkingDays, o => o.Ignore());
             CreateMap<Contract, ContractAllHRDto>();
+            
             CreateMap<ContractDto, Contract>()
                 .ForMember(d => d.CreateDate, o => o.Ignore())
                 .ForMember(d => d.CreateUser, o => o.Ignore());
@@ -173,7 +174,10 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<ProjectStageAttachment, ProjectStageAttachmentDto>().ReverseMap().ForMember(d => d.CreateDate, o => o.Ignore()).ForMember(d => d.CreateUser, o => o.Ignore()); ;
             CreateMap<SubscriptionConfiguration, SubscriptionConfigurationDto>().ReverseMap().ForMember(d => d.CreateDate, o => o.Ignore()).ForMember(d => d.CreateUser, o => o.Ignore()); ;
 
-
+            CreateMap<ContractDetail, Contract>();
+            CreateMap<Contract, ContractDetail>();
+            //.ForMember(s => s.ContractDuration, o => o.MapFrom(s => s.ContractDurationId == null ? "" : ((ContractDurationEnum)s.ContractDurationId).ToString()));
+            //.ForMember(s => s.WorkCountry, o => o.MapFrom(s => s.WorkCountryId == null ? "" : s.WorkCountryId));
         }
     }
 }

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

@@ -4,6 +4,7 @@ using Azure.Storage.Blobs.Models;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.StaticFiles;
+using Microsoft.Extensions.Logging;
 using MTWorkHR.Application.Models;
 using MTWorkHR.Application.Services.Interfaces;
 using MTWorkHR.Core.Global;
@@ -20,12 +21,14 @@ namespace MTWorkHR.Application.Services
         public const string ErrorMessageKey = "ErrorMessage";
         private readonly BlobServiceClient _blobServiceClient;
         private readonly BlobContainerClient _containerClient;
+        private readonly ILogger<BlobFileService> _logger;
 
-        public BlobFileService(BlobServiceClient blobServiceClient)
+        public BlobFileService(BlobServiceClient blobServiceClient, ILogger<BlobFileService> logger)
         {
             _blobServiceClient = blobServiceClient;
             _containerClient = _blobServiceClient.GetBlobContainerClient(ContainerName);
             _containerClient.CreateIfNotExists();
+            _logger = logger;
         }
         public async Task<AttachmentResponseDto> UploadFile(IFormFile file)
         {
@@ -80,7 +83,44 @@ namespace MTWorkHR.Application.Services
                 return "";
             }
         }
+        public async Task<AttachmentResponseDto> UploadFile(byte[] pdfBytes, string fileName)
+        {
+            AttachmentResponseDto result = new AttachmentResponseDto();
+            try
+            {
+                // Get a reference to the container
+                //BlobContainerClient containerClient = _blobServiceClient.GetBlobContainerClient("Contracts");
+
+                // Create the container if it doesn’t exist
+                //containerClient.CreateIfNotExists();
+                var blobClient = _containerClient.GetBlobClient(fileName);
+                if (blobClient != null)
+                {
+                    using (MemoryStream uploadStream = new MemoryStream(pdfBytes))
+                    {
+                        _logger.LogInformation("1--Contract uploadStream length={0}", pdfBytes.Length);
 
+                        var status = await blobClient.UploadAsync(uploadStream, overwrite: true);
+                        _logger.LogInformation("2--Contract uploadStream Status={0}, uri={1}", status, blobClient.Uri.AbsoluteUri);
+
+                    }
+                    result.FileName = fileName;
+                    result.FilePath = blobClient.Uri.AbsoluteUri;
+                    _logger.LogInformation("3--Contract upload finish path={0}", blobClient.Uri.AbsoluteUri);
+                    return result;
+                }
+                else
+                {
+                    _logger.LogInformation("BlobClient is null when upload file ={0}", fileName);
+                    return result;
+                }
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex.Message);
+                return result;
+            }
+        }
         public async Task<BlobObject> Download(string url)
         {
             try

+ 5 - 0
MTWorkHR.Application/Services/Base/FileService.cs

@@ -215,5 +215,10 @@ namespace MTWorkHR.Application.Services
         {
             throw new NotImplementedException();
         }
+
+        public Task<AttachmentResponseDto> UploadFile(byte[] pdfBytes, string fileName)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 73 - 0
MTWorkHR.Application/Services/Contract/ContractPdfService.cs

@@ -0,0 +1,73 @@
+
+using MTWorkHR.Application.Models;
+using MTWorkHR.Core.UnitOfWork;
+using MTWorkHR.Application.Services.Interfaces;
+using MTWorkHR.Core.Entities;
+using Microsoft.AspNetCore.Identity;
+using MTWorkHR.Application.Mapper;
+using MTWorkHR.Core.Global;
+using MTWorkHR.Infrastructure.Entities;
+using MTWorkHR.Infrastructure.Repositories;
+using MTWorkHR.Infrastructure.UnitOfWorks;
+using MTWorkHR.Core.IRepositories.Base;
+using Microsoft.AspNetCore.Http;
+using System.IO;
+using MTWorkHR.Infrastructure.Reports;
+using MTWorkHR.Core.Entities.Base;
+using Microsoft.Extensions.Logging;
+using MTWorkHR.Application.Identity;
+
+namespace MTWorkHR.Application.Services
+{
+    public class ContractPdfService
+    {
+      //  private readonly IContractService _contractService;
+      //  //   private readonly IFileService _fileService;
+      //  private readonly IUnitOfWork _unitOfWork;
+      ////  private ILogger _logger;
+      //  private readonly IUserService _userService;
+
+      //  public ContractPdfService(IUnitOfWork unitOfWork, IContractService contractService, IUserService userService) 
+      //  {
+      //     _unitOfWork = unitOfWork;
+      //     _userService = userService;
+      //     _contractService = contractService;
+      //    //  _fileService = fileService;
+      //  }
+
+      //  public async Task GenerateContractPdf(string outputPath, long contractId)
+      //  {
+      //      try
+      //      {
+      //          //    var contractData = await _unitOfWork.Contract.GetByIdWithAllChildren(contractId);
+      //          //    // var contractData = new Contract { CompanyId = 1, JobTitleName = "SW Developer", ProjectStages = new List<ProjectStage> { new ProjectStage { Title = "Team Project", ScopeOfWork = "testing" } } };
+
+      //          //    var contract = MapperObject.Mapper.Map<ContractDetail>(contractData);
+
+      //          //    var user = await _userService.GetUserById(contractData.UserId);
+      //          //    if (user != null)
+      //          //    {
+      //          //        contract.EmployeeName = user.FirstName + " " + user.LastName;
+      //          //        contract.EmployeeEmail = user.Email;
+      //          //        contract.EmployeePassport = user.PassportNumber;
+      //          //        contract.EmployeePhone = user.PhoneNumber;
+      //          //        contract.EmployeeUniversity = user.UniversityName;
+      //          //        contract.AcademicQualification = user.QualificationName;
+      //          //        contract.EmployeeJobName = user.JobTitleName;
+      //          //    }
+
+
+      //          var contract = await _contractService.GetByIdReport(contractId);
+      //          var x = await new ContractPdfGenerator().GenerateContractPdf(outputPath, contract);
+      //      }catch(Exception e)
+      //      {
+      //     //     _logger.LogError(e, "Failed to generate contract PDF for contractId {ContractId}", contractId);
+      //          var msg = e.Message;
+      //      }
+      //  }
+
+     
+
+       
+    }
+}

+ 118 - 1
MTWorkHR.Application/Services/Contract/ContractService.cs

@@ -12,6 +12,10 @@ using MTWorkHR.Infrastructure.Entities;
 using System.Linq;
 using MTWorkHR.Core.IDto;
 using MTWorkHR.Core.Entities.User;
+using System.Diagnostics.Contracts;
+using Contract = MTWorkHR.Core.Entities.Contract;
+using MTWorkHR.Infrastructure.Reports;
+using DevExpress.DataProcessing;
 namespace MTWorkHR.Application.Services
 {
     public class ContractService : BaseService<Contract, ContractDto, ContractDto>, IContractService
@@ -19,14 +23,16 @@ namespace MTWorkHR.Application.Services
         private readonly IUnitOfWork _unitOfWork;
         private readonly IUserService _userService;
         private readonly GlobalInfo _globalInfo;
+        private readonly IFileService _fileService;
         private readonly IOrderAllocationService _orderAllocationService;
 
-        public ContractService(IUnitOfWork unitOfWork, IUserService userService, GlobalInfo globalInfo, IOrderAllocationService orderAllocationService) : base(unitOfWork)
+        public ContractService(IUnitOfWork unitOfWork, IUserService userService, GlobalInfo globalInfo, IOrderAllocationService orderAllocationService, IFileService fileService) : base(unitOfWork)
         {
             _unitOfWork = unitOfWork;
             _userService = userService;
             _globalInfo = globalInfo;
             _orderAllocationService = orderAllocationService;
+            _fileService = fileService;
         }
 
         public override async Task<ContractDto> GetById(long id)
@@ -317,6 +323,117 @@ namespace MTWorkHR.Application.Services
             
         }
 
+        public async Task<ContractDetail> GetByIdReport(long id)
+        {
+            var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(id);
+            var contract = MapperObject.Mapper.Map<ContractDetail>(entity);
+            contract.WorkingDays = entity.WorkingDays;//!= null ? entity.WorkingDays.Split(",").ToList() : null;
+            var user = await _userService.GetUserById(entity.UserId);
+            if (user != null)
+            {
+                contract.EmployeeName = user.FirstName + " " + user.LastName;
+                contract.EmployeeEmail = user.Email;
+                contract.EmployeePassport = user.PassportNumber;
+                contract.EmployeePhone = user.PhoneNumber;
+                contract.EmployeeUniversity = user.UniversityName;
+                contract.AcademicQualification = user.QualificationName;
+                contract.EmployeeJobName = user.JobTitleName;
+            }
+            return contract;
+        }
+
+
 
+        public async Task<AttachmentResponseDto> GenerateContractPdf(string outputPath, long contractId)
+        {
+            try
+            {
+                var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(contractId);
+
+                var contract = new ContractDetail
+                {
+                    StartDate = entity.StartDate,
+                    BillingCycle = entity.BillingCycle,
+                    ContractDuration = entity.ContractDurationId != null ? ((ContractDurationEnum)entity.ContractDurationId).ToString() : "",
+                    ContractStatusId = (ContractStatusEnum)entity.ContractStatusId,
+                    FirstPatchAmount = entity.FirstPatchAmount,
+                    FirstPatchDateFrom = entity.FirstPatchDateFrom,
+                    FirstPatchDateTo = entity.FirstPatchDateTo,
+                    LastPatchAmount = entity.LastPatchAmount,
+                    LastPatchDateFrom = entity.LastPatchDateFrom,
+                    LastPatchDateTo = entity.LastPatchDateTo,
+                    JobDescription = entity.JobDescription,
+                    JobNumber = entity.JobNumber,
+                    Salary = entity.Salary,
+                    JobTitleName = entity.JobTitleName,//Specialization = entity.SpecializationId,
+                    TrialPeriod = entity.TrialPeriod,
+                    VacationDays = entity.VacationDays, //WhoCanTerminateContract = entity.WhoCanTerminateContract,TypeOfWork = entity.TypeOfWork
+                                                        //WhoCanTerminateContractInTrial = 
+                    WorkCountry = entity.WorkCountryId + "",
+                    WorkingHours = entity.WorkingHours + "",
+                    ContractTypeId = (ContractTypeEnum)entity.ContractTypeId,
+                    Currency = entity.Currency,
+                    FixedAllowances = entity.FixedAllowances,
+                    ProjectStages = entity.ProjectStages,
+                    ContractTasks = entity.ContractTasks,
+                    WorkState = entity.WorkStateId + "",
+                    WorkingDays = entity.WorkingDays
+                };              
+                
+                var user = await _userService.GetUserById(entity.UserId);
+                if (user != null)
+                {
+                    contract.EmployeeName = user.FirstName + " " + user.LastName;
+                    contract.EmployeeEmail = user.Email;
+                    contract.EmployeePassport = user.PassportNumber;
+                    contract.EmployeePhone = user.PhoneNumber;
+                    contract.EmployeeUniversity = user.UniversityName;
+                    contract.AcademicQualification = user.QualificationName;
+                    contract.EmployeeJobName = user.JobTitleName;
+                    contract.EmployeeDateOfBirth = user.DateOfBirth;
+                }
+                var representativeUser = await _userService.GetUserById(entity.CompanyRepresentativeId);
+                if (representativeUser != null)
+                {
+                    contract.CompanyRepresentativeName = representativeUser.FirstName + " " + representativeUser.LastName;
+                    contract.CompanyRepresentativeEmail = representativeUser.Email;
+                    contract.CompanyRepresentativePassport = representativeUser.PassportNumber;
+                    contract.CompanyRepresentativePhone = representativeUser.PhoneNumber;
+                    contract.CompanyRepresentativePosition = representativeUser.Position ?? "";
+                }
+                var company = await _unitOfWork.Company.GetByIdAsync(entity.CompanyId);
+                if (company != null)
+                {
+                    contract.CompanyName = company.CompanyName;
+                    contract.CompanyEmail = company.Email;
+                    contract.CompanyPhone = company.PhoneNumber;
+                    contract.CompanyCR = company.CRNumber;
+                    contract.CompanyAddress = company.Address;
+                }
+
+
+                var pdfBytes = await new ContractPdfGenerator().GenerateContractPdf(outputPath, contract);
+                // Upload to Azure Blob Storage and return the Blob URL
+                string fileName = $"contract_{Guid.NewGuid()}.pdf";
+                var result = await _fileService.UploadFile(pdfBytes, fileName);
+                entity.FilePath = result.FilePath;
+                await _unitOfWork.CompleteAsync();
+
+                return result;
+            }
+            catch (Exception e)
+            {
+                throw e;
+
+                //     _logger.LogError(e, "Failed to generate contract PDF for contractId {ContractId}", contractId);
+                var msg = e.Message;
+                //return new AttachmentResponseDto();
+            }
+        }
+        public byte[] generatePdfTest()
+        {
+            var pdfBytes = new ContractPdfGenerator().GeneratePdf();
+            return pdfBytes;
+        }
     }
 }

+ 12 - 0
MTWorkHR.Application/Services/Interfaces/IContractPdfService.cs

@@ -0,0 +1,12 @@
+
+using MTWorkHR.Application.Models;
+using MTWorkHR.Core.Entities;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Application.Services.Interfaces
+{
+    public interface IContractPdfService 
+    {
+        Task GenerateContractPdf(string outputPath, long contractId); // Adjust parameters as needed
+    }
+}

+ 8 - 0
MTWorkHR.Application/Services/Interfaces/IContractService.cs

@@ -1,6 +1,7 @@
 
 using MTWorkHR.Application.Models;
 using MTWorkHR.Core.Entities;
+using MTWorkHR.Infrastructure.Entities;
 using System.Threading.Tasks;
 
 namespace MTWorkHR.Application.Services.Interfaces
@@ -11,5 +12,12 @@ namespace MTWorkHR.Application.Services.Interfaces
         Task<PagingResultDto<ContractAllHRDto>> GetAllForHr(ContractPagingInputDto PagingInputDto);
         Task<bool> ChangeStatus(long contractId, int statusId);
         Task<ContractHRDto> GetByIdHRDetails(long id);
+
+
+        Task<ContractDetail> GetByIdReport(long id);
+
+        Task<AttachmentResponseDto> GenerateContractPdf(string outputPath, long contractId);
+
+        byte[] generatePdfTest();
     }
 }

+ 1 - 0
MTWorkHR.Application/Services/Interfaces/IFileService.cs

@@ -20,5 +20,6 @@ namespace MTWorkHR.Application.Services.Interfaces
         string GetActualAttachmentPath();
         Task<Tuple<MemoryStream, string, string>> GetFileDownloadInfo(string fileUrl);
         Task<BlobObject> Download(string url);
+        Task<AttachmentResponseDto> UploadFile(byte[] pdfBytes, string fileName);
     }
 }

+ 1 - 1
MTWorkHR.Application/Services/User/OrderRequestService.cs

@@ -150,7 +150,7 @@ namespace MTWorkHR.Application.Services
                     var user = await _userService.GetUserWithAttachmentById(item.RequestingEmployeeId);
                     if (user != null)
                     {
-                        item.Employee = new EmployeeDto { Id = item.RequestingEmployeeId, FirstName = user.FirstName, LastName = user.LastName, Email = user.Email };
+                        item.Employee = new EmployeeDto { Id = item.RequestingEmployeeId, FirstName = user.FirstName, LastName = user.LastName, Email = user.Email, Position = user.Position };
                         var attach = user.UserAttachments?.FirstOrDefault(a => a.AttachmentTypeId == 9);
                         item.Employee.ProfileImagePath = attach?.FilePath;
                        // if (attach != null)

+ 1 - 0
MTWorkHR.Core/Entities/Attendance/OverTimeDay.cs

@@ -20,6 +20,7 @@ namespace MTWorkHR.Core.Entities
         public string? StartTime { get; set; }
         public string? EndTime { get; set; }
         public decimal? TotalHours { get; set; }
+        public string? OverTimeDetail { get; set; }
         public OverTimeDayAttachment? OverTimeAttachment { get; set; }
     }
 }

+ 1 - 0
MTWorkHR.Core/Entities/Contract/Contract.cs

@@ -74,6 +74,7 @@ namespace MTWorkHR.Core.Entities
         public DateTime? LastPatchDateFrom { get; set; } //
         public DateTime? LastPatchDateTo { get; set; } // 
         public decimal? LastPatchAmount { get; set; }
+        public string? FilePath { get; set; }// on cloud
 
 
         //  public decimal? GrossAnnualBaseSalary { get; set; }

+ 90 - 0
MTWorkHR.Core/Entities/Contract/ContractDetail.cs

@@ -0,0 +1,90 @@
+using MTWorkHR.Core.Entities.Base;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.Global;
+
+
+namespace MTWorkHR.Core.Entities
+{
+    public class ContractDetail
+    {
+        public ContractTypeEnum ContractTypeId { get; set; }
+        public ContractStatusEnum ContractStatusId { get; set; }
+        //--------Company data-------
+        public string CompanyName { get; set; }
+        public string CompanyCR { get; set; }
+        public string CompanyEmail { get; set; }
+        public string CompanyAddress { get; set; }
+        public string CompanyPhone { get; set; }
+        //--------Company Representative-------
+        public string CompanyRepresentativeName { get; set; }
+        public string CompanyRepresentativePassport { get; set; }
+        public string CompanyRepresentativePhone { get; set; }
+        public string CompanyRepresentativeEmail { get; set; }
+        public string CompanyRepresentativePosition { get; set; }
+        //--------Employee Data------------------------------------
+        public string UserId { get; set; }
+        public string? EmployeeName { get; set; }
+        public string? EmployeeEmail { get; set; }
+        public string? EmployeePassport{ get; set; }
+        public string? EmployeePhone { get; set; }
+        public string? EmployeeUniversity { get; set; }
+        public DateTime? EmployeeDateOfBirth { get; set; }
+        //-----------------------------
+        public string? EmployeeJobName { get; set; }
+        public string? AcademicQualification { get; set; }
+        public string? Specialization { get; set; }
+        public string WorkCountry { get; set; }
+        public string WorkState { get; set; }
+        //-------------------Scope of work-----------
+        public string? JobTitleName { get; set; }
+        public string? JobDescription { get; set; }
+        [MaxLength(150)]
+        public string? JobNumber { get; set; } //ثابت و مأخوذ من المنصة
+        //----------------Contract data -------------------------
+        public DateTime? StartDate { get; set; }
+        public DateTime? EndDate { get; set; }
+
+        public string? ContractDuration { get; set; } //:  اختيار: شهري – ربعي – نصف سنوي – 3 ارباع – سنوي
+        public string? TypeOfWork { get; set; } //: :   اختيار: عقد بدوام كامل -  عقد دوام جزئي   
+        public int? VacationDays { get; set; } //اختيار: بدون – سنويا (رقم)
+        public int? TrialPeriod { get; set; } // تجربة (ادخال: تلقائياً كل ربع سنوي أسبوع تلقائياً) آخر: تعديل
+        public string? WhoCanTerminateContractInTrial { get; set; } //اختيار   الجميع – صاحب العمل – الموظف
+        public string? WhoCanTerminateContract { get; set; }
+        public int? NoticePeriodBeforeTermination { get; set; } //اختيار: بدون – تحديد (ادخال: تلقائياً مدة 10 أيام قبل انتهاء الاستحقاق) آخر: تعديل
+
+
+        //------Working time---------------
+        public string? WorkingDays { get; set; } //:   اختيار متعدد الأيام سبت أحد اثنين..... (بحيث الأيام الأخرى تكون إجازة) 1,2,3,4,5
+        public string? WorkingHours { get; set; } //	يومي/ اسبوعي  
+        public int? WorkingHoursNum { get; set; } // عدد الساعات
+        public DateTime? StartDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
+        public DateTime? EndDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
+
+        //----------Salary-----------------
+        [MaxLength(50)]
+        public string? Currency { get; set; }
+        public decimal? Salary { get; set; }
+        public string? BillingCycle { get; set; }// 2 fortnightly, 4 Monthly
+        //------------------------Fixed Pay----------------
+        public DateTime? FirstPatchDateFrom { get; set; }
+        public DateTime? FirstPatchDateTo { get; set; } //
+        public decimal? FirstPatchAmount { get; set; }
+
+        public DateTime? LastPatchDateFrom { get; set; } //
+        public DateTime? LastPatchDateTo { get; set; } // 
+        public decimal? LastPatchAmount { get; set; }
+        public string? Teams { get; set; }
+        public string? Vacations { get; set; }
+
+
+        //---------Allowances----------------------
+        public bool IncludesAllAllowances { get; set; }
+        public List<ContractAllowance>? FixedAllowances { get; set; }
+
+        //-------------------------------
+        public List<ContractTask>? ContractTasks { get; set; }
+        public List<ProjectStage>? ProjectStages { get; set; }
+    }
+}

+ 97 - 0
MTWorkHR.Infrastructure/Entities/ContractDetail.cs

@@ -0,0 +1,97 @@
+using MTWorkHR.Core.Entities.Base;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.Global;
+using Newtonsoft.Json;
+
+namespace MTWorkHR.Infrastructure.Entities
+{
+    public class ContractDetail2
+    {
+        public ContractTypeEnum ContractTypeId { get; set; }
+        public ContractStatusEnum ContractStatusId { get; set; }
+        //--------Company data-------
+        public string CompanyName { get; set; }
+        public string CompanyCR { get; set; }
+        public string CompanyEmail { get; set; }
+        public string CompanyAddress { get; set; }
+        public string CompanyPhone { get; set; }
+        //--------Company Representative-------
+        public string CompanyRepresentativeName { get; set; }
+        public string CompanyRepresentativePassport { get; set; }
+        public string CompanyRepresentativePhone { get; set; }
+        public string CompanyRepresentativeEmail { get; set; }
+        public string CompanyRepresentativePosition { get; set; }
+        //--------Employee Data------------------------------------
+        public string UserId { get; set; }
+        [JsonProperty(Required = Required.AllowNull)]
+        public string? EmployeeName { get; set; }
+        [JsonProperty(Required = Required.AllowNull)]
+        public string? EmployeeEmail { get; set; }
+        public string? EmployeePassport{ get; set; }
+        public string? EmployeePhone { get; set; }
+        public string? EmployeeUniversity { get; set; }
+        public DateTime? EmployeeDateOfBirth { get; set; }
+        //-----------------------------
+        public string? EmployeeJobName { get; set; }
+        public string? AcademicQualification { get; set; }
+        public string? Specialization { get; set; }
+        public string WorkCountry { get; set; }
+        public string WorkState { get; set; }
+        //-------------------Scope of work-----------
+        public string? JobTitleName { get; set; }
+        public string? JobDescription { get; set; }
+        [MaxLength(150)]
+        public string? JobNumber { get; set; } //ثابت و مأخوذ من المنصة
+        //----------------Contract data -------------------------
+        public DateTime? StartDate { get; set; }
+        [JsonProperty(Required = Required.AllowNull)]
+        public DateTime? EndDate { get; set; }
+
+        [JsonProperty(Required = Required.AllowNull)]
+        public string? ContractDuration { get; set; } //:  اختيار: شهري – ربعي – نصف سنوي – 3 ارباع – سنوي
+        public string? TypeOfWork { get; set; } //: :   اختيار: عقد بدوام كامل -  عقد دوام جزئي   
+        [JsonProperty(Required = Required.AllowNull)]
+        public int? VacationDays { get; set; } //اختيار: بدون – سنويا (رقم)
+        public int? TrialPeriod { get; set; } // تجربة (ادخال: تلقائياً كل ربع سنوي أسبوع تلقائياً) آخر: تعديل
+        public string? WhoCanTerminateContractInTrial { get; set; } //اختيار   الجميع – صاحب العمل – الموظف
+        public string? WhoCanTerminateContract { get; set; }
+        [JsonProperty(Required = Required.AllowNull)]
+        public int? NoticePeriodBeforeTermination { get; set; } //اختيار: بدون – تحديد (ادخال: تلقائياً مدة 10 أيام قبل انتهاء الاستحقاق) آخر: تعديل
+
+
+        //------Working time---------------
+        [JsonProperty(Required = Required.AllowNull)]
+        public List<string>? WorkingDays { get; set; } //:   اختيار متعدد الأيام سبت أحد اثنين..... (بحيث الأيام الأخرى تكون إجازة) 1,2,3,4,5
+        public string? WorkingHours { get; set; } //	يومي/ اسبوعي  
+        public int? WorkingHoursNum { get; set; } // عدد الساعات
+        public DateTime? StartDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
+        public DateTime? EndDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
+
+        //----------Salary-----------------
+        [MaxLength(50)]
+        public string? Currency { get; set; }
+        public decimal? Salary { get; set; }
+        public string? BillingCycle { get; set; }// 2 fortnightly, 4 Monthly
+        //------------------------Fixed Pay----------------
+        public DateTime? FirstPatchDateFrom { get; set; }
+        public DateTime? FirstPatchDateTo { get; set; } //
+        public decimal? FirstPatchAmount { get; set; }
+
+        public DateTime? LastPatchDateFrom { get; set; } //
+        public DateTime? LastPatchDateTo { get; set; } // 
+        public decimal? LastPatchAmount { get; set; }
+        public string? Teams { get; set; }
+        public string? Vacations { get; set; }
+
+
+        //---------Allowances----------------------
+        public bool IncludesAllAllowances { get; set; }
+        public List<ContractAllowance>? FixedAllowances { get; set; }
+
+        //-------------------------------
+        public List<ContractTask>? ContractTasks { get; set; }
+        public List<ProjectStage>? ProjectStages { get; set; }
+    }
+}

+ 2 - 4
MTWorkHR.Infrastructure/MTWorkHR.Infrastructure.csproj

@@ -13,6 +13,8 @@
 
   <ItemGroup>
     <PackageReference Include="DevExpress.AspNetCore.Reporting" Version="24.1.6" />
+    <PackageReference Include="itext7" Version="8.0.3" />
+    <PackageReference Include="itext7.bouncy-castle-adapter" Version="8.0.3" />
     <PackageReference Include="MailKit" Version="4.3.0" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.1" />
     <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
@@ -32,8 +34,4 @@
     <ProjectReference Include="..\MTWorkHR.Core\MTWorkHR.Core.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Reports\" />
-  </ItemGroup>
-
 </Project>

Разница между файлами не показана из-за своего большого размера
+ 7260 - 0
MTWorkHR.Infrastructure/Migrations/20250324091142_altrContractFile.Designer.cs


+ 28 - 0
MTWorkHR.Infrastructure/Migrations/20250324091142_altrContractFile.cs

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

Разница между файлами не показана из-за своего большого размера
+ 7263 - 0
MTWorkHR.Infrastructure/Migrations/20250326203251_altrOvertimeDay.Designer.cs


+ 28 - 0
MTWorkHR.Infrastructure/Migrations/20250326203251_altrOvertimeDay.cs

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

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

@@ -715,6 +715,9 @@ namespace MTWorkHR.Infrastructure.Migrations
                     b.Property<DateTime?>("EndDate")
                         .HasColumnType("datetime2");
 
+                    b.Property<string>("FilePath")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<decimal?>("FirstPatchAmount")
                         .HasColumnType("decimal(18,2)");
 
@@ -3602,6 +3605,9 @@ namespace MTWorkHR.Infrastructure.Migrations
                     b.Property<DateTime?>("OverTimeDate")
                         .HasColumnType("datetime2");
 
+                    b.Property<string>("OverTimeDetail")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<string>("StartTime")
                         .HasColumnType("nvarchar(max)");
 

+ 396 - 0
MTWorkHR.Infrastructure/Reports/ContractPdfGenerator.cs

@@ -0,0 +1,396 @@
+using iText.Kernel.Colors;
+using iText.Kernel.Font;
+using iText.Kernel.Pdf;
+using iText.Layout;
+using iText.Layout.Element;
+using iText.Layout.Properties;
+using MTWorkHR.Core.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DevExpress.CodeParser;
+using iText.Kernel.Events;
+using Event = iText.Kernel.Events.Event;
+using MTWorkHR.Core.Global;
+using MTWorkHR.Infrastructure.Entities;
+using Microsoft.Extensions.Options;
+
+namespace MTWorkHR.Infrastructure.Reports
+{
+    public class ContractPdfGenerator 
+    {
+        public async Task<byte[]> GenerateContractPdf(string outputPath, ContractDetail contractData)
+        {
+            try { 
+            // Use MemoryStream to generate the PDF in memory
+            using (MemoryStream memoryStream = new MemoryStream())
+            {
+                using (PdfWriter writer = new PdfWriter(memoryStream))
+                using (PdfDocument pdf = new PdfDocument(writer))
+                using (Document document = new Document(pdf))
+                {
+                    PdfFont boldFont = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA_BOLD);
+                    PdfFont regularFont = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA);
+
+                    // Timestamp and Title
+                    document.Add(new Paragraph($"{DateTime.Now:dd/MM/yyyy HH:mm:ss} .")
+                        .SetFont(regularFont)
+                        .SetFontSize(10));
+                    document.Add(new Paragraph("Employee Contract")
+                        .SetFont(boldFont)
+                        .SetFontSize(20)
+                        .SetMarginBottom(20)
+                        .SetTextAlignment(TextAlignment.CENTER));
+
+                        // Header
+                        //        document.Add(new Paragraph("Contract Agreement")
+                        //            .SetFont(boldFont)
+                        //            .SetFontSize(20)
+                        //            .SetTextAlignment(TextAlignment.CENTER));
+
+                        // Company Information
+                        document.Add(new Paragraph("Company Information:")
+                            .SetFont(boldFont)
+                            .SetFontSize(12));
+                        Table companyTable = new Table(new float[] { 1, 3, 1, 1 }).UseAllAvailableWidth();
+                        companyTable.AddCell(CreateCell("Name:", boldFont));
+                        companyTable.AddCell(CreateCell(contractData.CompanyName, regularFont));
+                        companyTable.AddCell(CreateCell("CR:", boldFont));
+                        companyTable.AddCell(CreateCell(contractData.CompanyCR, regularFont));
+                        companyTable.AddCell(CreateCell("Email:", boldFont));
+                        companyTable.AddCell(CreateCell(contractData.CompanyEmail, regularFont));
+                        companyTable.AddCell(CreateCell("Phone:", boldFont));
+                        companyTable.AddCell(CreateCell(contractData.CompanyPhone, regularFont));
+                        companyTable.AddCell(CreateCell("Address:", boldFont));
+                        companyTable.AddCell(CreateCell(contractData.CompanyAddress, regularFont, 3));
+                        document.Add(companyTable);
+
+                        // Company Representative
+                        document.Add(new Paragraph("Company Representative:")
+                        .SetFont(boldFont)
+                        .SetFontSize(12)
+                        .SetMarginTop(10));
+
+                        //Representative Table
+                    Table repTable = new Table(new float[] { 1, 3 }).UseAllAvailableWidth();
+
+                        // Row 1: Name
+                        repTable.AddCell(CreateCell("Name:", boldFont));
+                        repTable.AddCell(CreateCell(contractData.CompanyRepresentativeName, regularFont));
+
+                        // Row 2: Passport
+                        repTable.AddCell(CreateCell("Passport:", boldFont));
+                        repTable.AddCell(CreateCell(contractData.CompanyRepresentativePassport, regularFont));
+
+                        // Row 3: Phone
+                        repTable.AddCell(CreateCell("Phone:", boldFont));
+                        repTable.AddCell(CreateCell(contractData.CompanyRepresentativePhone, regularFont));
+
+                        // Row 4: Email
+                        repTable.AddCell(CreateCell("Email:", boldFont));
+                        repTable.AddCell(CreateCell(contractData.CompanyRepresentativeEmail, regularFont));
+
+                        // Row 5: Position
+                        repTable.AddCell(CreateCell("Position:", boldFont));
+                        repTable.AddCell(CreateCell(contractData.CompanyRepresentativePosition, regularFont));
+
+                        document.Add(repTable);
+
+
+                        //Employee Information
+                        document.Add(new Paragraph("Employee Information:")
+                            .SetFont(boldFont)
+                            .SetFontSize(12)
+                            .SetMarginTop(10));
+                        document.Add(new Paragraph($"Name: \t {contractData.EmployeeName}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Passport: \t {contractData.EmployeePassport}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Date Of Birth: \t {contractData.EmployeeDateOfBirth:dd/MM/yyyy}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Phone: \t {contractData.EmployeePhone}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"University: \t {contractData.EmployeeUniversity}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Work Country: \t {contractData.WorkCountry}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Job: \t {contractData.JobTitleName}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Job Number: \t {contractData.JobNumber}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Job Description: \t {contractData.JobDescription}")
+                            .SetFont(regularFont));
+
+                        //Contract Details
+                        document.Add(new Paragraph("Contract")
+                            .SetFont(boldFont)
+                            .SetFontSize(12)
+                            .SetMarginTop(10));
+                        Table contractTable = new Table(new float[] { 1, 3, 1, 3 }).UseAllAvailableWidth();
+                        contractTable.AddCell(CreateCell("Start Date:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.StartDate:dd/MM/yyyy}", regularFont));
+                        contractTable.AddCell(CreateCell("End Date:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.EndDate:dd/MM/yyyy}", regularFont));
+                        contractTable.AddCell(CreateCell("Duration:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.ContractDuration}", regularFont));
+                        contractTable.AddCell(CreateCell("Contract Type:", boldFont));
+                        contractTable.AddCell(CreateCell((ContractTypeEnum)contractData.ContractTypeId + "", regularFont));
+                        contractTable.AddCell(CreateCell("Vacation Days:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.VacationDays}", regularFont));
+                        contractTable.AddCell(CreateCell("Trial Period:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.TrialPeriod}", regularFont));
+                        contractTable.AddCell(CreateCell("Termination Notice Period:", boldFont));
+                        contractTable.AddCell(CreateCell($"{contractData.NoticePeriodBeforeTermination}", regularFont));
+                        document.Add(contractTable);
+
+                        // Work Time
+                        document.Add(new Paragraph("Work Time")
+                            .SetFont(boldFont)
+                            .SetFontSize(12)
+                            .SetMarginTop(10));
+                        document.Add(new Paragraph($"Working Days: \t {contractData.WorkingDays}")
+                            .SetFont(regularFont));
+                        document.Add(new Paragraph($"Working Hours: \t {contractData.WorkingHours}")
+                            .SetFont(regularFont));
+
+                        // Salary
+                        document.Add(new Paragraph("Salary")
+                            .SetFont(boldFont)
+                            .SetFontSize(12)
+                            .SetMarginTop(10));
+                        document.Add(new Paragraph($"Amount: \t {contractData.Salary:F2} {contractData.Currency}")
+                            .SetFont(regularFont));
+
+                      
+                        
+                        if (contractData.FixedAllowances != null && contractData.FixedAllowances.Count > 0)
+                        {
+                            // Allowances
+                            document.Add(new Paragraph("Allowances")
+                                .SetFont(boldFont)
+                                .SetFontSize(12)
+                                .SetMarginTop(10));
+
+                            Table allowanceTable = new Table(new float[] { 2, 1, 2, 1 }).UseAllAvailableWidth();
+                            allowanceTable.AddHeaderCell(CreateCell("Type", boldFont));
+                            allowanceTable.AddHeaderCell(CreateCell("Rate", boldFont));
+                            allowanceTable.AddHeaderCell(CreateCell("Amount", boldFont));
+                            allowanceTable.AddHeaderCell(CreateCell("Frequency", boldFont));
+                            foreach (var allowance in contractData.FixedAllowances)
+                            {
+                                allowanceTable.AddCell(CreateCell(allowance.AllowanceType + "", regularFont));
+                                allowanceTable.AddCell(CreateCell($"{allowance.PaymentType:F2}", regularFont));
+                                allowanceTable.AddCell(CreateCell($"{allowance.EntitlementAmount:F2}", regularFont));
+                                allowanceTable.AddCell(CreateCell($"{allowance.EntitlementPercent}", regularFont));
+                            }
+                            document.Add(allowanceTable);
+                        }
+                        //ProjectStages
+                        if (contractData.ProjectStages != null && contractData.ProjectStages.Count >0)
+                        {
+                            // Allowances
+                            document.Add(new Paragraph("Project Stages")
+                                .SetFont(boldFont)
+                                .SetFontSize(12)
+                                .SetMarginTop(10));
+                            Table ProjectStagesTable = new Table(new float[] { 1, 3 }).UseAllAvailableWidth();
+                            ProjectStagesTable.AddHeaderCell(CreateCell("Title", boldFont));
+                            ProjectStagesTable.AddHeaderCell(CreateCell("Scope of work", boldFont));
+                            foreach (var allowance in contractData.ProjectStages)
+                            {
+                                ProjectStagesTable.AddCell(CreateCell(allowance.Title + "", regularFont));
+                                ProjectStagesTable.AddCell(CreateCell($"{allowance.ScopeOfWork:F2}", regularFont));
+                            }
+                            document.Add(ProjectStagesTable);
+                        }
+                        //ContractTasks
+                       
+                        if (contractData.ContractTasks != null && contractData.ContractTasks.Count > 0)
+                        {
+                            // Allowances
+                            document.Add(new Paragraph("Contract Tasks")
+                                .SetFont(boldFont)
+                                .SetFontSize(12)
+                                .SetMarginTop(10));
+                            Table ContractTasksTable = new Table(new float[] { 1, 3, 1, 3 }).UseAllAvailableWidth();
+                            ContractTasksTable.AddHeaderCell(CreateCell("Title", boldFont));
+                            ContractTasksTable.AddHeaderCell(CreateCell("Scope of work", boldFont));
+                            ContractTasksTable.AddHeaderCell(CreateCell("StartDate", boldFont));
+                            ContractTasksTable.AddHeaderCell(CreateCell("Amount", boldFont));
+                            foreach (var allowance in contractData.ContractTasks)
+                            {
+                                ContractTasksTable.AddCell(CreateCell(allowance.Title + "", regularFont));
+                                ContractTasksTable.AddCell(CreateCell($"{allowance.ScopeOfWork:F2}", regularFont));
+                                ContractTasksTable.AddCell(CreateCell($"{allowance.StartDate:dd/MM/yyyy}", regularFont));
+                                ContractTasksTable.AddCell(CreateCell($"{allowance.Amount:F2}", regularFont));
+                            }
+                            document.Add(ContractTasksTable);
+                        }
+                        // Page Numbers
+                    pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, new PageNumberEventHandler(document));
+                }
+                byte[] pdfBytes = memoryStream.ToArray();
+
+                // If you still want to save to file, you can do it here
+                //if (!string.IsNullOrEmpty(outputPath))
+                //{
+                //    await File.WriteAllBytesAsync(outputPath, pdfBytes);
+                //}
+
+                return pdfBytes;
+
+
+                    //return UploadToAzureBlob(pdfBytes, blobName);
+
+                }
+            }
+            catch (Exception e)
+            {
+                throw e;
+            }
+        }
+
+        public   byte[] GeneratePdf()
+        {
+            //_logger.LogInformation("Generating PDF...");
+            try
+            {
+                using (var stream = new MemoryStream())
+                {
+                    PdfWriter writer = new PdfWriter(stream);
+                    PdfDocument pdf = new PdfDocument(writer);
+                    Document document = new Document(pdf);
+                    document.Add(new Paragraph("Hello, Azure App Service!"));
+                    document.Close();
+                    //  _logger.LogInformation("PDF generated successfully.");
+                    return stream.ToArray();
+                }
+            }
+            catch (Exception ex)
+            {
+               // _logger.LogError(ex, "Failed to generate PDF.");
+                throw;
+            }
+        }
+        //private string UploadToAzureBlob(byte[] pdfBytes, string blobName)
+        //{
+        //    // Create a BlobServiceClient
+        //    BlobServiceClient blobServiceClient = new BlobServiceClient(_storageSettings.ConnectionString);
+
+        //    // Get a reference to the container
+        //    BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(_storageSettings.ContainerName);
+
+        //    // Create the container if it doesn’t exist
+        //    containerClient.CreateIfNotExists();
+
+        //    // Get a reference to the blob
+        //    BlobClient blobClient = containerClient.GetBlobClient(blobName);
+
+        //    // Upload the PDF bytes
+        //    using (MemoryStream uploadStream = new MemoryStream(pdfBytes))
+        //    {
+        //        blobClient.Upload(uploadStream, overwrite: true);
+        //    }
+
+        //    // Return the Blob URL
+        //    return blobClient.Uri.ToString();
+        //}
+        private Cell CreateCell(string text, PdfFont font, int colspan = 1)
+        {
+            return new Cell(1, colspan).Add(new Paragraph(text).SetFont(font).SetFontSize(10));
+        }
+
+        private class PageNumberEventHandler : IEventHandler
+        {
+            private readonly Document _document;
+
+            public PageNumberEventHandler(Document document)
+            {
+                _document = document;
+            }
+
+            public void HandleEvent(Event @event)
+            {
+                PdfDocumentEvent docEvent = (PdfDocumentEvent)@event;
+                PdfDocument pdf = docEvent.GetDocument();
+                PdfPage page = docEvent.GetPage();
+                int pageNumber = pdf.GetPageNumber(page);
+                PdfFont font = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA);
+
+                _document.ShowTextAligned(
+                    new Paragraph($"Page {pageNumber}").SetFont(font).SetFontSize(10),
+                    550, 20, pageNumber, TextAlignment.RIGHT, VerticalAlignment.BOTTOM, 0);
+            }
+        }
+    }
+}
+//public class ContractPdfGenerator 
+//    {
+//public void GenerateContractPdf(string outputPath, Contract contractData)
+//{
+//    using (PdfWriter writer = new PdfWriter(outputPath))
+//    using (PdfDocument pdf = new PdfDocument(writer))
+//    using (Document document = new Document(pdf))
+//    {
+//        PdfFont boldFont = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA_BOLD);
+//        PdfFont regularFont = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA);
+
+//        // Header
+//        document.Add(new Paragraph("Contract Agreement")
+//            .SetFont(boldFont)
+//            .SetFontSize(20)
+//            .SetTextAlignment(TextAlignment.CENTER));
+
+//        // Parties
+//        document.Add(new Paragraph($"\nThis contract is made on {DateTime.Now:MMMM dd, yyyy}, between:")
+//            .SetFont(regularFont));
+//        document.Add(new Paragraph()
+//            .Add(new Text("Party A: ").SetFont(boldFont))
+//            .Add(new Text($"{contractData.CompanyId}\n").SetFont(regularFont))
+//            .Add(new Text("Party B: ").SetFont(boldFont))
+//            .Add(new Text($"{contractData.JobTitleName}").SetFont(regularFont)));
+
+//        // Terms Table
+//        Table table = new Table(UnitValue.CreatePercentArray(new float[] { 1, 3 })).UseAllAvailableWidth();
+//        table.AddHeaderCell(new Cell().Add(new Paragraph("Clause").SetFont(boldFont)).SetBackgroundColor(ColorConstants.LIGHT_GRAY));
+//        table.AddHeaderCell(new Cell().Add(new Paragraph("Description").SetFont(boldFont)).SetBackgroundColor(ColorConstants.LIGHT_GRAY));
+//        foreach (var term in contractData.ProjectStages)
+//        {
+//            table.AddCell(new Cell().Add(new Paragraph(term.Title).SetFont(regularFont)));
+//            table.AddCell(new Cell().Add(new Paragraph(term.ScopeOfWork).SetFont(regularFont)));
+//        }
+//        document.Add(table);
+
+//        // Signatures
+//        document.Add(new Paragraph("\nSignatures:").SetFont(boldFont).SetFontSize(14));
+//        document.Add(new Paragraph("___________________________\nParty A Representative").SetFont(regularFont));
+//        document.Add(new Paragraph("___________________________\nParty B Representative").SetFont(regularFont));
+
+//        // Page numbers (via event handler if needed)
+//        pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, new PageNumberEventHandler(document));
+//    }
+//}
+
+//private class PageNumberEventHandler : IEventHandler
+//{
+//    private readonly Document _document;
+//    public PageNumberEventHandler(Document document) => _document = document;
+
+//    public void HandleEvent(iText.Kernel.Events.Event @event)
+//    {
+//        PdfDocumentEvent docEvent = (PdfDocumentEvent)@event;
+//        PdfDocument pdf = docEvent.GetDocument();
+//        PdfPage page = docEvent.GetPage();
+//        int pageNumber = pdf.GetPageNumber(page);
+//        PdfFont font = PdfFontFactory.CreateFont(iText.IO.Font.Constants.StandardFonts.HELVETICA);
+
+//        _document.ShowTextAligned(
+//            new Paragraph($"Page {pageNumber}").SetFont(font).SetFontSize(10),
+//            550, 20, pageNumber, TextAlignment.RIGHT, VerticalAlignment.BOTTOM, 0);
+//    }
+//}
+//  }
+//}
+