18 Коміти eb140b5d5b ... e1b7c33cde

Автор SHA1 Опис Дата
  zinab_elgendy e1b7c33cde AppException: handle language and fix 500 by reorder the register in program.cs 1 місяць тому
  zinab_elgendy 3349d3e7ee AppException: handle language and fix 500 by reorder the register in program.cs 1 місяць тому
  zinab_elgendy eb6fd69e62 https://www.mtwork.com 1 місяць тому
  zinab_elgendy 12f64b441e fix ConnectionString 1 місяць тому
  zinab_elgendy 3465d7649d Contract filter 1 місяць тому
  zinab_elgendy 98623bf40e remove report appSetting 1 місяць тому
  zinab_elgendy 468d072d2e CompanyUserGetMessages 1 місяць тому
  zinab_elgendy 80e19c52b1 Merge reporting and chatCompanyUsers 1 місяць тому
  zinab_elgendy a6c7d54b8f Chat getCompanyMessages 1 місяць тому
  zinab_elgendy 2780903cd5 SendMessage : empty receiver conn 1 місяць тому
  zinab_elgendy 3ea93e6370 SendMessage 1 місяць тому
  zinab_elgendy bdbb78e902 ChatUser: Default Constractor 1 місяць тому
  zinab_elgendy 44a211b485 Mapper for UserId 1 місяць тому
  zinab_elgendy f8256ddd16 unseen 1 місяць тому
  zinab_elgendy 54f4847eb8 lastMsgDate 1 місяць тому
  zinab_elgendy 2992a7661d Mapper :ApplicationUser, ChatUserDto 1 місяць тому
  zinab_elgendy da29f4e4f7 Company: add address, email, phone 1 місяць тому
  zinab_elgendy f06c7f5530 Contract with Report 1 місяць тому
61 змінених файлів з 35497 додано та 388 видалено
  1. 6 1
      MTWorkHR.API/Controllers/CompanyController.cs
  2. 8 3
      MTWorkHR.API/Controllers/ContractController.cs
  3. 23 0
      MTWorkHR.API/Controllers/CustomWebDocumentViewerController.cs
  4. 52 0
      MTWorkHR.API/Controllers/ReportingController.cs
  5. 10 0
      MTWorkHR.API/Controllers/UserController.cs
  6. 10 0
      MTWorkHR.API/MTWorkHR.API.csproj
  7. 48 25
      MTWorkHR.API/Program.cs
  8. 292 0
      MTWorkHR.API/Reports/ContractAllowances.Designer.cs
  9. 16 0
      MTWorkHR.API/Reports/ContractAllowances.cs
  10. 123 0
      MTWorkHR.API/Reports/ContractAllowances.resx
  11. 1763 0
      MTWorkHR.API/Reports/ContractReport.Designer.cs
  12. 16 0
      MTWorkHR.API/Reports/ContractReport.cs
  13. 123 0
      MTWorkHR.API/Reports/ContractReport.resx
  14. 85 0
      MTWorkHR.API/Reports/ReportStorageWebExtension.cs
  15. 1 1
      MTWorkHR.API/appsettings.json
  16. 104 36
      MTWorkHR.Application/Chat/ChatHub.cs
  17. 2 2
      MTWorkHR.Application/Dtos/Contract/ContractAllowanceDto.cs
  18. 4 2
      MTWorkHR.Application/Dtos/Contract/ContractDto.cs
  19. 17 0
      MTWorkHR.Application/Dtos/Contract/ContractPagingInputDto.cs
  20. 15 0
      MTWorkHR.Application/Dtos/Contract/ContractStatusDto.cs
  21. 3 0
      MTWorkHR.Application/Dtos/Identity/UserDto.cs
  22. 3 0
      MTWorkHR.Application/Dtos/Identity/UserUpdateDto.cs
  23. 22 0
      MTWorkHR.Application/Dtos/Lookup/NationalityDto.cs
  24. 21 16
      MTWorkHR.Application/Dtos/User/ChatUserDto.cs
  25. 5 1
      MTWorkHR.Application/Dtos/User/CompanyDto.cs
  26. 3 0
      MTWorkHR.Application/Mapper/MappingProfile.cs
  27. 6 6
      MTWorkHR.Application/Middlewares/LoggingMiddleware.cs
  28. 27 2
      MTWorkHR.Application/Services/Contract/ContractService.cs
  29. 2 1
      MTWorkHR.Application/Services/Interfaces/ICompanyService.cs
  30. 3 0
      MTWorkHR.Application/Services/Interfaces/IContractService.cs
  31. 2 1
      MTWorkHR.Application/Services/Interfaces/IUserService.cs
  32. 14 3
      MTWorkHR.Application/Services/User/CompanyService.cs
  33. 48 4
      MTWorkHR.Application/Services/User/UserService.cs
  34. 8 7
      MTWorkHR.Core/Entities/Contract/Contract.cs
  35. 2 2
      MTWorkHR.Core/Entities/Contract/ContractAllowance.cs
  36. 14 0
      MTWorkHR.Core/Entities/User/Company.cs
  37. 24 0
      MTWorkHR.Core/Entities/User/Nationality.cs
  38. 60 13
      MTWorkHR.Core/Global/AppException.cs
  39. 136 28
      MTWorkHR.Core/Global/AppExceptions.cs
  40. 17 0
      MTWorkHR.Core/Global/Enum/ContractDurationEnum.cs
  41. 1 1
      MTWorkHR.Core/Global/GlobalInfo.cs
  42. 11 0
      MTWorkHR.Core/IDto/IContractPagingInputDto.cs
  43. 1 0
      MTWorkHR.Core/IRepositories/Chat/IHubConnectionRepository.cs
  44. 1479 0
      MTWorkHR.Infrastructure/Configurations/NationalityConfiguration.cs
  45. 10 0
      MTWorkHR.Infrastructure/Configurations/RoleConfiguration.cs
  46. 1 0
      MTWorkHR.Infrastructure/DBContext/HRDataContext.cs
  47. 6 0
      MTWorkHR.Infrastructure/Entities/ApplicationUser.cs
  48. 1 1
      MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs
  49. 11 0
      MTWorkHR.Infrastructure/MTWorkHR.Infrastructure.csproj
  50. 5642 0
      MTWorkHR.Infrastructure/Migrations/20241029101807_altrUserCompany_addNationality.Designer.cs
  51. 375 0
      MTWorkHR.Infrastructure/Migrations/20241029101807_altrUserCompany_addNationality.cs
  52. 5663 0
      MTWorkHR.Infrastructure/Migrations/20241030125620_altrCompanyTbl.Designer.cs
  53. 129 0
      MTWorkHR.Infrastructure/Migrations/20241030125620_altrCompanyTbl.cs
  54. 5698 0
      MTWorkHR.Infrastructure/Migrations/20241103150423_altrRoleBusiness.Designer.cs
  55. 32 0
      MTWorkHR.Infrastructure/Migrations/20241103150423_altrRoleBusiness.cs
  56. 5698 0
      MTWorkHR.Infrastructure/Migrations/20241110132939_altrUserRoles.Designer.cs
  57. 26 0
      MTWorkHR.Infrastructure/Migrations/20241110132939_altrUserRoles.cs
  58. 5701 0
      MTWorkHR.Infrastructure/Migrations/20241112095808_altrContractDura.Designer.cs
  59. 81 0
      MTWorkHR.Infrastructure/Migrations/20241112095808_altrContractDura.cs
  60. 1783 230
      MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs
  61. 10 2
      MTWorkHR.Infrastructure/Repositories/Chat/HubConnectionRepository.cs

+ 6 - 1
MTWorkHR.API/Controllers/CompanyController.cs

@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
 using MTWorkHR.Application.Filters;
 using MTWorkHR.Application.Identity;
 using MTWorkHR.Application.Models;
+using MTWorkHR.Application.Services;
 using MTWorkHR.Application.Services.Interfaces;
 
 namespace MTWorkHR.API.Controllers
@@ -30,7 +31,11 @@ namespace MTWorkHR.API.Controllers
         {
             return Ok(await _companyService.GetById());
         }
-
+        [HttpGet("GetById")]
+        public async Task<ActionResult<CompanyDto>> GetById(long companyId)
+        {
+            return Ok(await _companyService.GetById(companyId));
+        }
 
         [HttpPost("Create")]
         [ProducesResponseType(StatusCodes.Status200OK)]

+ 8 - 3
MTWorkHR.API/Controllers/ContractController.cs

@@ -3,10 +3,9 @@
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using MTWorkHR.Application.Filters;
-using MTWorkHR.Application.Identity;
 using MTWorkHR.Application.Models;
+using MTWorkHR.Application.Services;
 using MTWorkHR.Application.Services.Interfaces;
-using MTWorkHR.Identity.Services;
 
 namespace MTWorkHR.API.Controllers
 {
@@ -23,7 +22,7 @@ namespace MTWorkHR.API.Controllers
         [HttpGet("GetAll")]
         [ProducesResponseType(StatusCodes.Status200OK)]
 
-        public async Task<ActionResult<List<ContractDto>>> GetAll([FromQuery] PagingInputDto pagingInput)
+        public async Task<ActionResult<List<ContractDto>>> GetAll([FromQuery] ContractPagingInputDto pagingInput)
         {
             return Ok(await _ContractService.GetAll(pagingInput));
         }
@@ -61,7 +60,13 @@ namespace MTWorkHR.API.Controllers
             await _ContractService.Delete(id);
         }
 
+        [HttpPost("ChangeStatus")]
+        [ProducesResponseType(StatusCodes.Status200OK)]
 
+        public async Task<bool> ChangeStatus([FromBody] ContractStatusDto input)
+        {
+            return await _ContractService.ChangeStatus(input.ContractId, input.StatusId);
+        }
 
     }
 }

+ 23 - 0
MTWorkHR.API/Controllers/CustomWebDocumentViewerController.cs

@@ -0,0 +1,23 @@
+using DevExpress.AspNetCore.Reporting.QueryBuilder.Native.Services;
+using DevExpress.AspNetCore.Reporting.QueryBuilder;
+using DevExpress.AspNetCore.Reporting.WebDocumentViewer.Native.Services;
+using DevExpress.AspNetCore.Reporting.WebDocumentViewer;
+using Microsoft.AspNetCore.Mvc;
+
+namespace MTWorkHR.API.Controllers
+{
+    [ApiExplorerSettings(IgnoreApi = true)]
+    public class CustomWebDocumentViewerController : WebDocumentViewerController
+    {
+        public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService controllerService) : base(controllerService)
+        {
+        }
+    }
+    [ApiExplorerSettings(IgnoreApi = true)]
+    public class CustomQueryBuilderController : QueryBuilderController
+    {
+        public CustomQueryBuilderController(IQueryBuilderMvcControllerService controllerService) : base(controllerService)
+        {
+        }
+    }
+}

+ 52 - 0
MTWorkHR.API/Controllers/ReportingController.cs

@@ -0,0 +1,52 @@
+
+using Microsoft.AspNetCore.Mvc;
+using DevExpress.XtraReports.UI;
+using DevExpress.XtraReports.Web.Extensions;
+using System.IO;
+
+namespace MTWorkHR.API.Controllers
+{
+    [ApiController]
+    [Route("api/[controller]")]
+    public class ReportController : ControllerBase
+    {
+        private readonly ReportStorageWebExtension _reportStorage;
+
+        public ReportController(ReportStorageWebExtension reportStorage)
+        {
+            _reportStorage = reportStorage;
+        }
+
+        [HttpGet("generate-pdf")]
+        public async Task<IActionResult> GeneratePdf(string reportUrl)
+        {
+            byte[] reportData = _reportStorage.GetData(reportUrl);
+
+            // Load the report from the byte array
+            using (MemoryStream ms = new MemoryStream(reportData))
+            {
+                XtraReport report = XtraReport.FromStream(ms, true);
+
+                using (MemoryStream pdfStream = new MemoryStream())
+                {
+                    try
+                    {
+                        if (report.DataSource == null)
+                        {
+                            var m = "The report's DataSource is null.";
+                        }
+                        await report.CreateDocumentAsync();
+
+                        await report.ExportToPdfAsync(pdfStream);
+                    }
+                    catch(Exception e)
+                    {
+                        var mess = e.Message;
+                    }
+                    return File(pdfStream.ToArray(), "application/pdf", "GeneratedReport.pdf");
+                }
+            }
+        }
+
+    }
+}

+ 10 - 0
MTWorkHR.API/Controllers/UserController.cs

@@ -36,7 +36,17 @@ namespace MTWorkHR.API.Controllers
         {
             return Ok(await _userService.GetById());
         }
+        [HttpGet("GetById")]
+        public async Task<ActionResult<UserDto>> GetById(string userId)
+        {
+            return Ok(await _userService.GetById(userId));
+        }
 
+        [HttpGet("GetByEmail")]
+        public async Task<ActionResult<UserDto>> GetByEmail(string userId)
+        {
+            return Ok(await _userService.GetByEmail(userId));
+        }
 
         [HttpPost("Create")]
         [ProducesResponseType(StatusCodes.Status200OK)]

+ 10 - 0
MTWorkHR.API/MTWorkHR.API.csproj

@@ -11,6 +11,7 @@
 
   <ItemGroup>
     <PackageReference Include="Azure.Storage.Blobs" Version="12.20.0" />
+    <PackageReference Include="DevExpress.AspNetCore.Reporting" Version="24.1.6" />
     <PackageReference Include="dotenv.net" Version="3.2.0" />
     <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.8" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
@@ -28,4 +29,13 @@
     <ProjectReference Include="..\MTWorkHR.Infrastructure\MTWorkHR.Infrastructure.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Compile Update="Reports\ContractReport.cs">
+      <SubType>XtraReport</SubType>
+    </Compile>
+    <Compile Update="Reports\ContractAllowances.cs">
+      <SubType>XtraReport</SubType>
+    </Compile>
+  </ItemGroup>
+
 </Project>

+ 48 - 25
MTWorkHR.API/Program.cs

@@ -17,6 +17,11 @@ using Moq;
 
 
 using Microsoft.Extensions.DependencyInjection;
+using DevExpress.AspNetCore;
+using DevExpress.XtraCharts;
+using DevExpress.XtraReports.Web.Extensions;
+using DevExpress.AspNetCore.Reporting;
+using MTWorkHR.Infrastructure.Reports;
 using MTWorkHR.API.Chat;
 using Microsoft.AspNetCore.SignalR;
 
@@ -33,7 +38,7 @@ var config = new AppSettingsConfiguration();
 // Add services to the container.
 builder.Services.AddDbContext<HRDataContext>(options =>
 {
-    options.UseSqlServer(config.ConnectionStrings.LocalConnectionString);
+    options.UseSqlServer(config.ConnectionStrings.MTWorkHRConnectionString);
     //  options.UseSqlServer(builder.Configuration.GetSection("ConnectionStrings:MTWorkHRConnectionString").Value);
 });
 
@@ -75,7 +80,7 @@ builder.Services.AddControllers(options =>
 {
     //add filter by instance
     options.Filters.Add(new InputValidationActionFilter());
-    //add filter By the type 
+    //add filter By the type
     options.Filters.Add(typeof(InputValidationActionFilter));
 });
 //disable default model validation, because we handle this in InputValidationActionFilter and LoggingMiddleware.
@@ -83,10 +88,31 @@ builder.Services.Configure<ApiBehaviorOptions>(options =>
 {
     options.SuppressModelStateInvalidFilter = true;
 });
+
+builder.Services.AddDevExpressControls(); // Add DevExpress Reporting controls
+
+//Reporting
+
+
+builder.Services.AddScoped<ReportStorageWebExtension, CustomReportStorageWebExtension>();
+
+builder.Services.ConfigureReportingServices(configurator => {
+    configurator.ConfigureWebDocumentViewer(viewerConfigurator => {
+        viewerConfigurator.UseCachedReportSourceBuilder();
+    });
+});
+
 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 builder.Services.AddEndpointsApiExplorer();
 //builder.Services.AddSwaggerGen();
 //--------------------------
+builder.Services.AddSignalR(options =>
+{
+    options.EnableDetailedErrors = true;
+});
+builder.Services.AddCors(options => {
+    options.AddPolicy("CORSPolicy", builder => builder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().SetIsOriginAllowed((hosts) => true));
+});
 builder.Services.AddSwaggerGen(swagger =>
 {
     //This is to apply global headers for all requests
@@ -95,7 +121,7 @@ builder.Services.AddSwaggerGen(swagger =>
     //This is to export enums to front
     swagger.SchemaFilter<EnumSchemaFilter>();
 
-    //This is to generate the Default UI of Swagger Documentation  
+    //This is to generate the Default UI of Swagger Documentation
     swagger.SwaggerDoc("v1", new OpenApiInfo
     {
         Version = "v1",
@@ -107,7 +133,7 @@ builder.Services.AddSwaggerGen(swagger =>
             d => (d.ActionDescriptor as ControllerActionDescriptor)?.ControllerName + (d.ActionDescriptor as ControllerActionDescriptor)?.ActionName
         );
 
-    // To Enable authorization using Swagger (JWT)  
+    // To Enable authorization using Swagger (JWT)
     swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
     {
         Name = "Authorization",
@@ -133,44 +159,41 @@ builder.Services.AddSwaggerGen(swagger =>
                     }
                 });
 });
-builder.Services.AddSignalR(options =>
-{
-    options.EnableDetailedErrors = true;
-});
+
 //--------------------------
 var app = builder.Build();
 
 // Configure the HTTP request pipeline.
 // if (app.Environment.IsDevelopment())
 // {
+app.UseDevExpressControls(); // Required for DevExpress Reporting
 app.UseSwagger();
 //app.UseSwaggerUI();
 app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MTWorkHR.API v1"));
 // }
 
-app.UseCors(x => x
-    .AllowAnyMethod()
-    .AllowAnyHeader()
-    .SetIsOriginAllowed(origin =>
-    true) // allow any origin
-    .AllowCredentials()); // allow credentials
+
+app.UseRouting();  // <-- Add UseRouting() here
+app.UseMiddleware<LoggingMiddleware>();
+
+//app.UseCors(x => x
+//    .WithOrigins("https://api.mtwork.com", "https://mtworkhrclient.azurewebsites.net", "http://localhost:4200", "https://www.mtwork.com") // Allowed origins without trailing slash
+//    .AllowAnyMethod()
+//    .AllowAnyHeader()
+//    .AllowCredentials() // Allows credentials
+//);
+app.UseCors("CORSPolicy");
 
 
-//app.MapPost("broadcast", async (string message, IHubContext<ChatHub, IChatClient> context) =>
-//{
-//    await context.Clients.All.ReceiveMessage(message);
-//    return Results.NoContent();
-//});
 
-//app.UseEndpoints(endpoints =>
-//{
-//    endpoints.MapHub<ChatHub>("/chatHub");
-//});
 app.UseHttpsRedirection();
 app.UseAuthentication();
 app.UseAuthorization();
-app.UseMiddleware<LoggingMiddleware>();
+app.UseEndpoints(endpoints =>
+{
+    endpoints.MapHub<ChatHub>("/chatHub"); // Map your SignalR hub
+});
 app.MapControllers();
-app.MapHub<ChatHub>("/chatHub");
+//app.MapHub<ChatHub>("/chatHub");
 
 app.Run();

+ 292 - 0
MTWorkHR.API/Reports/ContractAllowances.Designer.cs

@@ -0,0 +1,292 @@
+namespace MTWorkHR.Infrastructure.Reports
+{
+    partial class ContractAllowances
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            DevExpress.DataAccess.Sql.SelectQuery selectQuery1 = new DevExpress.DataAccess.Sql.SelectQuery();
+            DevExpress.DataAccess.Sql.Column column1 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression1 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.Table table1 = new DevExpress.DataAccess.Sql.Table();
+            DevExpress.DataAccess.Sql.Column column2 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression2 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.Column column3 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression3 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.Column column4 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression4 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.Column column5 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression5 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.Column column6 = new DevExpress.DataAccess.Sql.Column();
+            DevExpress.DataAccess.Sql.ColumnExpression columnExpression6 = new DevExpress.DataAccess.Sql.ColumnExpression();
+            DevExpress.DataAccess.Sql.QueryParameter queryParameter1 = new DevExpress.DataAccess.Sql.QueryParameter();
+            DevExpress.DataAccess.Sql.QueryParameter queryParameter2 = new DevExpress.DataAccess.Sql.QueryParameter();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ContractAllowances));
+            this.TopMargin = new DevExpress.XtraReports.UI.TopMarginBand();
+            this.xrLine1 = new DevExpress.XtraReports.UI.XRLine();
+            this.xrLabel4 = new DevExpress.XtraReports.UI.XRLabel();
+            this.xrLabel3 = new DevExpress.XtraReports.UI.XRLabel();
+            this.xrLabel2 = new DevExpress.XtraReports.UI.XRLabel();
+            this.xrLabel1 = new DevExpress.XtraReports.UI.XRLabel();
+            this.BottomMargin = new DevExpress.XtraReports.UI.BottomMarginBand();
+            this.Detail = new DevExpress.XtraReports.UI.DetailBand();
+            this.xrTable1 = new DevExpress.XtraReports.UI.XRTable();
+            this.xrTableRow1 = new DevExpress.XtraReports.UI.XRTableRow();
+            this.xrTableCell1 = new DevExpress.XtraReports.UI.XRTableCell();
+            this.xrTableCell2 = new DevExpress.XtraReports.UI.XRTableCell();
+            this.xrTableCell3 = new DevExpress.XtraReports.UI.XRTableCell();
+            this.xrTableCell4 = new DevExpress.XtraReports.UI.XRTableCell();
+            this.sqlDataSource1 = new DevExpress.DataAccess.Sql.SqlDataSource(this.components);
+            this.ContractId = new DevExpress.XtraReports.Parameters.Parameter();
+            ((System.ComponentModel.ISupportInitialize)(this.xrTable1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
+            // 
+            // TopMargin
+            // 
+            this.TopMargin.Borders = DevExpress.XtraPrinting.BorderSide.None;
+            this.TopMargin.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
+            this.xrLine1,
+            this.xrLabel4,
+            this.xrLabel3,
+            this.xrLabel2,
+            this.xrLabel1});
+            this.TopMargin.Name = "TopMargin";
+            this.TopMargin.StylePriority.UseBorders = false;
+            // 
+            // xrLine1
+            // 
+            this.xrLine1.LocationFloat = new DevExpress.Utils.PointFloat(2.098083E-05F, 98F);
+            this.xrLine1.Name = "xrLine1";
+            this.xrLine1.SizeF = new System.Drawing.SizeF(641F, 2F);
+            // 
+            // xrLabel4
+            // 
+            this.xrLabel4.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Bold);
+            this.xrLabel4.LocationFloat = new DevExpress.Utils.PointFloat(545.8333F, 75F);
+            this.xrLabel4.Multiline = true;
+            this.xrLabel4.Name = "xrLabel4";
+            this.xrLabel4.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
+            this.xrLabel4.SizeF = new System.Drawing.SizeF(104.1667F, 23F);
+            this.xrLabel4.StylePriority.UseFont = false;
+            this.xrLabel4.Text = "Payment Type";
+            // 
+            // xrLabel3
+            // 
+            this.xrLabel3.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Bold);
+            this.xrLabel3.LocationFloat = new DevExpress.Utils.PointFloat(377.5F, 75F);
+            this.xrLabel3.Multiline = true;
+            this.xrLabel3.Name = "xrLabel3";
+            this.xrLabel3.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
+            this.xrLabel3.SizeF = new System.Drawing.SizeF(158.3333F, 23F);
+            this.xrLabel3.StylePriority.UseFont = false;
+            this.xrLabel3.Text = "Entitlement Amount";
+            // 
+            // xrLabel2
+            // 
+            this.xrLabel2.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Bold);
+            this.xrLabel2.LocationFloat = new DevExpress.Utils.PointFloat(271.6667F, 75F);
+            this.xrLabel2.Multiline = true;
+            this.xrLabel2.Name = "xrLabel2";
+            this.xrLabel2.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
+            this.xrLabel2.SizeF = new System.Drawing.SizeF(100F, 23F);
+            this.xrLabel2.StylePriority.UseFont = false;
+            this.xrLabel2.Text = "Entitlement %";
+            // 
+            // xrLabel1
+            // 
+            this.xrLabel1.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Bold);
+            this.xrLabel1.LocationFloat = new DevExpress.Utils.PointFloat(0F, 75F);
+            this.xrLabel1.Multiline = true;
+            this.xrLabel1.Name = "xrLabel1";
+            this.xrLabel1.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
+            this.xrLabel1.SizeF = new System.Drawing.SizeF(100F, 23F);
+            this.xrLabel1.StylePriority.UseFont = false;
+            this.xrLabel1.Text = "Allowance";
+            // 
+            // BottomMargin
+            // 
+            this.BottomMargin.HeightF = 6.666667F;
+            this.BottomMargin.Name = "BottomMargin";
+            // 
+            // Detail
+            // 
+            this.Detail.Borders = DevExpress.XtraPrinting.BorderSide.None;
+            this.Detail.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
+            this.xrTable1});
+            this.Detail.HeightF = 33.33333F;
+            this.Detail.Name = "Detail";
+            this.Detail.StylePriority.UseBorders = false;
+            // 
+            // xrTable1
+            // 
+            this.xrTable1.LocationFloat = new DevExpress.Utils.PointFloat(2.098083E-05F, 0F);
+            this.xrTable1.Name = "xrTable1";
+            this.xrTable1.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 96F);
+            this.xrTable1.Rows.AddRange(new DevExpress.XtraReports.UI.XRTableRow[] {
+            this.xrTableRow1});
+            this.xrTable1.SizeF = new System.Drawing.SizeF(650F, 25F);
+            // 
+            // xrTableRow1
+            // 
+            this.xrTableRow1.Cells.AddRange(new DevExpress.XtraReports.UI.XRTableCell[] {
+            this.xrTableCell1,
+            this.xrTableCell2,
+            this.xrTableCell3,
+            this.xrTableCell4});
+            this.xrTableRow1.Name = "xrTableRow1";
+            this.xrTableRow1.Weight = 1D;
+            // 
+            // xrTableCell1
+            // 
+            this.xrTableCell1.ExpressionBindings.AddRange(new DevExpress.XtraReports.UI.ExpressionBinding[] {
+            new DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[AllowanceDesc]")});
+            this.xrTableCell1.Multiline = true;
+            this.xrTableCell1.Name = "xrTableCell1";
+            this.xrTableCell1.Text = "xrTableCell1";
+            this.xrTableCell1.Weight = 2.716666392960696D;
+            // 
+            // xrTableCell2
+            // 
+            this.xrTableCell2.ExpressionBindings.AddRange(new DevExpress.XtraReports.UI.ExpressionBinding[] {
+            new DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[EntitlementPercent]")});
+            this.xrTableCell2.Multiline = true;
+            this.xrTableCell2.Name = "xrTableCell2";
+            this.xrTableCell2.Text = "xrTableCell2";
+            this.xrTableCell2.Weight = 1.0583330503373904D;
+            // 
+            // xrTableCell3
+            // 
+            this.xrTableCell3.ExpressionBindings.AddRange(new DevExpress.XtraReports.UI.ExpressionBinding[] {
+            new DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[EntitlementAmount]")});
+            this.xrTableCell3.Multiline = true;
+            this.xrTableCell3.Name = "xrTableCell3";
+            this.xrTableCell3.Text = "xrTableCell3";
+            this.xrTableCell3.Weight = 1.6833330154999731D;
+            // 
+            // xrTableCell4
+            // 
+            this.xrTableCell4.ExpressionBindings.AddRange(new DevExpress.XtraReports.UI.ExpressionBinding[] {
+            new DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[PaymentType]")});
+            this.xrTableCell4.Multiline = true;
+            this.xrTableCell4.Name = "xrTableCell4";
+            this.xrTableCell4.Text = "xrTableCell4";
+            this.xrTableCell4.Weight = 1.0416671788927943D;
+            // 
+            // sqlDataSource1
+            // 
+            this.sqlDataSource1.ConnectionName = "LocalConnectionString";
+            this.sqlDataSource1.Name = "sqlDataSource1";
+            columnExpression1.ColumnName = "ContractId";
+            table1.MetaSerializable = "<Meta X=\"30\" Y=\"30\" Width=\"125\" Height=\"285\" />";
+            table1.Name = "ContractAllowance";
+            columnExpression1.Table = table1;
+            column1.Expression = columnExpression1;
+            columnExpression2.ColumnName = "AllowanceType";
+            columnExpression2.Table = table1;
+            column2.Expression = columnExpression2;
+            columnExpression3.ColumnName = "AllowanceDesc";
+            columnExpression3.Table = table1;
+            column3.Expression = columnExpression3;
+            columnExpression4.ColumnName = "EntitlementPercent";
+            columnExpression4.Table = table1;
+            column4.Expression = columnExpression4;
+            columnExpression5.ColumnName = "EntitlementAmount";
+            columnExpression5.Table = table1;
+            column5.Expression = columnExpression5;
+            columnExpression6.ColumnName = "PaymentType";
+            columnExpression6.Table = table1;
+            column6.Expression = columnExpression6;
+            selectQuery1.Columns.Add(column1);
+            selectQuery1.Columns.Add(column2);
+            selectQuery1.Columns.Add(column3);
+            selectQuery1.Columns.Add(column4);
+            selectQuery1.Columns.Add(column5);
+            selectQuery1.Columns.Add(column6);
+            selectQuery1.FilterString = "[ContractAllowance.ContractId] = ?ContractId";
+            selectQuery1.GroupFilterString = "";
+            selectQuery1.Name = "Query";
+            queryParameter1.Name = "ContractId";
+            queryParameter1.Type = typeof(global::DevExpress.DataAccess.Expression);
+            queryParameter1.Value = new DevExpress.DataAccess.Expression("?ContractId", typeof(long));
+            queryParameter2.Name = "Parameter1";
+            queryParameter2.Type = typeof(global::DevExpress.DataAccess.Expression);
+            queryParameter2.Value = new DevExpress.DataAccess.Expression("?ContractId", typeof(int));
+            selectQuery1.Parameters.AddRange(new DevExpress.DataAccess.Sql.QueryParameter[] {
+            queryParameter1,
+            queryParameter2});
+            selectQuery1.Tables.Add(table1);
+            this.sqlDataSource1.Queries.AddRange(new DevExpress.DataAccess.Sql.SqlQuery[] {
+            selectQuery1});
+            this.sqlDataSource1.ResultSchemaSerializable = resources.GetString("sqlDataSource1.ResultSchemaSerializable");
+            // 
+            // ContractId
+            // 
+            this.ContractId.Description = "ContractId";
+            this.ContractId.Name = "ContractId";
+            this.ContractId.Type = typeof(int);
+            this.ContractId.ValueInfo = "0";
+            // 
+            // ContractAllowances
+            // 
+            this.Bands.AddRange(new DevExpress.XtraReports.UI.Band[] {
+            this.TopMargin,
+            this.BottomMargin,
+            this.Detail});
+            this.ComponentStorage.AddRange(new System.ComponentModel.IComponent[] {
+            this.sqlDataSource1});
+            this.DataMember = "Query";
+            this.DataSource = this.sqlDataSource1;
+            this.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F);
+            this.Margins = new DevExpress.Drawing.DXMargins(100F, 100F, 100F, 6.666667F);
+            this.Parameters.AddRange(new DevExpress.XtraReports.Parameters.Parameter[] {
+            this.ContractId});
+            this.Version = "24.1";
+            ((System.ComponentModel.ISupportInitialize)(this.xrTable1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
+
+        }
+
+        #endregion
+
+        private DevExpress.XtraReports.UI.TopMarginBand TopMargin;
+        private DevExpress.XtraReports.UI.BottomMarginBand BottomMargin;
+        private DevExpress.XtraReports.UI.DetailBand Detail;
+        private DevExpress.DataAccess.Sql.SqlDataSource sqlDataSource1;
+        private DevExpress.XtraReports.UI.XRLabel xrLabel1;
+        private DevExpress.XtraReports.UI.XRTable xrTable1;
+        private DevExpress.XtraReports.UI.XRTableRow xrTableRow1;
+        private DevExpress.XtraReports.UI.XRTableCell xrTableCell1;
+        private DevExpress.XtraReports.UI.XRTableCell xrTableCell2;
+        private DevExpress.XtraReports.UI.XRTableCell xrTableCell3;
+        private DevExpress.XtraReports.UI.XRTableCell xrTableCell4;
+        private DevExpress.XtraReports.UI.XRLabel xrLabel4;
+        private DevExpress.XtraReports.UI.XRLabel xrLabel3;
+        private DevExpress.XtraReports.UI.XRLabel xrLabel2;
+        private DevExpress.XtraReports.Parameters.Parameter ContractId;
+        private DevExpress.XtraReports.UI.XRLine xrLine1;
+    }
+}

+ 16 - 0
MTWorkHR.API/Reports/ContractAllowances.cs

@@ -0,0 +1,16 @@
+using DevExpress.XtraReports.UI;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+
+namespace MTWorkHR.Infrastructure.Reports
+{
+    public partial class ContractAllowances : DevExpress.XtraReports.UI.XtraReport
+    {
+        public ContractAllowances()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 123 - 0
MTWorkHR.API/Reports/ContractAllowances.resx

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="sqlDataSource1.ResultSchemaSerializable" xml:space="preserve">
+    <value>PERhdGFTZXQgTmFtZT0ic3FsRGF0YVNvdXJjZTEiPjxWaWV3IE5hbWU9IlF1ZXJ5Ij48RmllbGQgTmFtZT0iQ29udHJhY3RJZCIgVHlwZT0iSW50NjQiIC8+PEZpZWxkIE5hbWU9IkFsbG93YW5jZVR5cGUiIFR5cGU9IkludDY0IiAvPjxGaWVsZCBOYW1lPSJBbGxvd2FuY2VEZXNjIiBUeXBlPSJTdHJpbmciIC8+PEZpZWxkIE5hbWU9IkVudGl0bGVtZW50UGVyY2VudCIgVHlwZT0iRGVjaW1hbCIgLz48RmllbGQgTmFtZT0iRW50aXRsZW1lbnRBbW91bnQiIFR5cGU9IkRlY2ltYWwiIC8+PEZpZWxkIE5hbWU9IlBheW1lbnRUeXBlIiBUeXBlPSJJbnQzMiIgLz48L1ZpZXc+PC9EYXRhU2V0Pg==</value>
+  </data>
+</root>

Різницю між файлами не показано, бо вона завелика
+ 1763 - 0
MTWorkHR.API/Reports/ContractReport.Designer.cs


+ 16 - 0
MTWorkHR.API/Reports/ContractReport.cs

@@ -0,0 +1,16 @@
+using DevExpress.XtraReports.UI;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+
+namespace MTWorkHR.Infrastructure.Reports
+{
+    public partial class ContractReport : DevExpress.XtraReports.UI.XtraReport
+    {
+        public ContractReport()
+        {
+            InitializeComponent();
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 123 - 0
MTWorkHR.API/Reports/ContractReport.resx


+ 85 - 0
MTWorkHR.API/Reports/ReportStorageWebExtension.cs

@@ -0,0 +1,85 @@
+using DevExpress.XtraReports.UI;
+using Microsoft.AspNetCore.Hosting;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace MTWorkHR.Infrastructure.Reports
+{
+    public class CustomReportStorageWebExtension : DevExpress.XtraReports.Web.Extensions.ReportStorageWebExtension
+    {
+      //  private readonly GlobalInfo globalInfo;
+    //    private readonly AppSettingsConfiguration settings;
+        public CustomReportStorageWebExtension()
+        {
+        }
+        public override byte[] GetData(string url)
+        {
+            try
+            {
+                // Parse the string with the report name and parameter values.
+                string[] parts = url.Split('?');
+                string reportName = parts[0];
+                string parametersQueryString = parts.Length > 1 ? parts[1] : String.Empty;
+
+                // Create a report instance.
+
+                XtraReport report= getReport(reportName);
+              
+                if (report != null)
+                {
+                    // Apply the parameter values to the report.
+                    var parameters = HttpUtility.ParseQueryString(parametersQueryString);
+
+                    foreach (string parameterName in parameters.AllKeys)
+                    {
+                        if (parameters.Get(parameterName) != "null"&& parameters.Get(parameterName) != null)
+                        {
+                                report.Parameters[parameterName].Value = Convert.ChangeType(
+                            parameters.Get(parameterName), report.Parameters[parameterName].Type);
+                        }
+                    }
+
+                    // Disable the Visible property for all report parameters
+                    // to hide the Parameters Panel in the viewer.
+                    foreach (var parameter in report.Parameters)
+                    {
+                        parameter.Visible = false;
+                    }
+
+                    // If you do not hide the panel, disable the report's RequestParameters property.
+                    // report.RequestParameters = false;
+
+                    using (MemoryStream ms = new MemoryStream())
+                    {
+                        report.SaveLayoutToXml(ms);
+                        return ms.ToArray();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new DevExpress.XtraReports.Web.ClientControls.FaultException(
+                    "Could not get report data.", ex);
+            }
+            throw new DevExpress.XtraReports.Web.ClientControls.FaultException(
+                string.Format("Could not find report '{0}'.", url));
+        }
+        private XtraReport getReport(string reportName)
+        {
+            switch (reportName)
+            {
+                case "ContractReport":
+                    return new ContractReport();
+                case "ContractAllowance":
+                    return new ContractAllowances();
+                default: return null;
+            }
+        }
+    
+    }
+}

+ 1 - 1
MTWorkHR.API/appsettings.json

@@ -7,7 +7,7 @@
   },
   "ConnectionStrings": {
     "MTWorkHRConnectionString": "Server=tcp:mtworksqlserver.database.windows.net,1433;Initial Catalog=MTWorkHRDB;Persist Security Info=False;User ID=MTWorkHR;Password=MTWork@12345;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
-    //"LocalConnectionString": "Server=.;Database=MTWorkHRDB;User=sa;Password=p@ssw0rd;MultipleActiveResultSets=true;Integrated Security=True;Encrypt=False",
+    "LocalConnectionString": "Server=.;Database=MTWorkHRDB;User=sa;Password=p@ssw0rd;MultipleActiveResultSets=true;Integrated Security=True;Encrypt=False",
     "BlobConnectionString": "DefaultEndpointsProtocol=https;AccountName=mtworkhrstorage;AccountKey=8EfjO3+4jHmf6QSnW5PCFDWry8oXSAM4pGtlIviImd5yCo6lxWDUpnzfT6ppHJqhKztuGU9IL4Ai+ASt16oHZA==;EndpointSuffix=core.windows.net"
     // "HRIdentityDB": "Server=localhost;Database=HRIdentityDB;User=sa;Password=p@ssw0rd;MultipleActiveResultSets=true"
     //Data Source=.;Initial Catalog=CBQ_VIVR;Integrated Security=True;Encrypt=False

+ 104 - 36
MTWorkHR.Application/Chat/ChatHub.cs

@@ -1,6 +1,7 @@
 using Microsoft.AspNetCore.Identity;
 using Microsoft.AspNetCore.SignalR;
 using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
 using MimeKit;
 using MTWorkHR.Application.Filters;
 using MTWorkHR.Application.Identity;
@@ -27,13 +28,14 @@ namespace MTWorkHR.API.Chat
         private readonly GlobalInfo _globalInfo;
         //private readonly UserService _userService; 
         private readonly ApplicationUserManager _userManager;
-
-        public ChatHub(IUnitOfWork unitOfWork, GlobalInfo globalInfo, ApplicationUserManager userManager /*, UserService userService*/) 
+        private readonly ILogger<ChatHub> _logger;
+        public ChatHub(IUnitOfWork unitOfWork, GlobalInfo globalInfo, ApplicationUserManager userManager /*, UserService userService*/, ILogger<ChatHub> logger) 
         {
             _unitOfWork = unitOfWork;
             _globalInfo = globalInfo;
             //  _userService = userService;
             _userManager = userManager;
+            _logger = logger;
         }
 
         public async Task GetUsers()
@@ -43,27 +45,71 @@ namespace MTWorkHR.API.Chat
             await Clients.Caller.SendAsync("UpdateUserList", myCompanyUsers);
         }
 
-      
-      
+
+
         public async Task<List<ChatUserDto>> GetAllCompanyEmployees()
         {
-            var employees = await _userManager.GetUsersInRoleAsync("Employee");
-            var CompanyId = GetAuthenticatedCompanyId();
-            var res = employees.Where(e => e.CompanyId == CompanyId).ToList();
+            var response = new List<ChatUserDto>();
 
-            var response = MapperObject.Mapper.Map<List<ChatUserDto>>(res);
+            try
+            {
+                // Get all employees with "Employee" and "Business" roles
+                var employeesInRole = await _userManager.GetUsersInRoleAsync("Employee");
+                var businessInRole = await _userManager.GetUsersInRoleAsync("Business");
+
+                // Combine employee lists if needed and apply unique filtering based on IDs
+                var allEmployees = employeesInRole.Union(businessInRole).DistinctBy(e => e.Id).ToList();
+
+                var CompanyId = GetAuthenticatedCompanyId();
+                var userId = Context.User.Identities.FirstOrDefault()?.FindFirst("uid")?.Value;
+
+                // Get all message sender and receiver IDs excluding the current user
+                var allMessages = await GetAllMessages();
+                var companyUserIds = allMessages
+                    .SelectMany(m => new[] { m.SenderId, m.ReceiverId })
+                    .Where(id => id != userId)
+                    .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();
+
+                // Get online users and map to a dictionary for faster lookups
+                var allConnections = await _unitOfWork.HubConnection.GetAllAsync();
+                var onlineUsers = allConnections.Item1.ToDictionary(c => c.UserId, c => c.SignalrId);
 
-            var allConnections = await _unitOfWork.HubConnection.GetAllAsync();
-            var onlineUsers = allConnections.Item1
-                .Select(c => new { c.UserId, c.SignalrId }).ToList();
-            foreach(var emp in res)
+                // Retrieve last message data for each employee
+                foreach (var emp in employeesToChat)
+                {
+                    var onlineSignalrId = onlineUsers.TryGetValue(emp.Id, out var signalrId) ? signalrId : null;
+                    var isOnline = onlineSignalrId != null;
+                    var profileImg = ""; // Assuming this is coming from another source if needed
+
+                    // Retrieve last message and unseen count for the employee
+                    var lastMessage = await GetLastMessage(emp.Id);
+
+                    // Create ChatUserDto and add to response
+                    response.Add(new ChatUserDto(
+                        emp.Id,
+                        $"{emp.FirstName} {emp.LastName}",
+                        onlineSignalrId,
+                        emp.Email,
+                        isOnline,
+                        profileImg,
+                        lastMessage.Item2,
+                        lastMessage.Item1?.Content,
+                        lastMessage.Item1?.CreateDate,
+                        emp.FirstName,
+                        emp.LastName
+                    ));
+                }
+            }
+            catch (Exception e)
             {
-                var online = onlineUsers.FirstOrDefault(u=>  u.UserId == emp.Id);
-                var profileImg = "";
-                var lastMsg = "";
-                var lastMsgDate = "";
-                var unseenCount = 0;
-                var chatUser = new ChatUserDto(emp.Id, emp.FirstName + " " + emp.LastName, online?.SignalrId, emp.Email, online != null ? true : false, profileImg, unseenCount,lastMsg,lastMsgDate);
+                _logger.LogError(e, e.Message);
             }
 
             return response;
@@ -82,12 +128,22 @@ namespace MTWorkHR.API.Chat
             return CompanyIdLong;
         }
 
-      
 
-      
+        // Get previous messages between two users
+        public async Task GetPreviousMessages(string contactId)
+        {
+            var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+            var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(userId, contactId);
+            // Ensure the query is fully materialized before passing it to SignalR
+            var messagesList = await allmessages.Item1.ToListAsync();
+
+            await Clients.Caller.SendAsync("PreviousMessages", messagesList);
+        }
+
+
         // Send a message from one user to another
-       
-        public async Task sendMsg(string receiverUserId, string msg)
+
+        public async Task SendMessage(string receiverUserId, string msg)
         {
             try
             {
@@ -100,7 +156,7 @@ namespace MTWorkHR.API.Chat
                 ChatMessage messag = new ChatMessage { 
                     Content = msg, 
                     ReceiverId = receiverUserId, 
-                    ReceiverName = receiverUser.UserName ?? "", 
+                    ReceiverName = receiverUser?.UserName ?? "", 
                     SenderId = userId, 
                     SenderName = userName, 
                     IsSeen = false 
@@ -110,33 +166,40 @@ namespace MTWorkHR.API.Chat
                 await Clients.Client(receiverconnIdDB).SendAsync("ReceiveMessage", messag);
                 await Clients.Caller.SendAsync("ReceiveMessage", messag);
             }
-            catch (Exception e) { }
+            catch (Exception e) { _logger.LogError(e, e.Message); }
         }
 
-        // Get previous messages between two users
-        public async Task GetPreviousMessages(string contactId)
+
+        public async Task<IList<ChatMessage>> GetAllMessages()
         {
             var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
-            var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(userId, contactId);
+            var allmessages = await _unitOfWork.ChatMessage.GetAllUserMessagesAsync(userId);
             // Ensure the query is fully materialized before passing it to SignalR
             var messagesList = await allmessages.Item1.ToListAsync();
-
-            await Clients.Caller.SendAsync("PreviousMessages", messagesList);
+            return messagesList;
         }
 
-
-        public async Task<ChatMessage> GetLastMessage()
+        public async Task<Tuple<ChatMessage, int>> GetLastMessage(string contactId)
         {
             var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
-            var allmessages = await _unitOfWork.ChatMessage.GetAllUserMessagesAsync(userId);
+            var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(userId, contactId);
             // Ensure the query is fully materialized before passing it to SignalR
-            var lastOne = allmessages.Item1.LastOrDefault();
-
-            return lastOne?? new ChatMessage();
+            var lastOne = allmessages.Item1.OrderByDescending(m=> m.Id).FirstOrDefault();
+            var unseen = allmessages.Item1.Count(m=> m.IsSeen == false);
+            return new Tuple<ChatMessage, int>( lastOne?? new ChatMessage(), unseen);
         }
         //----------------------------------------------------------------------
         //----------------------------------------------------------------------
         //----------------------------------------------------------------------
+        public async Task<bool> MarkAsSeen(long messageId)
+        {
+            //var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+            var message = await _unitOfWork.ChatMessage.GetByIdAsync(messageId);
+            message.IsSeen = true;
+            await _unitOfWork.CompleteAsync();
+
+            return true;
+        }
 
         //Simple Test Method
         public async Task SendMessageAll(string user, string message)
@@ -165,6 +228,11 @@ namespace MTWorkHR.API.Chat
 
                 if (userId != null) //if credentials are correct
                 {
+                    //--------------delete
+                    var connections = await _unitOfWork.HubConnection.GetAllByUserAsync(userId);
+                    await _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList());
+                    await _unitOfWork.CompleteAsync();
+                    //
                     HubConnection currUser = new HubConnection
                     {
                         UserId = userId,
@@ -186,7 +254,7 @@ namespace MTWorkHR.API.Chat
                     await Clients.Caller.SendAsync("authMeResponseFail");
                 }
             }
-            catch (Exception ex) { }
+            catch (Exception e) { _logger.LogError(e, e.Message); }
 
             await base.OnConnectedAsync();
         }

+ 2 - 2
MTWorkHR.Application/Dtos/Contract/ContractAllowanceDto.cs

@@ -17,8 +17,8 @@ namespace MTWorkHR.Application.Models
         [Required]
         public long AllowanceType { get; set; }
         public string? AllowanceDesc { get; set; }
-        public long EntitlementPercent { get; set; }// اختيار (مبلغ – يكتب المبلغ)    أو  (نسبة من الراتب – ويظهر المبلغ توماتك)      
-        public long EntitlementAmount { get; set; }
+        public decimal EntitlementPercent { get; set; }// اختيار (مبلغ – يكتب المبلغ)    أو  (نسبة من الراتب – ويظهر المبلغ توماتك)      
+        public decimal EntitlementAmount { get; set; }
         public PaymentType PaymentType { get; set; }
 
     }

+ 4 - 2
MTWorkHR.Application/Dtos/Contract/ContractDto.cs

@@ -14,6 +14,7 @@ namespace MTWorkHR.Application.Models
     public class ContractDto : EntityDto
     {
         public ContractTypeEnum ContractTypeId { get; set; }
+        public ContractStatusEnum ContractStatusId { get; set; } 
 
         public long CompanyId { get; set; }
         public string CompanyRepresentativeId { get; set; }
@@ -26,14 +27,14 @@ namespace MTWorkHR.Application.Models
         public int WorkCountryId { get; set; }
         public int WorkStateId { get; set; }
         //-------------------Scope of work-----------
-        public int? JobTitleId { get; set; }
+        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 int ContractDurationId { get; set; } //:  اختيار: شهري – ربعي – نصف سنوي – 3 ارباع – سنوي
+        public ContractDurationEnum ContractDurationId { get; set; } //:  اختيار: شهري – ربعي – نصف سنوي – 3 ارباع – سنوي
         public TypeOfWork TypeOfWork { get; set; } //: :   اختيار: عقد بدوام كامل -  عقد دوام جزئي   
         public int VacationDays { get; set; } //اختيار: بدون – سنويا (رقم)
         public int TrialPeriod { get; set; } // تجربة (ادخال: تلقائياً كل ربع سنوي أسبوع تلقائياً) آخر: تعديل
@@ -45,6 +46,7 @@ namespace MTWorkHR.Application.Models
         //------Working time---------------
         public string WorkingDays { get; set; } //:   اختيار متعدد الأيام سبت أحد اثنين..... (بحيث الأيام الأخرى تكون إجازة) 1,2,3,4,5
         public WorkingHours WorkingHours { get; set; } //	يومي/ اسبوعي  
+        public int WorkingHoursNum { get; set; } // عدد الساعات
         public DateTime? StartDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
         public DateTime? EndDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
 

+ 17 - 0
MTWorkHR.Application/Dtos/Contract/ContractPagingInputDto.cs

@@ -0,0 +1,17 @@
+using MTWorkHR.Core.IDto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Application.Models
+{
+    public class ContractPagingInputDto : PagingInputDto, IContractPagingInputDto
+    {
+        public long? ContractStatusId { get; set; }
+        public long? ContractTypeId { get; set; }
+
+
+    }
+}

+ 15 - 0
MTWorkHR.Application/Dtos/Contract/ContractStatusDto.cs

@@ -0,0 +1,15 @@
+using Microsoft.AspNetCore.Http;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.Entities.Base;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MTWorkHR.Application.Models
+{
+    public class ContractStatusDto
+    {
+        public long ContractId { get; set; }
+        public int StatusId { get; set; }
+
+    }
+}

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

@@ -24,6 +24,8 @@ namespace MTWorkHR.Application.Models
         public string Email { get; set; }
 
         public string PassportNumber { get; set; }
+        public DateTime? PassportExpiryDate { get; set; }
+
         public string? FavoriteName { get; set; }
 
         public string PhoneNumber { get; set; }
@@ -40,6 +42,7 @@ namespace MTWorkHR.Application.Models
         public int? JobTitleId { get; set; }
         public int? IndustryId { get; set; }
         public int? CountryId { get; set; }
+        public int? NationalityId { get; set; }
         public string? QualificationName { get; set; }
         public string? UniversityName { get; set; }
         public string? JobTitleName { get; set; }

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

@@ -19,6 +19,8 @@ namespace MTWorkHR.Application.Models
         public string Email { get; set; }
 
         public string PassportNumber { get; set; }
+        public DateTime? PassportExpiryDate { get; set; }
+
         public string? FavoriteName { get; set; }
 
         public string PhoneNumber { get; set; }
@@ -35,6 +37,7 @@ namespace MTWorkHR.Application.Models
         public int? JobTitleId { get; set; }
         public int? IndustryId { get; set; }
         public int? CountryId { get; set; }
+        public int? NationalityId { get; set; }
         public string? QualificationName { get; set; }
         public string? UniversityName { get; set; }
         public string? JobTitleName { get; set; }

+ 22 - 0
MTWorkHR.Application/Dtos/Lookup/NationalityDto.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Countries.NET;
+using MTWorkHR.Application.Models;
+using MTWorkHR.Core.Entities.Base;
+using MTWorkHR.Core.Global;
+
+namespace MTWorkHR.Application.Models
+{
+    public class NationalityDto :EntityDto
+    {
+        public string NameAr { get; set; }
+        public string NameEn { get; set; }
+        public long? CountryId { get; set; }
+        public string? CountryCode { get; set; }
+
+    }
+}

+ 21 - 16
MTWorkHR.Application/Dtos/User/ChatUserDto.cs

@@ -1,4 +1,5 @@
-using System;
+using Newtonsoft.Json.Serialization;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -8,30 +9,34 @@ namespace MTWorkHR.Application.Models
 {
     public class ChatUserDto
     {
-        public string UserId { get; set; }
-        public string UserName { get; set; }
-        public string ConnectionId { get; set; } //signalrId
-        public string FirstName { get; set; }
-        public string LastName { get; set; }
-        public string FavoriteName { get; set; }
-        public string PhoneNumber { get; set; }
-        public string Email { get; set; }
-        public bool IsOnline { get; set; }
+        public string? UserId { get; set; }
+        public string? UserName { get; set; }
+        public string? ConnectionId { get; set; } //signalrId
+        public string? FirstName { get; set; }
+        public string? LastName { get; set; }
+        public string? FavoriteName { get; set; }
+        public string? PhoneNumber { get; set; }
+        public string? Email { get; set; }
+        public bool? IsOnline { get; set; }
         public string? ProfileImage { get; set; }
         public string? LastMessage { get; set; }
-        public string? LastMessageDate { get; set; }
+        public DateTime? LastMessageDate { get; set; }
         public int? UnseenCount { get; set; }
-        public ChatUserDto(string someId, string someName, string someConnId)
+        public ChatUserDto() { }
+        public ChatUserDto(string userId, string userName, string ConnId)
         {
-            UserId = someId;
-            UserName = someName;
-            ConnectionId = someConnId;
+            UserId = userId;
+            UserName = userName;
+            ConnectionId = ConnId;
         }
 
-        public ChatUserDto(string userId, string userName, string ConnId, string email, bool isOnline, string profileImg, int? unseenCount,string lastMessage, string lastMessageDate)
+        public ChatUserDto(string userId, string userName, string ConnId, string email, bool isOnline, string profileImg, int? unseenCount,string lastMessage, DateTime? lastMessageDate,
+            string firstName, string lastName)
         {
             UserId = userId;
             UserName = userName;
+            FirstName = firstName;
+            LastName = lastName;
             ConnectionId = ConnId;
             Email = email;
             IsOnline = isOnline;

+ 5 - 1
MTWorkHR.Application/Dtos/User/CompanyDto.cs

@@ -15,8 +15,12 @@ namespace MTWorkHR.Application.Models
 
         public string CRNumber { get; set; } //Commercial Registration
         public string? UserId { get; set; }
+        public string? PhoneNumber { get; set; }
+        public string? Address { get; set; }
+        public string? Email { get; set; }
+        public long? CountryId { get; set; }
+        public long? CityId { get; set; }
         public UserTypeEnum? UserType { get; set; }
-
         public CompanyUserDto? CompanyUser { get; set; }
         public IFormFile? ProfileImage { get; set; }
         public IFormFile? CommercialRegAttach { get; set; }

+ 3 - 0
MTWorkHR.Application/Mapper/MappingProfile.cs

@@ -53,6 +53,9 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<UserDto, UserUpdateDto>().ReverseMap();
             CreateMap<UserBasicInfoDto, ApplicationUser>().ReverseMap();
             CreateMap<UserBasicInfoDto, UserDto>().ReverseMap();
+
+            CreateMap<ApplicationUser, ChatUserDto>()
+            .ForMember(s => s.UserId, o => o.MapFrom(s => s.Id )).ReverseMap();
             
             CreateMap<AttachmentDto, UserAttachment>().ReverseMap();
             CreateMap<UserAddress, UserAddressDto>()

+ 6 - 6
MTWorkHR.Application/Middlewares/LoggingMiddleware.cs

@@ -79,9 +79,9 @@ namespace MTWorkHR.Application.Middlewares
                 dynamic service = Activator.CreateInstance(logServiceWithGenericType, new object[] { unitOfWork });
 
                 var msg = error is AppException ? ((AppException)error).ErrorMessage : error.Message;
-                var errorNo = error is AppException ? ((AppException)error).ErrorNumber : "0";
-                int errorNum = 0;
-                int.TryParse(errorNo, out errorNum); 
+                var errorNum = error is AppException ? ((AppException)error).ErrorNumber : 0;
+               // int errorNum = 0;
+               // int.TryParse(errorNo, out errorNum); 
                 dynamic logEnitity = Activator.CreateInstance(entityType, new object[] {
                     controllerName+"/"+actionName, QueryString, bodyStr, DateTime.Now, "",GetLocalIPAddress(), GetServerIp(context), GetUserExternalIp(context), "", "", msg, error?.InnerException?.Message });
 
@@ -100,8 +100,8 @@ namespace MTWorkHR.Application.Middlewares
                             await context.Response.WriteAsJsonAsync(
                              new BadRequestResult
                              {
-                                 ErrorMsg = "*_*" + ((AppException)error).ErrorMessage + "*_*",
-                                 ErrorNo = errorNum
+                                 ErrorMsg = "" + ((AppException)error).ErrorMessage + "",
+                                 ErrorNo = (int)errorNum
                              });
                             return;
                         }
@@ -110,7 +110,7 @@ namespace MTWorkHR.Application.Middlewares
                             context.Response.Clear();
                             context.Response.ContentType = "text/plain";
                             context.Response.StatusCode = StatusCodes.Status500InternalServerError;
-                            await context.Response.WriteAsync("*_*" + "Internal Server Error" + "*_*");
+                            await context.Response.WriteAsync( "Internal Server Error" );
                             return;
 
                         }

+ 27 - 2
MTWorkHR.Application/Services/Contract/ContractService.cs

@@ -7,6 +7,8 @@ using MTWorkHR.Core.UnitOfWork;
 using MTWorkHR.Application.Services.Interfaces;
 using MTWorkHR.Core.Entities;
 using System.Linq.Dynamic.Core;
+using Microsoft.AspNetCore.Identity;
+using MTWorkHR.Infrastructure.Entities;
 
 namespace MTWorkHR.Application.Services
 {
@@ -62,7 +64,7 @@ namespace MTWorkHR.Application.Services
         //    var response = Mapper.MapperObject.Mapper.Map<ContractDto>(entity);
         //    return response;
         //}
-        public override async Task<PagingResultDto<ContractDto>> GetAll(PagingInputDto PagingInputDto)
+        public async Task<PagingResultDto<ContractDto>> GetAll(ContractPagingInputDto PagingInputDto)
         {
             var res = await _unitOfWork.Contract.GetAllWithChildrenAsync();
             var query = res.Item1;
@@ -78,6 +80,15 @@ namespace MTWorkHR.Application.Services
                 query = query.Where(u => u.JobDescription.Contains(filter));
             }
 
+            if (PagingInputDto.ContractStatusId != null)
+            {
+                query = query.Where(u => (int)u.ContractStatusId == PagingInputDto.ContractStatusId);
+            }
+            if (PagingInputDto.ContractTypeId != null)
+            {
+                query = query.Where(u => (int)u.ContractTypeId == PagingInputDto.ContractTypeId);
+            }
+
             var order = query.OrderBy(PagingInputDto.OrderByField + " " + PagingInputDto.OrderType);
 
             var page = order.Skip((PagingInputDto.PageNumber * PagingInputDto.PageSize) - PagingInputDto.PageSize).Take(PagingInputDto.PageSize);
@@ -96,7 +107,21 @@ namespace MTWorkHR.Application.Services
             return response;
         }
 
-       
+        public async Task<bool> ChangeStatus(long contractId, int statusId)
+        {
+            var entity = await _unitOfWork.Contract.GetByIdAsync(contractId);
+            if (entity == null)
+                throw new AppException(ExceptionEnum.RecordNotExist);
+            entity.ContractStatusId = statusId;
+            bool result = true;
+            if (statusId == (int)ContractStatusEnum.Approved)
+            {
+                var updatedSuccess = await _userService.Update(entity.UserId, entity.CompanyId);
+                if (!updatedSuccess) { result = false; }
+            }
+            await _unitOfWork.CompleteAsync();
+            return result;
+        }
 
 
 

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

@@ -14,6 +14,7 @@ namespace MTWorkHR.Application.Services.Interfaces
       
         Task<List<CompanyDto>> GetAllCompanies();
         Task<CompanyDto> GetById();
-        
+        Task<CompanyDto> GetById(long companyId);
+
     }
 }

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

@@ -7,5 +7,8 @@ namespace MTWorkHR.Application.Services.Interfaces
 {
     public interface IContractService : IService<Contract, ContractDto, ContractDto>
     {
+        Task<PagingResultDto<ContractDto>> GetAll(ContractPagingInputDto PagingInputDto);
+        Task<bool> ChangeStatus(long contractId, int statusId);
+
     }
 }

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

@@ -12,6 +12,7 @@ namespace MTWorkHR.Application.Identity
     {
         Task<PagingResultDto<UserAllDto>> GetAll(UserPagingInputDto PagingInputDto);
         Task<UserDto> GetById(string userId);
+        Task<UserDto> GetByEmail(string email);
         Task<UserDto> GetById();
         Task<List<UserDto>> GetAllEmployees();
 
@@ -32,6 +33,6 @@ namespace MTWorkHR.Application.Identity
         Task<BlobObject> Download(string filePath);
         Task<UserDto> GetUserWithAttachmentById(string id);
         Task<string> GetProfileImage(string userId);
-
+        Task<bool> Update(string userId, long companyId);
     }
 }

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

@@ -29,9 +29,10 @@ namespace MTWorkHR.Application.Services
         private readonly IUserService _userService;
         private readonly IFileService _fileService;
         private readonly ApplicationUserManager _userManager;
+        private readonly RoleManager<ApplicationRole> _roleManager;
 
 
-        public CompanyService(ApplicationUserManager userManager, IUnitOfWork unitOfWork, GlobalInfo globalInfo, AppSettingsConfiguration configuration, IUserService userService, IFileService fileService) : base(unitOfWork)
+        public CompanyService(ApplicationUserManager userManager, IUnitOfWork unitOfWork, GlobalInfo globalInfo, AppSettingsConfiguration configuration, IUserService userService, IFileService fileService, RoleManager<ApplicationRole> roleManager) : base(unitOfWork)
         {
             _unitOfWork = unitOfWork;
             _configuration = configuration;
@@ -39,6 +40,7 @@ namespace MTWorkHR.Application.Services
             _userService = userService;
             _fileService = fileService;
             _userManager = userManager;
+            _roleManager = roleManager;
         }
 
      
@@ -89,7 +91,7 @@ namespace MTWorkHR.Application.Services
             {
                 throw new AppException(ExceptionEnum.MapperIssue);
             }
-
+           
             var company = await _unitOfWork.Company.AddAsync(entity);
 
             UserCreated.CompanyId = company.Id;
@@ -101,7 +103,11 @@ namespace MTWorkHR.Application.Services
         public async Task<ApplicationUser> CreateCompanyUser(CompanyDto input)
         {
             var companyUser = MapperObject.Mapper.Map<UserDto>(input.CompanyUser);
-
+            input.Email = string.IsNullOrEmpty( input.Email)? input.CompanyUser?.Email : input.Email;
+            input.PhoneNumber = string.IsNullOrEmpty(input.PhoneNumber) ? input.CompanyUser?.PhoneNumber: input.PhoneNumber;
+            input.Address = string.IsNullOrEmpty(input.Address) ? input.CompanyUser?.UserAddress?.AddressDesc: input.Address;
+            input.CountryId = input.CountryId!=null && input.CountryId > 0 ?  input.CountryId : input.CompanyUser?.UserAddress?.CountryId;
+            input.CityId = input.CityId != null && input.CityId > 0 ?  input.CityId : input.CompanyUser?.UserAddress?.CityId;
             //UserDto companyUser = new UserDto
             //{
             //    UserType = UserTypeEnum.Business,
@@ -146,6 +152,11 @@ namespace MTWorkHR.Application.Services
             if (user.UserType == 0)
             {
                 user.UserType = (int)UserTypeEnum.Business;
+                var employeeRole = await _roleManager.FindByNameAsync("Business");
+                if (employeeRole != null)
+                {
+                    await _userManager.AddToRoleAsync(user, "Business");
+                }
             }
             var result = await _userManager.CreateAsync(user, companyUser.Password);
             if (!result.Succeeded)

+ 48 - 4
MTWorkHR.Application/Services/User/UserService.cs

@@ -58,6 +58,14 @@ namespace MTWorkHR.Application.Services
         {
             return await GetById(_globalInfo.UserId);
         }
+        public async Task<UserDto> GetByEmail(string email)
+        {
+            var user = _userManager.Users.FirstOrDefault(x => x.Email == email);
+            if(user == null)
+                throw new AppException(ExceptionEnum.UserNotExist);
+
+            return await GetById(user.Id);
+        }
         public async Task<UserDto> GetById(string id)
         {
             var entity = await _userManager.Users
@@ -359,11 +367,23 @@ namespace MTWorkHR.Application.Services
             //saving userRoles
             if(input.UserRoles == null || input.UserRoles.Count == 0)
             {
-                var employeeRole = await _roleManager.FindByNameAsync("Employee");
-                if (employeeRole != null)
+                if(user.UserType == (int)UserTypeEnum.Employee)
+                {
+                    var employeeRole = await _roleManager.FindByNameAsync("Employee");
+                    if (employeeRole != null)
+                    {
+                        await _userManager.AddToRoleAsync(user, "Employee");
+                    }
+                }
+                else if (user.UserType == (int)UserTypeEnum.Contractor)
                 {
-                    await _userManager.AddToRoleAsync(user, "Employee");
+                    var employeeRole = await _roleManager.FindByNameAsync("Contractor");
+                    if (employeeRole != null)
+                    {
+                        await _userManager.AddToRoleAsync(user, "Contractor");
+                    }
                 }
+
             }
             else
             {
@@ -545,8 +565,32 @@ namespace MTWorkHR.Application.Services
             var user = MapperObject.Mapper.Map<UserUpdateDto>(userResponse);
             return user;
         }
-        
 
+        public async Task<bool> Update(string userId, long companyId)
+        {
+            try
+            {
+                var entity = _userManager.Users.FirstOrDefault(x => x.Id == userId);
+
+                if (entity == null)
+                    throw new AppException(ExceptionEnum.UserNotExist);
+
+
+                entity.CompanyId = companyId;
+                entity.UpdateDate = DateTime.Now;
+
+                //saving user
+                var result = await _userManager.UpdateAsync(entity);
+                if (!result.Succeeded)
+                    throw new AppException(ExceptionEnum.RecordUpdateFailed);
+                await _unitOfWork.CompleteAsync();
+                return true;
+            }
+            catch (Exception e)
+            {
+                throw e;
+            }
+        }
         public async Task<bool> IsExpiredToken(ConfirmEmailDto input)
         {
             var user = await _userManager.Users.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.Id == input.UserId);

+ 8 - 7
MTWorkHR.Core/Entities/Contract/Contract.cs

@@ -12,8 +12,8 @@ namespace MTWorkHR.Core.Entities
 {
     public class Contract : FullAuditEntity, IHaveCompany
     {
-        public ContractTypeEnum ContractTypeId { get; set; }
-        public ContractStatusEnum ContractStatusId { get; set; }
+        public int ContractTypeId { get; set; }
+        public int ContractStatusId { get; set; }
 
         public long CompanyId { get; set; }
         public string CompanyRepresentativeId { get; set; }
@@ -28,7 +28,7 @@ namespace MTWorkHR.Core.Entities
         public int ContractorTaxResidencyId { get; set; }
         
         //-------------------Scope of work-----------
-        public int? JobTitleId { get; set; }
+        public string? JobTitleName { get; set; }
         public string? JobDescription{ get; set; }
         [MaxLength(150)]
         public string? JobNumber { get; set; } //ثابت و مأخوذ من المنصة
@@ -39,14 +39,15 @@ namespace MTWorkHR.Core.Entities
         public TypeOfWork TypeOfWork { get; set; } //: :   اختيار: عقد بدوام كامل -  عقد دوام جزئي   
         public int VacationDays { get; set; } //اختيار: بدون – سنويا (رقم)
         public int TrialPeriod { get; set; } // تجربة (ادخال: تلقائياً كل ربع سنوي أسبوع تلقائياً) آخر: تعديل
-        public TerminateContractEnum WhoCanTerminateContractInTrial { get; set; } //اختيار   الجميع – صاحب العمل – الموظف
-        public TerminateContractEnum WhoCanTerminateContract { get; set; }
+        public int WhoCanTerminateContractInTrial { get; set; } //اختيار   الجميع – صاحب العمل – الموظف
+        public int WhoCanTerminateContract { get; set; }
         public int NoticePeriodBeforeTermination { get; set; } //اختيار: بدون – تحديد (ادخال: تلقائياً مدة 10 أيام قبل انتهاء الاستحقاق) آخر: تعديل
 
 
         //------Working time---------------
         public string WorkingDays { get; set; } //:   اختيار متعدد الأيام سبت أحد اثنين..... (بحيث الأيام الأخرى تكون إجازة) 1,2,3,4,5
-        public WorkingHours WorkingHours { get; set; } //	يومي/ اسبوعي  
+        public int WorkingHours { get; set; } //	يومي/ اسبوعي  
+        public int WorkingHoursNum { get; set; } // عدد الساعات
         public DateTime? StartDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
         public DateTime? EndDailyWorkingHours { get; set; } // تحديد ساعات الدوام قائمة الساعات << التوقيت بحسب دولة صاحب العمل
 
@@ -54,7 +55,7 @@ namespace MTWorkHR.Core.Entities
         [MaxLength(50)]
         public string? Currency { get; set; }
         public decimal? Salary{ get; set; }
-        public BillingCycle BillingCycle { get; set; }// 2 fortnightly, 4 Monthly
+        public int BillingCycle { get; set; }// 2 fortnightly, 4 Monthly
 
 
         //---------Allowances----------------------

+ 2 - 2
MTWorkHR.Core/Entities/Contract/ContractAllowance.cs

@@ -19,8 +19,8 @@ namespace MTWorkHR.Core.Entities
         [Required]
         public long AllowanceType { get; set; }
         public string? AllowanceDesc { get; set; }
-        public long EntitlementPercent { get; set; }// اختيار (مبلغ – يكتب المبلغ)    أو  (نسبة من الراتب – ويظهر المبلغ توماتك)      
-        public long EntitlementAmount { get; set; }
+        public decimal EntitlementPercent { get; set; }// اختيار (مبلغ – يكتب المبلغ)    أو  (نسبة من الراتب – ويظهر المبلغ توماتك)      
+        public decimal EntitlementAmount { get; set; }
         public PaymentType PaymentType { get; set; }
 
     }

+ 14 - 0
MTWorkHR.Core/Entities/User/Company.cs

@@ -16,5 +16,19 @@ namespace MTWorkHR.Core.Entities
         [Filter]
         public string CRNumber { get; set; }
         public int TaxNumber { get; set; }
+        public string PhoneNumber { get; set; }
+        public string Address { get; set; }
+        public string Email { get; set; }
+
+        public long? CountryId { get; set; }
+        [ForeignKey("CountryId")]
+
+        public CountryLookup? Country { get; set; }
+
+        public long? CityId { get; set; }
+        [ForeignKey("CityId")]
+
+        public City? City { get; set; }
+
     }
 }

+ 24 - 0
MTWorkHR.Core/Entities/User/Nationality.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MTWorkHR.Core.Entities.Base;
+
+namespace MTWorkHR.Core.Entities
+{
+    public class Nationality : Entity
+    {
+        [Required]
+        [MaxLength(250)]
+        [Filter]
+        public string NameAr { get; set; }
+        [Required]
+        [MaxLength(250)]
+        [Filter]
+        public string NameEn { get; set; }
+        public string? CountryCode { get; set; }
+        public string? CountryId { get; set; }
+    }
+}

+ 60 - 13
MTWorkHR.Core/Global/AppException.cs

@@ -5,27 +5,74 @@ namespace MTWorkHR.Core.Global
 {
     public class AppException : Exception
     {
-        public readonly string ErrorNumber;
-        public readonly ExceptionEnum errorNumber;
-        public string ErrorMessage = "";
-        public AppException(string errorMessage) : base(errorMessage) { 
+        /// <summary>
+        /// Gets the error number associated with this exception.
+        /// </summary>
+        public readonly ExceptionEnum ErrorNumber;
+
+        /// <summary>
+        /// Gets the formatted error message.
+        /// </summary>
+        public string ErrorMessage { get; private set; } = string.Empty;
+        public AppException(string errorMessage) : base(errorMessage)
+        {
             ErrorMessage = errorMessage;
         }
-        public AppException(ExceptionEnum errorNumber,params object?[] args) : base()
+        /// <summary>
+        /// Creates a new instance of <see cref="AppException"/> using an error number, language, and optional format arguments.
+        /// </summary>
+        /// <param name="errorNumber">The error number (enum) representing the exception type.</param>
+        /// <param name="language">The language code (e.g., "en" or "ar").</param>
+        /// <param name="args">Optional arguments to format the error message.</param>
+        public AppException(ExceptionEnum errorNumber, params object[] args) : base()
+        {
+            ErrorNumber = errorNumber;
+            ErrorMessage = GetMessage(errorNumber, GlobalInfo.lang?? "en", args);
+
+            // Initialize the base exception with the localized error message.
+            this.SetErrorMessage();
+        }
+
+        /// <summary>
+        /// Sets the exception message for the base exception class.
+        /// </summary>
+        private void SetErrorMessage()
         {
-            this.errorNumber = errorNumber;
+            base.HelpLink = ErrorNumber.ToString(); // Optional: Use error number as a link or reference
+            base.Source = nameof(AppException);    // Optional: Set the exception source
+        }
 
-            AppExceptions.ExceptionMessages.TryGetValue((int)this.errorNumber, out this.ErrorMessage);
-            try
+        /// <summary>
+        /// Retrieves the error message based on the provided error code and language.
+        /// </summary>
+        /// <param name="code">The error number (enum).</param>
+        /// <param name="language">The language code (default: "en").</param>
+        /// <param name="args">Optional parameters for formatting the message.</param>
+        /// <returns>The localized error message.</returns>
+        public static string GetMessage(ExceptionEnum code, string language = "en", params object[] args)
+        {
+            if (AppExceptions.ExceptionMessages.TryGetValue(code, out var translations)
+                && translations.TryGetValue(language, out var message))
             {
-                this.ErrorMessage = string.Format(this.ErrorMessage, args);
+                try
+                {
+                    return string.Format(CultureInfo.InvariantCulture, message, args);
+                }
+                catch (FormatException)
+                {
+                    return language == "ar" ? "فشل في تنسيق الرسالة." : "Message formatting failed.";
+                }
             }
-            catch 
-            {
 
-            }
+            // Default fallback
+            return language == "ar" ? "رسالة الخطأ غير موجودة." : "Error message not found.";
         }
 
-
+        public override string ToString()
+        {
+            return $"{base.ToString()}\nError Number: {ErrorNumber}\nError Message: {ErrorMessage}";
+        }
     }
+
+
 }

+ 136 - 28
MTWorkHR.Core/Global/AppExceptions.cs

@@ -8,35 +8,143 @@ namespace MTWorkHR.Core.Global
 {
     public static class AppExceptions
     {
-        public static IDictionary<int, string> ExceptionMessages = new Dictionary<int, string>()
+        public static IDictionary<ExceptionEnum, Dictionary<string, string>> ExceptionMessages = new Dictionary<ExceptionEnum, Dictionary<string, string>>()
         {
-            {1, "Record Not Existed"},
-            {2, "Model is not valid"},
-            {3, "Not Authorized" },
-            {4, "A property called {0} can't be accessed for type {1}." },
-            {5, "Username or password incorrect!"},
-            {6, "Cannot delete the user" },
-            {7, "Record is already existed!" },
-            {8, "Record creation failed! Please check the record details and try again." },
-            {9, "Record update failed! Please check the record details and try again." },
-            {10, "Record delete failed!" },
-            {11, "Record name already existed" },
-            {12, "Record email already existed" },
-            {13, "Attachment Required" },
-             {14, "Could Not Move Files" },
-            {15, "Mapper Issue" },
-            {16, "InCorrect File Length" },
-			{17, "Wrong or expired OTP" },
-			{18, "Empty Response" },
-			{19, "Error Sending SMS" },
-            {20, "Invalid Captcha" },
-            {21, "Account Locked" },
-            {22, "Invalid File Type" },
-            {23, "No Vacation Balance" },
-            {24, "Email Not Exist" },
-            {25, "Phone Already Exist" },
-            {26, "User Not Exist" },
-            {27, "User already checked in" },
+            {ExceptionEnum.RecordNotExist, new Dictionary<string, string>
+            {
+                { "en", "Record Not Existed" },
+                { "ar", "السجل غير موجود" }
+            }},
+            {ExceptionEnum.ModelNotValid, new Dictionary<string, string>
+            {
+                { "en", "Model is not valid" },
+                { "ar", "النموذج غير صالح" }
+            }},
+            {ExceptionEnum.NotAuthorized, new Dictionary<string, string>
+            {
+                { "en", "Not Authorized" },
+                { "ar", "غير مصرح" }
+            }},
+            {ExceptionEnum.PropertyNotAccess, new Dictionary<string, string>
+            {
+                { "en", "A property called {0} can't be accessed for type {1}." },
+                { "ar", "الخاصية {0} لا يمكن الوصول إليها لنوع {1}." }
+            } },
+            {ExceptionEnum.WrongCredentials, new Dictionary<string, string>
+            {
+                { "en", "Username or password incorrect!" },
+                { "ar", "اسم المستخدم أو كلمة المرور غير صحيحة!" }
+            }},
+            {ExceptionEnum.RecordCannotBeDelete, new Dictionary<string, string>
+            {
+                { "en", "Cannot delete the user" },
+                { "ar", "لا يمكن حذف المستخدم" }
+            }},
+            {ExceptionEnum.RecordAlreadyExist, new Dictionary<string, string>
+            {
+                { "en", "Record is already existed!" },
+                { "ar", "السجل موجود بالفعل!" }
+            } },
+            {ExceptionEnum.RecordCreationFailed, new Dictionary<string, string>
+            {
+                { "en",  "Record creation failed! Please check the record details and try again." },
+                { "ar", "خطأ اثناء الإضافة برجاء مراجعة البيانات" }
+            } },
+            {ExceptionEnum.RecordUpdateFailed, new Dictionary<string, string>
+            {
+                { "en",  "Record update failed! Please check the record details and try again."},
+                { "ar", "خطأ اثناء التعديل برجاء مراجعة البيانات" }
+            } },
+            {ExceptionEnum.RecordDeleteFailed, new Dictionary<string, string>
+            {
+                { "en",  "Record delete failed!"},
+                { "ar", "خطأ اثناء الحذف" }
+            } },
+            {ExceptionEnum.RecordNameAlreadyExist, new Dictionary<string, string>
+            {
+                { "en",  "Record name already existed"},
+                { "ar", "الاسم موجود مسبقا" }
+            } },
+            {ExceptionEnum.RecordEmailAlreadyExist, new Dictionary<string, string>
+            {
+                { "en",   "Record email already existed"},
+                { "ar", "البريد الإلكتروني موجود مسبقا" }
+            } },
+            {ExceptionEnum.AttachmentsRequired, new Dictionary<string, string>
+            {
+                { "en",   "Attachment Required"},
+                { "ar", "المرفقات مطلوبة" }
+            }  },
+             {ExceptionEnum.CouldNotMoveFiles, new Dictionary<string, string>
+            {
+                { "en",   "Could Not Move Files"},
+                { "ar", "لا يمكن نقل الملفات" }
+            }   },
+            {ExceptionEnum.MapperIssue, new Dictionary<string, string>
+            {
+                { "en",  "Mapper Issue"},
+                { "ar", "مشكلة فى المطابقة" }
+            }   },
+            {ExceptionEnum.InCorrectFileLength, new Dictionary<string, string>
+            {
+                { "en",   "InCorrect File Length"},
+                { "ar", "حجم الملف غير مسموح به" }
+            }  },
+            {ExceptionEnum.WrongOTP, new Dictionary<string, string>
+            {
+                { "en",    "Wrong or expired OTP" },
+                { "ar", "كلمة السر المؤقتة غير صحيحة او منتهية الصلاحية" }
+            } },
+            {ExceptionEnum.EmptyResponse, new Dictionary<string, string>
+            {
+                { "en",   "Empty Response" },
+                { "ar", "رد فارغ" }
+            } },
+            {ExceptionEnum.ErrorSendingSMS, new Dictionary<string, string>
+            {
+                { "en",  "Error Sending SMS"},
+                { "ar", "خطأ في ارسال الرسالة النصية" }
+            }   },
+            {ExceptionEnum.InvalidCaptcha, new Dictionary<string, string>
+            {
+                { "en",   "Invalid Captcha" },
+                { "ar", "رمز خاطىء" }
+            } },
+            {ExceptionEnum.AccountLocked, new Dictionary<string, string>
+            {
+                { "en",    "Account Locked"},
+                { "ar", "الحساب موقوف" }
+            }  },
+            {ExceptionEnum.InvalidFileType, new Dictionary<string, string>
+            {
+                { "en",    "Invalid File Type" },
+                { "ar", "نوع الملف خطأ" }
+            } },
+            {ExceptionEnum.NoVacationBalance, new Dictionary<string, string>
+            {
+                { "en",   "No Vacation Balance" },
+                { "ar", "لا يوجد رصيد أجازات" }
+            } },
+            {ExceptionEnum.EmailNotExist, new Dictionary<string, string>
+            {
+                { "en",  "Email Not Exist" },
+                { "ar", "البريد الالكتروني غير موجود" }
+            }  },
+            {ExceptionEnum.RecordPhoneAlreadyExist, new Dictionary<string, string>
+            {
+                { "en",    "Phone Already Exist" },
+                { "ar", "رقم الهاتف موجود مسبقا" }
+            } },
+            {ExceptionEnum.UserNotExist, new Dictionary<string, string>
+            {
+                { "en",    "User Not Exist" },
+                { "ar", "المستخدم غير موجود" }
+            } },
+            {ExceptionEnum.UserAlreadyCheckedIn, new Dictionary<string, string>
+            {
+                { "en",   "User already checked in"},
+                { "ar", "تم تسجيل الحضور اليوم من قبل" }
+            }  },
 
         };
     }

+ 17 - 0
MTWorkHR.Core/Global/Enum/ContractDurationEnum.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Core.Global
+{
+    public enum ContractDurationEnum
+    {
+        Monthly = 1,
+        Quarterly = 2,
+        SemiAnnually = 3,
+        Quarters3 = 4,
+        Annually = 5
+    }
+}

+ 1 - 1
MTWorkHR.Core/Global/GlobalInfo.cs

@@ -12,7 +12,7 @@ namespace MTWorkHR.Core.Global
         public string UserId { get; set; }
         public UserTypeEnum UserType { get; set; }
         public long? CompanyId { get; set; }
-        public static string lang { get; set; }
+        public static string lang { get; set; } = "en";
         public string Token { get; set; }
 
         public void SetValues(string UserName, string UserId, long? CompanyId, string token, string lang)

+ 11 - 0
MTWorkHR.Core/IDto/IContractPagingInputDto.cs

@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace MTWorkHR.Core.IDto
+{
+    public interface IContractPagingInputDto : IPagingInputDto
+    {
+        public long? ContractStatusId { get; set; }
+        public long? ContractTypeId { get; set; }
+
+    }
+}

+ 1 - 0
MTWorkHR.Core/IRepositories/Chat/IHubConnectionRepository.cs

@@ -11,6 +11,7 @@ namespace MTWorkHR.Core.IRepositories
     public interface IHubConnectionRepository : IRepository<HubConnection>
     {
         Task<Tuple<IQueryable<HubConnection>, int>> GetAllAsync(string connectionId);
+        Task<Tuple<IQueryable<HubConnection>, int>> GetAllByUserAsync(string userId);
 
     }
 }

Різницю між файлами не показано, бо вона завелика
+ 1479 - 0
MTWorkHR.Infrastructure/Configurations/NationalityConfiguration.cs


+ 10 - 0
MTWorkHR.Infrastructure/Configurations/RoleConfiguration.cs

@@ -44,6 +44,16 @@ namespace MTWorkHR.Infrastructure.Configurations
                     IsDeleted = false,
 
                 }
+                  ,
+                new ApplicationRole
+                {
+                    Id = "BS5B3B92-2311-48F8-9DEC-F9FAEF1F2110",
+                    Name = "Business",
+                    NormalizedName = "BUSINESS",
+                    IsAdmin = false,
+                    IsDeleted = false,
+
+                }
 
                 );
         }

+ 1 - 0
MTWorkHR.Infrastructure/DBContext/HRDataContext.cs

@@ -53,6 +53,7 @@ namespace MTWorkHR.Infrastructure.DBContext
         public DbSet<City> Cities { get; set; }
         //-----------
         public DbSet<Contract> Contracts { get; set; }
+        public DbSet<Nationality> Nationalities{ get; set; }
 
         //------------------------Logs------------------------
         public DbSet<UserLog> UserLogs { get; set; }

+ 6 - 0
MTWorkHR.Infrastructure/Entities/ApplicationUser.cs

@@ -18,6 +18,7 @@ namespace MTWorkHR.Infrastructure.Entities
         public int UserType { get; set; }
         public string? FavoriteName { get; set; }
         public string PassportNumber { get; set; }
+        public DateTime? PassportExpiryDate { get; set; }
         public long? QualificationId { get; set; }
 
         [ForeignKey("QualificationId")]
@@ -31,6 +32,10 @@ namespace MTWorkHR.Infrastructure.Entities
         public long? IndustryId { get; set; }
         [ForeignKey("IndustryId")]
         public Industry? Industry { get; set; }
+        public long? NationalityId { get; set; }
+        [ForeignKey("NationalityId")]
+
+        public Nationality? Nationality { get; set; }
         public long? CountryId { get; set; }
         [ForeignKey("CountryId")]
 
@@ -59,6 +64,7 @@ namespace MTWorkHR.Infrastructure.Entities
         public string? LinkedInLink { get; set; }
         public string? Position { get; set; }
         public long? CompanyId { get; set; }
+        public string? CompanyRepresentativeTitle { get; set; }
 
         public ICollection<ApplicationRole> UserRoles { get; set; }
         public ICollection<UserAttachment> UserAttachments { get; set; }

+ 1 - 1
MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs

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

+ 11 - 0
MTWorkHR.Infrastructure/MTWorkHR.Infrastructure.csproj

@@ -7,6 +7,12 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <None Remove="Reports\ORMDataModel1.xpo" />
+    <None Remove="Reports\ORMDataModel1.xpo.diagram" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="DevExpress.AspNetCore.Reporting" Version="24.1.6" />
     <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" />
@@ -18,6 +24,7 @@
     </PackageReference>
     <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
     <PackageReference Include="MimeKit" Version="4.3.0" />
+    <PackageReference Include="QuestPDF" Version="2024.10.2" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.8" />
   </ItemGroup>
 
@@ -25,4 +32,8 @@
     <ProjectReference Include="..\MTWorkHR.Core\MTWorkHR.Core.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="Reports\" />
+  </ItemGroup>
+
 </Project>

Різницю між файлами не показано, бо вона завелика
+ 5642 - 0
MTWorkHR.Infrastructure/Migrations/20241029101807_altrUserCompany_addNationality.Designer.cs


+ 375 - 0
MTWorkHR.Infrastructure/Migrations/20241029101807_altrUserCompany_addNationality.cs

@@ -0,0 +1,375 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrUserCompany_addNationality : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<int>(
+                name: "ContractStatusId",
+                table: "Contracts",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AddColumn<int>(
+                name: "ContractorTaxResidencyId",
+                table: "Contracts",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AddColumn<int>(
+                name: "Address",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AddColumn<int>(
+                name: "Email",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AddColumn<int>(
+                name: "PhoneNumber",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AddColumn<string>(
+                name: "CompanyRepresentativeTitle",
+                table: "AspNetUsers",
+                type: "nvarchar(max)",
+                nullable: true);
+
+            migrationBuilder.AddColumn<long>(
+                name: "NationalityId",
+                table: "AspNetUsers",
+                type: "bigint",
+                nullable: true);
+
+            migrationBuilder.AddColumn<DateTime>(
+                name: "PassportExpiryDate",
+                table: "AspNetUsers",
+                type: "datetime2",
+                nullable: true);
+
+            migrationBuilder.CreateTable(
+                name: "Nationalities",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    NameAr = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
+                    NameEn = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
+                    CountryCode = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    CountryId = table.Column<string>(type: "nvarchar(max)", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Nationalities", x => x.Id);
+                });
+
+            migrationBuilder.UpdateData(
+                table: "AspNetUsers",
+                keyColumn: "Id",
+                keyValue: "ADMB3B92-2311-48F8-9DEC-F9FAEF1F21UA",
+                columns: new[] { "CompanyRepresentativeTitle", "NationalityId", "PassportExpiryDate" },
+                values: new object[] { null, null, null });
+
+            migrationBuilder.UpdateData(
+                table: "AspNetUsers",
+                keyColumn: "Id",
+                keyValue: "AL5B3B92-2311-48F8-9DEC-F9FAEF1F21UB",
+                columns: new[] { "CompanyRepresentativeTitle", "NationalityId", "PassportExpiryDate" },
+                values: new object[] { null, null, null });
+
+            migrationBuilder.InsertData(
+                table: "Nationalities",
+                columns: new[] { "Id", "CountryCode", "CountryId", "NameAr", "NameEn" },
+                values: new object[,]
+                {
+                    { 1L, "AF", null, "أفغاني", "Afghan" },
+                    { 2L, "AL", null, "ألباني", "Albanian" },
+                    { 3L, "DZ", null, "جزائري", "Algerian" },
+                    { 4L, "AS", null, "أمريكي ساموي", "American Samoan" },
+                    { 5L, "US", null, "أمريكي", "American" },
+                    { 6L, "AD", null, "أندوري", "Andorran" },
+                    { 7L, "AO", null, "أنغولي", "Angolan" },
+                    { 8L, "AI", null, "أنغويلي", "Anguillian" },
+                    { 9L, "AG", null, "أنتيغي", "Antiguan" },
+                    { 10L, "AR", null, "أرجنتيني", "Argentinian" },
+                    { 11L, "AM", null, "أرميني", "Armenian" },
+                    { 12L, "AW", null, "أروبي", "Aruban" },
+                    { 13L, "AU", null, "أسترالي", "Australian" },
+                    { 14L, "AT", null, "نمساوي", "Austrian" },
+                    { 15L, "AZ", null, "أذربيجاني", "Azerbaijani" },
+                    { 16L, "BS", null, "باهامي", "Bahamian" },
+                    { 17L, "BH", null, "بحريني", "Bahraini" },
+                    { 18L, "BD", null, "بنغلاديشي", "Bangladeshi" },
+                    { 19L, "BB", null, "باربادوسي", "Barbadian" },
+                    { 20L, "BY", null, "بيلاروسي", "Belarusian" },
+                    { 21L, "BE", null, "بلجيكي", "Belgian" },
+                    { 22L, "BZ", null, "بليزي", "Belizean" },
+                    { 23L, "BJ", null, "بنيني", "Beninese" },
+                    { 24L, "BT", null, "بوتاني", "Bhutanese" },
+                    { 25L, "BO", null, "بوليفي", "Bolivian" },
+                    { 26L, "BA", null, "بوسني", "Bosnian" },
+                    { 27L, "BR", null, "برازيلي", "Brazilian" },
+                    { 28L, "GB", null, "بريطاني", "British" },
+                    { 29L, "BN", null, "بروني", "Bruneian" },
+                    { 30L, "BG", null, "بلغاري", "Bulgarian" },
+                    { 31L, "BF", null, "بوركيني", "Burkinabe" },
+                    { 32L, "MM", null, "بورمي", "Burmese" },
+                    { 33L, "BI", null, "بوروندي", "Burundian" },
+                    { 34L, "KH", null, "كمبودي", "Cambodian" },
+                    { 35L, "CM", null, "كاميروني", "Cameroonian" },
+                    { 36L, "CA", null, "كندي", "Canadian" },
+                    { 37L, "CV", null, "الرأس الأخضر", "Cape Verdean" },
+                    { 38L, "CF", null, "أفريقي أوسط", "Central African" },
+                    { 39L, "TD", null, "تشادي", "Chadian" },
+                    { 40L, "CL", null, "تشيلي", "Chilean" },
+                    { 41L, "CN", null, "صيني", "Chinese" },
+                    { 42L, "CO", null, "كولومبي", "Colombian" },
+                    { 43L, "KM", null, "قُمُري", "Comorian" },
+                    { 44L, "CG", null, "كونغولي", "Congolese" },
+                    { 45L, "CR", null, "كوستاريكي", "Costa Rican" },
+                    { 46L, "HR", null, "كرواتي", "Croatian" },
+                    { 47L, "CU", null, "كوبي", "Cuban" },
+                    { 48L, "CY", null, "قبرصي", "Cypriot" },
+                    { 49L, "CZ", null, "تشيكي", "Czech" },
+                    { 50L, "DK", null, "دنماركي", "Danish" },
+                    { 51L, "DJ", null, "جيبوتي", "Djiboutian" },
+                    { 52L, "DO", null, "دومينيكاني", "Dominican" },
+                    { 53L, "NL", null, "هولندي", "Dutch" },
+                    { 54L, "EC", null, "إكوادوري", "Ecuadorean" },
+                    { 55L, "EG", null, "مصري", "Egyptian" },
+                    { 56L, "AE", null, "إماراتي", "Emirati" },
+                    { 57L, "GQ", null, "غيني استوائي", "Equatorial Guinean" },
+                    { 58L, "ER", null, "إريتيري", "Eritrean" },
+                    { 59L, "EE", null, "إستوني", "Estonian" },
+                    { 60L, "ET", null, "أثيوبي", "Ethiopian" },
+                    { 61L, "FJ", null, "فيجي", "Fijian" },
+                    { 62L, "FI", null, "فنلندي", "Finnish" },
+                    { 63L, "FR", null, "فرنسي", "French" },
+                    { 64L, "GA", null, "غابوني", "Gabonese" },
+                    { 65L, "GM", null, "غامبي", "Gambian" },
+                    { 66L, "GE", null, "جورجي", "Georgian" },
+                    { 67L, "DE", null, "ألماني", "German" },
+                    { 68L, "GH", null, "غاني", "Ghanaian" },
+                    { 69L, "GI", null, "جبل طارق", "Gibraltarian" },
+                    { 70L, "GR", null, "يوناني", "Greek" },
+                    { 71L, "GL", null, "جرينلندي", "Greenlandic" },
+                    { 72L, "GD", null, "غرينادي", "Grenadian" },
+                    { 73L, "GU", null, "غوامي", "Guamanian" },
+                    { 74L, "GT", null, "غواتيمالي", "Guatemalan" },
+                    { 75L, "GN", null, "غيني", "Guinean" },
+                    { 76L, "GW", null, "غيني", "Guinean" },
+                    { 77L, "GY", null, "غياني", "Guyanese" },
+                    { 78L, "HT", null, "هايتي", "Haitian" },
+                    { 79L, "HN", null, "هندوراسي", "Honduran" },
+                    { 80L, "HK", null, "هونغ كونغي", "Hong Konger" },
+                    { 81L, "HU", null, "مجري", "Hungarian" },
+                    { 82L, "IS", null, "آيسلندي", "Icelander" },
+                    { 83L, "IN", null, "هندي", "Indian" },
+                    { 84L, "ID", null, "إندونيسي", "Indonesian" },
+                    { 85L, "IR", null, "إيراني", "Iranian" },
+                    { 86L, "IQ", null, "عراقي", "Iraqi" },
+                    { 87L, "IE", null, "إيرلندي", "Irish" },
+                    { 89L, "IT", null, "إيطالي", "Italian" },
+                    { 90L, "JM", null, "جامايكي", "Jamaican" },
+                    { 91L, "JP", null, "ياباني", "Japanese" },
+                    { 92L, "JE", null, "جيرسي", "Jersey" },
+                    { 93L, "JO", null, "أردني", "Jordanian" },
+                    { 94L, "KZ", null, "كازاخي", "Kazakh" },
+                    { 95L, "KE", null, "كيني", "Kenyan" },
+                    { 96L, "KI", null, "كيريباتي", "Kiribati" },
+                    { 97L, "KP", null, "كوري شمالي", "North Korean" },
+                    { 98L, "KR", null, "كوري جنوبي", "South Korean" },
+                    { 99L, "KW", null, "كويتي", "Kuwaiti" },
+                    { 100L, "KG", null, "قرغيزستاني", "Kyrgyzstani" },
+                    { 101L, "LA", null, "لاوي", "Lao" },
+                    { 102L, "LV", null, "لاتفي", "Latvian" },
+                    { 103L, "LB", null, "لبناني", "Lebanese" },
+                    { 104L, "LS", null, "ليسوتو", "Lesotho" },
+                    { 105L, "LR", null, "ليبيريي", "Liberian" },
+                    { 106L, "LY", null, "ليبي", "Libyan" },
+                    { 107L, "LI", null, "ليختنشتايني", "Liechtensteiner" },
+                    { 108L, "LT", null, "ليتواني", "Lithuanian" },
+                    { 109L, "LU", null, "لوكسمبورغي", "Luxembourgish" },
+                    { 110L, "MG", null, "ملغاشي", "Malagasy" },
+                    { 111L, "MW", null, "ملووي", "Malawian" },
+                    { 112L, "MY", null, "ماليزيا", "Malaysian" },
+                    { 113L, "MV", null, "مالديفي", "Maldivian" },
+                    { 114L, "ML", null, "مالي", "Malian" },
+                    { 115L, "MT", null, "مالطي", "Maltese" },
+                    { 116L, "MH", null, "مارشالي", "Marshallese" },
+                    { 117L, "MR", null, "موريتاني", "Mauritanian" },
+                    { 118L, "MU", null, "موريشيوسي", "Mauritian" },
+                    { 119L, "MX", null, "مكسيكي", "Mexican" },
+                    { 120L, "FM", null, "ماكروني", "Micronesian" },
+                    { 121L, "MD", null, "مولدوفي", "Moldovan" },
+                    { 122L, "MC", null, "موناكي", "Monacan" },
+                    { 123L, "MN", null, "منغولي", "Mongolian" },
+                    { 124L, "ME", null, "مونتينيغري", "Montenegrin" },
+                    { 125L, "MA", null, "مغربي", "Moroccan" },
+                    { 126L, "MZ", null, "موزمبيقي", "Mozambican" },
+                    { 127L, "NA", null, "ناميبي", "Namibian" },
+                    { 128L, "NR", null, "نيواروي", "Nauruan" },
+                    { 129L, "NP", null, "نيبالي", "Nepali" },
+                    { 130L, "NL", null, "هولندي", "Dutch" },
+                    { 131L, "NZ", null, "نيوزيلندي", "New Zealander" },
+                    { 132L, "NI", null, "نيكاراغوي", "Nicaraguan" },
+                    { 133L, "NE", null, "نيجيري", "Nigerien" },
+                    { 134L, "NG", null, "نيجيري", "Nigerian" },
+                    { 135L, "MK", null, "مقدوني شمالي", "North Macedonian" },
+                    { 136L, "NO", null, "نرويجي", "Norwegian" },
+                    { 137L, "OM", null, "عماني", "Omani" },
+                    { 138L, "PK", null, "باكستاني", "Pakistani" },
+                    { 139L, "PW", null, "بالاوي", "Palauan" },
+                    { 140L, "PA", null, "بنمي", "Panamanian" },
+                    { 141L, "PG", null, "بابوا غينيا الجديدة", "Papua New Guinean" },
+                    { 142L, "PY", null, "باراغواني", "Paraguayan" },
+                    { 143L, "PE", null, "بيروفي", "Peruvian" },
+                    { 144L, "PH", null, "فلبيني", "Filipino" },
+                    { 145L, "PL", null, "بولندي", "Polish" },
+                    { 146L, "PT", null, "برتغالي", "Portuguese" },
+                    { 147L, "QA", null, "قطري", "Qatari" },
+                    { 148L, "RE", null, "لا ريونيون", "Réunionese" },
+                    { 149L, "RO", null, "روماني", "Romanian" },
+                    { 150L, "RU", null, "روسي", "Russian" },
+                    { 151L, "RW", null, "رواندي", "Rwandan" },
+                    { 152L, "BL", null, "سانت بارتيليمي", "Saint Barthélemy" },
+                    { 153L, "SH", null, "سانت هيلاني", "Saint Helenian" },
+                    { 154L, "KN", null, "سانت كيتس ونيفيس", "Saint Kitts and Nevis" },
+                    { 155L, "LC", null, "سانت لوسيان", "Saint Lucian" },
+                    { 156L, "MF", null, "سانت مارتن", "Saint Martin" },
+                    { 157L, "SX", null, "سانت مارتن", "Sint Maarten" },
+                    { 158L, "WS", null, "سماوي", "Samoan" },
+                    { 159L, "SM", null, "سانماريني", "Sammarinese" },
+                    { 160L, "ST", null, "ساو توماني", "Sao Tomean" },
+                    { 161L, "SA", null, "سعودي", "Saudi" },
+                    { 162L, "SN", null, "سنغالي", "Senegalese" },
+                    { 163L, "RS", null, "صربي", "Serbian" },
+                    { 164L, "SC", null, "سيشلي", "Seychellois" },
+                    { 165L, "SL", null, "سيراليوني", "Sierra Leonean" },
+                    { 166L, "SG", null, "سنغافوري", "Singaporean" },
+                    { 167L, "SK", null, "سلوفاكي", "Slovak" },
+                    { 168L, "SI", null, "سلوفيني", "Slovenian" },
+                    { 169L, "SB", null, "سولوموني", "Solomon Islander" },
+                    { 170L, "SO", null, "صومالي", "Somali" },
+                    { 171L, "ZA", null, "جنوب أفريقي", "South African" },
+                    { 172L, "SS", null, "جنوب سوداني", "South Sudanese" },
+                    { 173L, "ES", null, "إسباني", "Spanish" },
+                    { 174L, "LK", null, "سريلانكي", "Sri Lankan" },
+                    { 175L, "SD", null, "سوداني", "Sudanese" },
+                    { 176L, "SR", null, "سورينامي", "Surinamese" },
+                    { 177L, "SZ", null, "سواتي", "Swazi" },
+                    { 178L, "SE", null, "سويدي", "Swedish" },
+                    { 179L, "CH", null, "سويسري", "Swiss" },
+                    { 180L, "SY", null, "سوري", "Syrian" },
+                    { 181L, "TW", null, "تايواني", "Taiwanese" },
+                    { 182L, "TJ", null, "طاجيكي", "Tajik" },
+                    { 183L, "TZ", null, "تنزاني", "Tanzanian" },
+                    { 184L, "TH", null, "تايلندي", "Thai" },
+                    { 185L, "TL", null, "تيموري", "Timorese" },
+                    { 186L, "TG", null, "توغولي", "Togolese" },
+                    { 187L, "TK", null, "توكلاوي", "Tokelauan" },
+                    { 188L, "TO", null, "تونغي", "Tongan" },
+                    { 189L, "TT", null, "ترينيدادي", "Trinidadian" },
+                    { 190L, "TN", null, "تونسي", "Tunisian" },
+                    { 191L, "TR", null, "تركي", "Turkish" },
+                    { 192L, "TM", null, "تركماني", "Turkmen" },
+                    { 193L, "TC", null, "تركي وكايكوسي", "Turks and Caicos Islander" },
+                    { 194L, "TV", null, "توفالي", "Tuvaluan" },
+                    { 195L, "UG", null, "أوغندي", "Ugandan" },
+                    { 196L, "UA", null, "أوكراني", "Ukrainian" },
+                    { 197L, "AE", null, "إماراتي", "Emirati" },
+                    { 198L, "GB", null, "بريطاني", "British" },
+                    { 199L, "US", null, "أمريكي", "American" },
+                    { 200L, "UY", null, "أوروغواي", "Uruguayan" },
+                    { 201L, "UZ", null, "أوزبكي", "Uzbek" },
+                    { 202L, "VU", null, "فانواتي", "Vanuatuan" },
+                    { 203L, "VE", null, "فنزويلي", "Venezuelan" },
+                    { 204L, "VN", null, "فيتنامي", "Vietnamese" },
+                    { 205L, "WF", null, "واليس وفوتونا", "Wallis and Futuna" },
+                    { 206L, "YE", null, "يمني", "Yemeni" },
+                    { 207L, "ZM", null, "زامبي", "Zambian" },
+                    { 208L, "ZW", null, "زيمبابوي", "Zimbabwean" }
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_AspNetUsers_NationalityId",
+                table: "AspNetUsers",
+                column: "NationalityId");
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_AspNetUsers_Nationalities_NationalityId",
+                table: "AspNetUsers",
+                column: "NationalityId",
+                principalTable: "Nationalities",
+                principalColumn: "Id");
+            var sqlStm = @"update Nationalities set CountryId = (select top 1 id from CountryLookups where UPPER(CountryCode)=UPPER(code))";
+            migrationBuilder.Sql(sqlStm);
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropForeignKey(
+                name: "FK_AspNetUsers_Nationalities_NationalityId",
+                table: "AspNetUsers");
+
+            migrationBuilder.DropTable(
+                name: "Nationalities");
+
+            migrationBuilder.DropIndex(
+                name: "IX_AspNetUsers_NationalityId",
+                table: "AspNetUsers");
+
+            migrationBuilder.DropColumn(
+                name: "ContractStatusId",
+                table: "Contracts");
+
+            migrationBuilder.DropColumn(
+                name: "ContractorTaxResidencyId",
+                table: "Contracts");
+
+            migrationBuilder.DropColumn(
+                name: "Address",
+                table: "Companies");
+
+            migrationBuilder.DropColumn(
+                name: "Email",
+                table: "Companies");
+
+            migrationBuilder.DropColumn(
+                name: "PhoneNumber",
+                table: "Companies");
+
+            migrationBuilder.DropColumn(
+                name: "CompanyRepresentativeTitle",
+                table: "AspNetUsers");
+
+            migrationBuilder.DropColumn(
+                name: "NationalityId",
+                table: "AspNetUsers");
+
+            migrationBuilder.DropColumn(
+                name: "PassportExpiryDate",
+                table: "AspNetUsers");
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 5663 - 0
MTWorkHR.Infrastructure/Migrations/20241030125620_altrCompanyTbl.Designer.cs


+ 129 - 0
MTWorkHR.Infrastructure/Migrations/20241030125620_altrCompanyTbl.cs

@@ -0,0 +1,129 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrCompanyTbl : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+          
+
+            migrationBuilder.AlterColumn<string>(
+                name: "PhoneNumber",
+                table: "Companies",
+                type: "nvarchar(max)",
+                nullable: false,
+                oldClrType: typeof(int),
+                oldType: "int");
+
+            migrationBuilder.AlterColumn<string>(
+                name: "Email",
+                table: "Companies",
+                type: "nvarchar(max)",
+                nullable: false,
+                oldClrType: typeof(int),
+                oldType: "int");
+
+            migrationBuilder.AlterColumn<string>(
+                name: "Address",
+                table: "Companies",
+                type: "nvarchar(max)",
+                nullable: false,
+                oldClrType: typeof(int),
+                oldType: "int");
+
+            migrationBuilder.AddColumn<long>(
+                name: "CityId",
+                table: "Companies",
+                type: "bigint",
+                nullable: true);
+
+            migrationBuilder.AddColumn<long>(
+                name: "CountryId",
+                table: "Companies",
+                type: "bigint",
+                nullable: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Companies_CityId",
+                table: "Companies",
+                column: "CityId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Companies_CountryId",
+                table: "Companies",
+                column: "CountryId");
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Companies_Cities_CityId",
+                table: "Companies",
+                column: "CityId",
+                principalTable: "Cities",
+                principalColumn: "Id");
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Companies_CountryLookups_CountryId",
+                table: "Companies",
+                column: "CountryId",
+                principalTable: "CountryLookups",
+                principalColumn: "Id");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropForeignKey(
+                name: "FK_Companies_Cities_CityId",
+                table: "Companies");
+
+            migrationBuilder.DropForeignKey(
+                name: "FK_Companies_CountryLookups_CountryId",
+                table: "Companies");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Companies_CityId",
+                table: "Companies");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Companies_CountryId",
+                table: "Companies");
+
+            migrationBuilder.DropColumn(
+                name: "CityId",
+                table: "Companies");
+
+            migrationBuilder.DropColumn(
+                name: "CountryId",
+                table: "Companies");
+
+            migrationBuilder.AlterColumn<int>(
+                name: "PhoneNumber",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+
+            migrationBuilder.AlterColumn<int>(
+                name: "Email",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+
+            migrationBuilder.AlterColumn<int>(
+                name: "Address",
+                table: "Companies",
+                type: "int",
+                nullable: false,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 5698 - 0
MTWorkHR.Infrastructure/Migrations/20241103150423_altrRoleBusiness.Designer.cs


+ 32 - 0
MTWorkHR.Infrastructure/Migrations/20241103150423_altrRoleBusiness.cs

@@ -0,0 +1,32 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrRoleBusiness : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+           
+            migrationBuilder.InsertData(
+                table: "AspNetRoles",
+                columns: new[] { "Id", "ConcurrencyStamp", "CreateDate", "CreateUser", "DeleteUserId", "IsAdmin", "IsDeleted", "Name", "NormalizedName", "UpdateDate", "UpdateUser" },
+                values: new object[] { "BS5B3B92-2311-48F8-9DEC-F9FAEF1F2110", null, new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), null, null, false, false, "Business", "BUSINESS", null, null });
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+         
+
+            migrationBuilder.DeleteData(
+                table: "AspNetRoles",
+                keyColumn: "Id",
+                keyValue: "BS5B3B92-2311-48F8-9DEC-F9FAEF1F2110");
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 5698 - 0
MTWorkHR.Infrastructure/Migrations/20241110132939_altrUserRoles.Designer.cs


+ 26 - 0
MTWorkHR.Infrastructure/Migrations/20241110132939_altrUserRoles.cs

@@ -0,0 +1,26 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrUserRoles : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            var sqlStm = @"Insert into AspNetUserRoles select Id, 'BS5B3B92-2311-48F8-9DEC-F9FAEF1F2110' from AspNetUsers where UserType=3";
+
+          
+            migrationBuilder.Sql(sqlStm);
+
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 5701 - 0
MTWorkHR.Infrastructure/Migrations/20241112095808_altrContractDura.Designer.cs


+ 81 - 0
MTWorkHR.Infrastructure/Migrations/20241112095808_altrContractDura.cs

@@ -0,0 +1,81 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrContractDura : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "JobTitleId",
+                table: "Contracts");
+
+            migrationBuilder.AddColumn<string>(
+                name: "JobTitleName",
+                table: "Contracts",
+                type: "nvarchar(max)",
+                nullable: true);
+
+            migrationBuilder.AddColumn<int>(
+                name: "WorkingHoursNum",
+                table: "Contracts",
+                type: "int",
+                nullable: false,
+                defaultValue: 0);
+
+            migrationBuilder.AlterColumn<decimal>(
+                name: "EntitlementPercent",
+                table: "ContractAllowance",
+                type: "decimal(18,2)",
+                nullable: false,
+                oldClrType: typeof(long),
+                oldType: "bigint");
+
+            migrationBuilder.AlterColumn<decimal>(
+                name: "EntitlementAmount",
+                table: "ContractAllowance",
+                type: "decimal(18,2)",
+                nullable: false,
+                oldClrType: typeof(long),
+                oldType: "bigint");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "JobTitleName",
+                table: "Contracts");
+
+            migrationBuilder.DropColumn(
+                name: "WorkingHoursNum",
+                table: "Contracts");
+
+            migrationBuilder.AddColumn<int>(
+                name: "JobTitleId",
+                table: "Contracts",
+                type: "int",
+                nullable: true);
+
+            migrationBuilder.AlterColumn<long>(
+                name: "EntitlementPercent",
+                table: "ContractAllowance",
+                type: "bigint",
+                nullable: false,
+                oldClrType: typeof(decimal),
+                oldType: "decimal(18,2)");
+
+            migrationBuilder.AlterColumn<long>(
+                name: "EntitlementAmount",
+                table: "ContractAllowance",
+                type: "bigint",
+                nullable: false,
+                oldClrType: typeof(decimal),
+                oldType: "decimal(18,2)");
+        }
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1783 - 230
MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs


+ 10 - 2
MTWorkHR.Infrastructure/Repositories/Chat/HubConnectionRepository.cs

@@ -18,13 +18,21 @@ namespace MTWorkHR.Infrastructure.Repositories
 
         public async Task<Tuple<IQueryable<HubConnection>, int>> GetAllAsync(string connectionId)
         {
-            var query = dbSet.AsQueryable();
+            var query = dbSet.Where(c=> c.SignalrId == connectionId).AsQueryable();
             var total = await query.CountAsync();
 
             return new Tuple<IQueryable<HubConnection>, int>(query, total);
         }
 
-       
+        public async Task<Tuple<IQueryable<HubConnection>, int>> GetAllByUserAsync(string userId)
+        {
+            var query = dbSet.Where(c=> c.UserId == userId).AsQueryable();
+            var total = await query.CountAsync();
+
+            return new Tuple<IQueryable<HubConnection>, int>(query, total);
+        }
+
+
 
     }
 }