diff --git a/0_Framework/0_Framework.csproj b/0_Framework/0_Framework.csproj index ad747dc2..66522232 100644 --- a/0_Framework/0_Framework.csproj +++ b/0_Framework/0_Framework.csproj @@ -6,6 +6,7 @@ + diff --git a/0_Framework/Application/AuthHelper.cs b/0_Framework/Application/AuthHelper.cs index 41e6efa2..2af2188f 100644 --- a/0_Framework/Application/AuthHelper.cs +++ b/0_Framework/Application/AuthHelper.cs @@ -56,6 +56,11 @@ public class AuthHelper : IAuthHelper return Tools.DeserializeFromBsonList(permissions); //Mahan } + public bool HasPermission(int permission) + { + return GetPermissions().Any(x => x == permission); + } + public long CurrentAccountId() { return IsAuthenticated() diff --git a/0_Framework/Application/FaceEmbedding/IFaceEmbeddingService.cs b/0_Framework/Application/FaceEmbedding/IFaceEmbeddingService.cs index b5aab83b..78dbf735 100644 --- a/0_Framework/Application/FaceEmbedding/IFaceEmbeddingService.cs +++ b/0_Framework/Application/FaceEmbedding/IFaceEmbeddingService.cs @@ -11,6 +11,7 @@ public interface IFaceEmbeddingService Task RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, float confidence, Dictionary metadata = null); Task DeleteEmbeddingAsync(long employeeId, long workshopId); Task> GetEmbeddingAsync(long employeeId, long workshopId); + Task UpdateEmbeddingFullNameAsync(long employeeId, long workshopId, string newFullName); } public class FaceEmbeddingResponse diff --git a/0_Framework/Application/IAuthHelper.cs b/0_Framework/Application/IAuthHelper.cs index ab9cf572..d43ac069 100644 --- a/0_Framework/Application/IAuthHelper.cs +++ b/0_Framework/Application/IAuthHelper.cs @@ -12,6 +12,7 @@ public interface IAuthHelper string CurrentAccountRole(); AuthViewModel CurrentAccountInfo(); List GetPermissions(); + bool HasPermission(int permission); long CurrentAccountId(); string CurrentAccountMobile(); diff --git a/0_Framework/Application/Sms/ISmsService.cs b/0_Framework/Application/Sms/ISmsService.cs index 6171e87a..9ce58010 100644 --- a/0_Framework/Application/Sms/ISmsService.cs +++ b/0_Framework/Application/Sms/ISmsService.cs @@ -27,7 +27,7 @@ public interface ISmsService Task GetCreditAmount(); - public Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId); + public Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms = null); public Task SendInstitutionAmendmentVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId); public Task SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName, diff --git a/0_Framework/Excel/ExcelGenerator.cs b/0_Framework/Excel/ExcelGenerator.cs index 23d6382b..fb172b1f 100644 --- a/0_Framework/Excel/ExcelGenerator.cs +++ b/0_Framework/Excel/ExcelGenerator.cs @@ -17,7 +17,7 @@ public class ExcelGenerator { public ExcelGenerator() { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); } public static byte[] GenerateExcel(List obj, string date = "") where T : class { diff --git a/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs b/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs index e6fd9da1..3af1276d 100644 --- a/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs +++ b/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs @@ -1,7 +1,10 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using FluentValidation; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -27,6 +30,14 @@ public class CustomExceptionHandler : IExceptionHandler (string Detail, string Title, int StatusCode, Dictionary? Extra) details = exception switch { + ValidationException validationException => + ( + validationException.Errors.FirstOrDefault()?.ErrorMessage ?? "One or more validation errors occurred.", + "Validation Error", + context.Response.StatusCode = StatusCodes.Status400BadRequest, + null + ), + InternalServerException => ( exception.Message, @@ -34,6 +45,7 @@ public class CustomExceptionHandler : IExceptionHandler context.Response.StatusCode = StatusCodes.Status500InternalServerError, null ), + BadRequestException bre => ( exception.Message, @@ -41,6 +53,7 @@ public class CustomExceptionHandler : IExceptionHandler context.Response.StatusCode = StatusCodes.Status400BadRequest, bre.Extra ), + NotFoundException => ( exception.Message, @@ -48,6 +61,7 @@ public class CustomExceptionHandler : IExceptionHandler context.Response.StatusCode = StatusCodes.Status404NotFound, null ), + UnAuthorizeException => ( exception.Message, @@ -55,6 +69,7 @@ public class CustomExceptionHandler : IExceptionHandler context.Response.StatusCode = StatusCodes.Status401Unauthorized, null ), + _ => ( exception.Message, @@ -73,8 +88,6 @@ public class CustomExceptionHandler : IExceptionHandler Extensions = details.Extra ?? new Dictionary() }; - - problemDetails.Extensions.Add("traceId", context.TraceIdentifier); await context.Response.WriteAsJsonAsync(problemDetails, cancellationToken: cancellationToken); diff --git a/0_Framework/InfraStructure/FaceEmbeddingService.cs b/0_Framework/InfraStructure/FaceEmbeddingService.cs index 0b709ed5..148adc80 100644 --- a/0_Framework/InfraStructure/FaceEmbeddingService.cs +++ b/0_Framework/InfraStructure/FaceEmbeddingService.cs @@ -18,329 +18,387 @@ namespace _0_Framework.Infrastructure; /// public class FaceEmbeddingService : IFaceEmbeddingService { - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILogger _logger; - private readonly IFaceEmbeddingNotificationService _notificationService; - private readonly string _apiBaseUrl; + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILogger _logger; + private readonly IFaceEmbeddingNotificationService _notificationService; + private readonly string _apiBaseUrl; - public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger logger, - IFaceEmbeddingNotificationService notificationService = null) - { - _httpClientFactory = httpClientFactory; - _logger = logger; - _notificationService = notificationService; - _apiBaseUrl = "http://localhost:8000"; - } + public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger logger, + IFaceEmbeddingNotificationService notificationService = null) + { + _httpClientFactory = httpClientFactory; + _logger = logger; + _notificationService = notificationService; + _apiBaseUrl = "http://localhost:8000"; + } - public async Task GenerateEmbeddingsAsync(long employeeId, long workshopId, - string employeeFullName, string picture1Path, string picture2Path) - { - try - { - var httpClient = _httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(_apiBaseUrl); - httpClient.Timeout = TimeSpan.FromSeconds(30); + public async Task GenerateEmbeddingsAsync(long employeeId, long workshopId, + string employeeFullName, string picture1Path, string picture2Path) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); - using var content = new MultipartFormDataContent(); + using var content = new MultipartFormDataContent(); - // Add form fields - content.Add(new StringContent(employeeId.ToString()), "employee_id"); - content.Add(new StringContent(workshopId.ToString()), "workshop_id"); - content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); + // Add form fields + content.Add(new StringContent(employeeId.ToString()), "employee_id"); + content.Add(new StringContent(workshopId.ToString()), "workshop_id"); + content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); - // Add picture files - if (File.Exists(picture1Path)) - { - var picture1Bytes = await File.ReadAllBytesAsync(picture1Path); - var picture1Content = new ByteArrayContent(picture1Bytes); - picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); - content.Add(picture1Content, "picture1", "1.jpg"); - } - else - { - _logger.LogWarning("Picture1 not found at path: {Path}", picture1Path); - return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" }; - } + // Add picture files + if (File.Exists(picture1Path)) + { + var picture1Bytes = await File.ReadAllBytesAsync(picture1Path); + var picture1Content = new ByteArrayContent(picture1Bytes); + picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); + content.Add(picture1Content, "picture1", "1.jpg"); + } + else + { + _logger.LogWarning("Picture1 not found at path: {Path}", picture1Path); + return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" }; + } - if (File.Exists(picture2Path)) - { - var picture2Bytes = await File.ReadAllBytesAsync(picture2Path); - var picture2Content = new ByteArrayContent(picture2Bytes); - picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); - content.Add(picture2Content, "picture2", "2.jpg"); - } - else - { - _logger.LogWarning("Picture2 not found at path: {Path}", picture2Path); - return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" }; - } + if (File.Exists(picture2Path)) + { + var picture2Bytes = await File.ReadAllBytesAsync(picture2Path); + var picture2Content = new ByteArrayContent(picture2Bytes); + picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); + content.Add(picture2Content, "picture2", "2.jpg"); + } + else + { + _logger.LogWarning("Picture2 not found at path: {Path}", picture2Path); + return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" }; + } - // Send request to Python API - var response = await httpClient.PostAsync("embeddings", content); + // Send request to Python API + var response = await httpClient.PostAsync("embeddings", content); - if (response.IsSuccessStatusCode) - { - var responseContent = await response.Content.ReadAsStringAsync(); - _logger.LogInformation("Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}", - employeeId, workshopId); + if (response.IsSuccessStatusCode) + { + var responseContent = await response.Content.ReadAsStringAsync(); + _logger.LogInformation( + "Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}", + employeeId, workshopId); - // ارسال اطلاع‌رسانی به سایر سیستم‌ها - if (_notificationService != null) - { - await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); - } + // ارسال اطلاع‌رسانی به سایر سیستم‌ها + if (_notificationService != null) + { + await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); + } - return new OperationResult - { - IsSuccedded = true, - Message = "Embedding با موفقیت ایجاد شد" - }; - } - else - { - var errorContent = await response.Content.ReadAsStringAsync(); - _logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}", - response.StatusCode, errorContent); + return new OperationResult + { + IsSuccedded = true, + Message = "Embedding با موفقیت ایجاد شد" + }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); - return new OperationResult - { - IsSuccedded = false, - Message = $"خطا در تولید Embedding: {response.StatusCode}" - }; - } - } - catch (HttpRequestException ex) - { - _logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطا در ارتباط با سرور Embedding" - }; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطای غیرمنتظره در تولید Embedding" - }; - } - } + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در تولید Embedding: {response.StatusCode}" + }; + } + } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در ارتباط با سرور Embedding" + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطای غیرمنتظره در تولید Embedding" + }; + } + } - public async Task GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId, - string employeeFullName, Stream picture1Stream, Stream picture2Stream) - { - try - { - var httpClient = _httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(_apiBaseUrl); - httpClient.Timeout = TimeSpan.FromSeconds(30); + public async Task GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId, + string employeeFullName, Stream picture1Stream, Stream picture2Stream) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); - using var content = new MultipartFormDataContent(); + using var content = new MultipartFormDataContent(); - // Add form fields - content.Add(new StringContent(employeeId.ToString()), "employee_id"); - content.Add(new StringContent(workshopId.ToString()), "workshop_id"); - content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); + // Add form fields + content.Add(new StringContent(employeeId.ToString()), "employee_id"); + content.Add(new StringContent(workshopId.ToString()), "workshop_id"); + content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); - // Add picture streams - var picture1Content = new StreamContent(picture1Stream); - picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); - content.Add(picture1Content, "picture1", "1.jpg"); + // Add picture streams + var picture1Content = new StreamContent(picture1Stream); + picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); + content.Add(picture1Content, "picture1", "1.jpg"); - var picture2Content = new StreamContent(picture2Stream); - picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); - content.Add(picture2Content, "picture2", "2.jpg"); + var picture2Content = new StreamContent(picture2Stream); + picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); + content.Add(picture2Content, "picture2", "2.jpg"); - // Send request to Python API - var response = await httpClient.PostAsync("embeddings", content); + // Send request to Python API + var response = await httpClient.PostAsync("embeddings", content); - if (response.IsSuccessStatusCode) - { - _logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", employeeId); - - // ارسال اطلاع‌رسانی به سایر سیستم‌ها - if (_notificationService != null) - { - await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); - } - - return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" }; - } - else - { - var errorContent = await response.Content.ReadAsStringAsync(); - _logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}", - response.StatusCode, errorContent); + if (response.IsSuccessStatusCode) + { + _logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", + employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = $"خطا در تولید Embedding: {response.StatusCode}" - }; - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطا در تولید Embedding" - }; - } - } + // ارسال اطلاع‌رسانی به سایر سیستم‌ها + if (_notificationService != null) + { + await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); + } - public async Task RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, - float confidence, Dictionary metadata = null) - { - try - { - var httpClient = _httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(_apiBaseUrl); - httpClient.Timeout = TimeSpan.FromSeconds(30); + return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); - var requestBody = new - { - employeeId, - workshopId, - embedding, - confidence, - metadata = metadata ?? new Dictionary() - }; + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در تولید Embedding: {response.StatusCode}" + }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", + employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در تولید Embedding" + }; + } + } - var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody); + public async Task RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, + float confidence, Dictionary metadata = null) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); - if (response.IsSuccessStatusCode) - { - _logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId); - - // ارسال اطلاع‌رسانی به سایر سیستم‌ها - if (_notificationService != null) - { - await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId); - } - - return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" }; - } - else - { - var errorContent = await response.Content.ReadAsStringAsync(); - _logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}", - response.StatusCode, errorContent); + var requestBody = new + { + employeeId, + workshopId, + embedding, + confidence, + metadata = metadata ?? new Dictionary() + }; - return new OperationResult - { - IsSuccedded = false, - Message = $"خطا در بهبود Embedding: {response.StatusCode}" - }; - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطا در بهبود Embedding" - }; - } - } + var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody); - public async Task DeleteEmbeddingAsync(long employeeId, long workshopId) - { - try - { - var httpClient = _httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(_apiBaseUrl); - httpClient.Timeout = TimeSpan.FromSeconds(30); + if (response.IsSuccessStatusCode) + { + _logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId); - var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}"); + // ارسال اطلاع‌رسانی به سایر سیستم‌ها + if (_notificationService != null) + { + await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId); + } - if (response.IsSuccessStatusCode) - { - _logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId); - - // ارسال اطلاع‌رسانی به سایر سیستم‌ها - if (_notificationService != null) - { - await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId); - } - - return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" }; - } - else - { - var errorContent = await response.Content.ReadAsStringAsync(); - _logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}", - response.StatusCode, errorContent); + return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); - return new OperationResult - { - IsSuccedded = false, - Message = $"خطا در حذف Embedding: {response.StatusCode}" - }; - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطا در حذف Embedding" - }; - } - } + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در بهبود Embedding: {response.StatusCode}" + }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در بهبود Embedding" + }; + } + } - public async Task> GetEmbeddingAsync(long employeeId, long workshopId) - { - try - { - var httpClient = _httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(_apiBaseUrl); - httpClient.Timeout = TimeSpan.FromSeconds(30); + public async Task DeleteEmbeddingAsync(long employeeId, long workshopId) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); - var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}"); + var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}"); - if (response.IsSuccessStatusCode) - { - var content = await response.Content.ReadAsStringAsync(); - var embeddingData = JsonSerializer.Deserialize(content, - new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + if (response.IsSuccessStatusCode) + { + _logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId); - _logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId); + // ارسال اطلاع‌رسانی به سایر سیستم‌ها + if (_notificationService != null) + { + await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId); + } - return new OperationResult - { - IsSuccedded = true, - Message = "Embedding دریافت شد", - Data = embeddingData - }; - } - else - { - var errorContent = await response.Content.ReadAsStringAsync(); - _logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}", - response.StatusCode, errorContent); - - return new OperationResult - { - IsSuccedded = false, - Message = $"خطا در دریافت Embedding: {response.StatusCode}" - }; - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId); - return new OperationResult - { - IsSuccedded = false, - Message = "خطا در دریافت Embedding" - }; - } - } -} + return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); + + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در حذف Embedding: {response.StatusCode}" + }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در حذف Embedding" + }; + } + } + + public async Task> GetEmbeddingAsync(long employeeId, long workshopId) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); + + var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}"); + + if (response.IsSuccessStatusCode) + { + var content = await response.Content.ReadAsStringAsync(); + var embeddingData = JsonSerializer.Deserialize(content, + new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + + _logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId); + + return new OperationResult + { + IsSuccedded = true, + Message = "Embedding دریافت شد", + Data = embeddingData + }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); + + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در دریافت Embedding: {response.StatusCode}" + }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در دریافت Embedding" + }; + } + } + + public async Task UpdateEmbeddingFullNameAsync(long employeeId, long workshopId, + string newFullName) + { + try + { + var httpClient = _httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(_apiBaseUrl); + httpClient.Timeout = TimeSpan.FromSeconds(30); + + var requestBody = new + { + employee_id = employeeId, + workshop_id = workshopId, + employee_full_name = newFullName + }; + + var response = await httpClient.PutAsJsonAsync("embeddings/update-name", requestBody); + + if (response.IsSuccessStatusCode) + { + _logger.LogInformation("Employee Name Changed For {EmployeeId} In workshop ={WorkshopId}", employeeId, + workshopId); + + // ارسال اطلاع‌رسانی به سایر سیستم‌ها + if (_notificationService != null) + { + //await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId); + } + + return new OperationResult { IsSuccedded = true, Message = "عملیات با موفقیت انجام شد" }; + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + _logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}", + response.StatusCode, errorContent); + + return new OperationResult + { + IsSuccedded = false, + Message = $"خطا در بهبود Embedding: {response.StatusCode}" + }; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while Changing EmployeeFullName for Employee {EmployeeId}", employeeId); + return new OperationResult + { + IsSuccedded = false, + Message = "خطا در بهبود Embedding" + }; + } + } +} \ No newline at end of file diff --git a/AccountManagement.Application.Contracts/Account/EditAccount.cs b/AccountManagement.Application.Contracts/Account/EditAccount.cs index 41afe474..877edafc 100644 --- a/AccountManagement.Application.Contracts/Account/EditAccount.cs +++ b/AccountManagement.Application.Contracts/Account/EditAccount.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace AccountManagement.Application.Contracts.Account; +namespace AccountManagement.Application.Contracts.Account; public class EditAccount : CreateAccount { diff --git a/AccountManagement.Application.Contracts/Account/EditClientAccount.cs b/AccountManagement.Application.Contracts/Account/EditClientAccount.cs index eef61835..9d18014f 100644 --- a/AccountManagement.Application.Contracts/Account/EditClientAccount.cs +++ b/AccountManagement.Application.Contracts/Account/EditClientAccount.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AccountManagement.Application.Contracts.Account; +namespace AccountManagement.Application.Contracts.Account; public class EditClientAccount : RegisterAccount { diff --git a/AccountManagement.Application.Contracts/Account/IAccountApplication.cs b/AccountManagement.Application.Contracts/Account/IAccountApplication.cs index 10b107ad..b1da0153 100644 --- a/AccountManagement.Application.Contracts/Account/IAccountApplication.cs +++ b/AccountManagement.Application.Contracts/Account/IAccountApplication.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AccountManagement.Application.Contracts.ProgramManager; using Shared.Contracts.PmUser.Queries; namespace AccountManagement.Application.Contracts.Account; @@ -75,12 +74,8 @@ public interface IAccountApplication void CameraLogin(CameraLoginRequest request); - /// - /// دریافت کاربر پروگرام منیجر با اکانت آی دی - /// - /// - /// - Task GetPmUserByAccountId(long accountId); + Task GetPmUserAsync(long accountId); + } public class CameraLoginRequest diff --git a/AccountManagement.Application.Contracts/Account/RegisterAccount.cs b/AccountManagement.Application.Contracts/Account/RegisterAccount.cs index 78b9fcf0..d299dd88 100644 --- a/AccountManagement.Application.Contracts/Account/RegisterAccount.cs +++ b/AccountManagement.Application.Contracts/Account/RegisterAccount.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using _0_Framework.Application; +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Http; namespace AccountManagement.Application.Contracts.Account; diff --git a/AccountManagement.Application.Contracts/Account/WorkshopSelectList.cs b/AccountManagement.Application.Contracts/Account/WorkshopSelectList.cs index 8e17212f..48d952b8 100644 --- a/AccountManagement.Application.Contracts/Account/WorkshopSelectList.cs +++ b/AccountManagement.Application.Contracts/Account/WorkshopSelectList.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace AccountManagement.Application.Contracts.Account; +namespace AccountManagement.Application.Contracts.Account; public class WorkshopSelectList { diff --git a/AccountManagement.Application.Contracts/ProgramManager/GetRoleDto.cs b/AccountManagement.Application.Contracts/ProgramManager/GetRoleDto.cs deleted file mode 100644 index a3256abd..00000000 --- a/AccountManagement.Application.Contracts/ProgramManager/GetRoleDto.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; - -namespace AccountManagement.Application.Contracts.ProgramManager; - -public record GetPmRolesDto -{ - /// - /// آی دی نقش - /// - public long Id { get; set; } - - /// - /// نام نقش - /// - public string RoleName { get; set; } - - /// - /// آی دی نقش در گزارشگیر - /// - public long? GozareshgirRoleId { get; set; } - - /// - /// لیست کدهای دسترسی - /// - public List Permissions { get; set; } - - -} \ No newline at end of file diff --git a/AccountManagement.Application/AccountApplication.cs b/AccountManagement.Application/AccountApplication.cs index 0736293d..ff2fd102 100644 --- a/AccountManagement.Application/AccountApplication.cs +++ b/AccountManagement.Application/AccountApplication.cs @@ -2,13 +2,9 @@ using _0_Framework.Application.Sms; using _0_Framework.Exceptions; using AccountManagement.Application.Contracts.Account; -using AccountManagement.Application.Contracts.ProgramManagerApiResult; using AccountManagement.Domain.AccountAgg; using AccountManagement.Domain.AccountLeftWorkAgg; using AccountManagement.Domain.CameraAccountAgg; -using AccountManagement.Domain.InternalApiCaller; -using AccountManagement.Domain.PmDomains.PmRoleUserAgg; -using AccountManagement.Domain.PmDomains.PmUserAgg; using AccountManagement.Domain.PositionAgg; using AccountManagement.Domain.RoleAgg; using AccountManagement.Domain.SubAccountAgg; @@ -17,25 +13,13 @@ using AccountManagement.Domain.SubAccountRoleAgg; using Company.Domain._common; using Company.Domain.WorkshopAgg; using Company.Domain.WorkshopSubAccountAgg; -using CompanyManagment.App.Contracts.Workshop; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.JsonPatch.Operations; using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json; using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Net.Http; -using System.Runtime.InteropServices; -using System.Security.Claims; -using System.Text; -using System.Threading; using System.Threading.Tasks; -using AccountManagement.Application.Contracts.ProgramManager; + using Shared.Contracts.PmUser.Commands; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; using Shared.Contracts.PmUser.Queries; //using AccountManagement.Domain.RoleAgg; @@ -58,13 +42,13 @@ public class AccountApplication : IAccountApplication private readonly ISubAccountRoleRepository _subAccountRoleRepository; private readonly IWorkshopSubAccountRepository _workshopSubAccountRepository; private readonly ISubAccountPermissionSubtitle1Repository _accountPermissionSubtitle1Repository; - private readonly IPmUserRepository _pmUserRepository; + private readonly IUnitOfWork _unitOfWork; private readonly IPmUserQueryService _pmUserQueryService; private readonly IPmUserCommandService _pmUserCommandService; public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher, - IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository, IPmUserQueryService pmUserQueryService, IPmUserCommandService pmUserCommandService) + IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserQueryService pmUserQueryService, IPmUserCommandService pmUserCommandService) { _authHelper = authHelper; _roleRepository = roleRepository; @@ -78,7 +62,7 @@ public class AccountApplication : IAccountApplication _workshopSubAccountRepository = workshopSubAccountRepository; _accountPermissionSubtitle1Repository = accountPermissionSubtitle1Repository; _unitOfWork = unitOfWork; - _pmUserRepository = pmUserRepository; + _pmUserQueryService = pmUserQueryService; _pmUserCommandService = pmUserCommandService; _fileUploader = fileUploader; @@ -171,6 +155,8 @@ public class AccountApplication : IAccountApplication if (command.IsProgramManagerUser) { + if (command.UserRoles == null) + return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است"); var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList(); var createPm = await _pmUserCommandService.Create(new CreatePmUserDto(command.Fullname, command.Username, account.Password, command.Mobile, null, account.id, pmUserRoles)); @@ -268,6 +254,8 @@ public class AccountApplication : IAccountApplication //); var userResult =await _pmUserQueryService.GetPmUserDataByAccountId(account.id); + if (command.UserRoles == null) + return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است"); var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList(); //اگر کاربر در پروگرام منیجر قبلا ایجاد شده @@ -412,6 +400,23 @@ public class AccountApplication : IAccountApplication .Permissions .Select(x => x.Code) .ToList(); + //PmPermission + var PmUserData = _pmUserQueryService.GetPmUserDataByAccountId(account.id).GetAwaiter().GetResult(); + if (PmUserData.AccountId > 0 && PmUserData.IsActive) + { + + var pmUserPermissions = + PmUserData.RoleListDto != null + ? PmUserData.RoleListDto + .SelectMany(x => x.Permissions) + .Where(p => p != 99) + .Distinct() + .ToList() + : new List(); + permissions.AddRange(pmUserPermissions); + } + + int? positionValue; if (account.PositionId != null) { @@ -421,7 +426,7 @@ public class AccountApplication : IAccountApplication { positionValue = null; } - var pmUserId = _pmUserQueryService.GetCurrentPmUserIdFromAccountId(account.id).GetAwaiter().GetResult(); + var pmUserId = PmUserData.AccountId > 0 ? PmUserData.AccountId : null; var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname , account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, account.AdminAreaPermission, @@ -1015,8 +1020,8 @@ public class AccountApplication : IAccountApplication _authHelper.CameraSignIn(authViewModel); } - public async Task GetPmUserByAccountId(long accountId) + public async Task GetPmUserAsync(long accountId) { - return await _pmUserRepository.GetPmUserByAccountId(accountId); + return await _pmUserQueryService.GetPmUserDataByAccountId(accountId); } } \ No newline at end of file diff --git a/AccountManagement.Application/CameraAccountApplication.cs b/AccountManagement.Application/CameraAccountApplication.cs index bf0c02c2..d5a0ae24 100644 --- a/AccountManagement.Application/CameraAccountApplication.cs +++ b/AccountManagement.Application/CameraAccountApplication.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using _0_Framework.Application; using AccountManagement.Application.Contracts.Account; using AccountManagement.Application.Contracts.CameraAccount; diff --git a/AccountManagement.Application/MediaApplication.cs b/AccountManagement.Application/MediaApplication.cs index 354027da..48056abb 100644 --- a/AccountManagement.Application/MediaApplication.cs +++ b/AccountManagement.Application/MediaApplication.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using _0_Framework.Application; diff --git a/AccountManagement.Application/RoleApplication.cs b/AccountManagement.Application/RoleApplication.cs index eb25b1dd..b4d7a7db 100644 --- a/AccountManagement.Application/RoleApplication.cs +++ b/AccountManagement.Application/RoleApplication.cs @@ -4,13 +4,7 @@ using AccountManagement.Domain.RoleAgg; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AccountManagement.Application.Contracts.ProgramManagerApiResult; -using AccountManagement.Domain.InternalApiCaller; using Company.Domain._common; -using AccountManagement.Application.Contracts.Ticket; -using AccountManagement.Domain.PmDomains.PmPermissionAgg; -using AccountManagement.Domain.PmDomains.PmRoleAgg; -using AccountManagement.Domain.PmDomains.PmUserAgg; using Microsoft.AspNetCore.Mvc.Rendering; using Shared.Contracts.PmRole.Commands; using GetPmRolesDto = Shared.Contracts.PmRole.Queries.GetPmRolesDto; @@ -22,18 +16,15 @@ namespace AccountManagement.Application; public class RoleApplication : IRoleApplication { private readonly IRoleRepository _roleRepository; - private readonly IPmRoleRepository _pmRoleRepository; - private readonly IPmUserRepository _pmUserRepository; + private readonly IPmRoleQueryService _pmRoleQueryService; private readonly IPmRoleCommandService _pmRoleCommandService; private readonly IUnitOfWork _unitOfWork; - public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService) + public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService) { _roleRepository = roleRepository; _unitOfWork = unitOfWork; - _pmRoleRepository = pmRoleRepository; - _pmUserRepository = pmUserRepository; _pmRoleQueryService = pmRoleQueryService; _pmRoleCommandService = pmRoleCommandService; } diff --git a/AccountManagement.Application/SubAccountApplication.cs b/AccountManagement.Application/SubAccountApplication.cs index 8d2f592f..cd79c847 100644 --- a/AccountManagement.Application/SubAccountApplication.cs +++ b/AccountManagement.Application/SubAccountApplication.cs @@ -5,14 +5,11 @@ using AccountManagement.Domain.AccountAgg; using AccountManagement.Domain.CameraAccountAgg; using AccountManagement.Domain.SubAccountAgg; using AccountManagement.Domain.SubAccountRoleAgg; -using Company.Domain.WorkshopAccountAgg; using Company.Domain.WorkshopSubAccountAgg; -using CompanyManagment.App.Contracts.Workshop; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace AccountManagement.Application diff --git a/AccountManagement.Application/TaskSubjectApplication.cs b/AccountManagement.Application/TaskSubjectApplication.cs index 42383942..c27fa674 100644 --- a/AccountManagement.Application/TaskSubjectApplication.cs +++ b/AccountManagement.Application/TaskSubjectApplication.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using _0_Framework.Application; using AccountManagement.Application.Contracts.TaskSubject; using AccountManagement.Domain.TaskSubjectAgg; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace AccountManagement.Application; diff --git a/AccountManagement.Configuration/PmDbBootstrapper.cs b/AccountManagement.Configuration/PmDbBootstrapper.cs deleted file mode 100644 index 84d93fa8..00000000 --- a/AccountManagement.Configuration/PmDbBootstrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using AccountManagement.Domain.PmDomains.PmRoleAgg; -using AccountManagement.Domain.PmDomains.PmUserAgg; -using AccountMangement.Infrastructure.EFCore.PmDbConetxt; -using AccountMangement.Infrastructure.EFCore.Repository.PmRepositories; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; - -namespace AccountManagement.Configuration; - -public class PmDbBootstrapper -{ - public static void Configure(IServiceCollection services, string connectionString) - { - services.AddTransient(); - services.AddTransient(); - services.AddDbContext(x => x.UseSqlServer(connectionString)); - } -} \ No newline at end of file diff --git a/AccountManagement.Domain/PmDomains/PmPermissionAgg/PmPermission.cs b/AccountManagement.Domain/PmDomains/PmPermissionAgg/PmPermission.cs deleted file mode 100644 index 691a9954..00000000 --- a/AccountManagement.Domain/PmDomains/PmPermissionAgg/PmPermission.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AccountManagement.Domain.PmDomains.PmRoleAgg; - -namespace AccountManagement.Domain.PmDomains.PmPermissionAgg; - -public class PmPermission -{ - public long Id { get; private set; } - public int Code { get; private set; } - public PmRole Role { get; private set; } - - public PmPermission(int code) - { - Code = code; - } -} \ No newline at end of file diff --git a/AccountManagement.Domain/PmDomains/PmRoleAgg/IPmRoleRepository.cs b/AccountManagement.Domain/PmDomains/PmRoleAgg/IPmRoleRepository.cs deleted file mode 100644 index 49cb7f4e..00000000 --- a/AccountManagement.Domain/PmDomains/PmRoleAgg/IPmRoleRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using _0_Framework.Domain; -using System.Collections.Generic; -using System.Threading.Tasks; -using AccountManagement.Application.Contracts.ProgramManager; - -namespace AccountManagement.Domain.PmDomains.PmRoleAgg; - -public interface IPmRoleRepository :IRepository -{ - Task> GetPmRoleList(long? gozareshgirRoleId); - - Task GetPmRoleToEdit(long gozareshgirRoleId); - -} - diff --git a/AccountManagement.Domain/PmDomains/PmRoleAgg/PmRole.cs b/AccountManagement.Domain/PmDomains/PmRoleAgg/PmRole.cs deleted file mode 100644 index ddb305ea..00000000 --- a/AccountManagement.Domain/PmDomains/PmRoleAgg/PmRole.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using _0_Framework.Domain; -using AccountManagement.Domain.PmDomains.PmPermissionAgg; - -namespace AccountManagement.Domain.PmDomains.PmRoleAgg; - -public class PmRole : EntityBase -{ - /// - /// نام نقش - /// - public string RoleName { get; private set; } - - - /// - /// لیست پرمیشن کد ها - /// - public List PmPermission { get; private set; } - - /// - /// ای دی نقش در گزارشگیر - /// - public long? GozareshgirRoleId { get; private set; } - - - protected PmRole() - { - } - - public PmRole(string roleName,long? gozareshgirRolId, List permissions) - { - RoleName = roleName; - PmPermission = permissions; - GozareshgirRoleId = gozareshgirRolId; - - } - - - public void Edit(string roleName, List permissions) - { - RoleName = roleName; - PmPermission = permissions; - } - - -} \ No newline at end of file diff --git a/AccountManagement.Domain/PmDomains/PmRoleUserAgg/PmRoleUser.cs b/AccountManagement.Domain/PmDomains/PmRoleUserAgg/PmRoleUser.cs deleted file mode 100644 index a7cf6355..00000000 --- a/AccountManagement.Domain/PmDomains/PmRoleUserAgg/PmRoleUser.cs +++ /dev/null @@ -1,19 +0,0 @@ -using AccountManagement.Domain.PmDomains.PmUserAgg; - -namespace AccountManagement.Domain.PmDomains.PmRoleUserAgg; - -public class PmRoleUser -{ - public PmRoleUser(long roleId) - { - RoleId = roleId; - } - - public long Id { get; private set; } - public long RoleId { get; private set; } - - - public PmUser User { get; set; } - - -} \ No newline at end of file diff --git a/AccountManagement.Domain/PmDomains/PmUserAgg/IPmUserRepository.cs b/AccountManagement.Domain/PmDomains/PmUserAgg/IPmUserRepository.cs deleted file mode 100644 index 52c28fc1..00000000 --- a/AccountManagement.Domain/PmDomains/PmUserAgg/IPmUserRepository.cs +++ /dev/null @@ -1,22 +0,0 @@ -using _0_Framework.Domain; -using AccountManagement.Application.Contracts.ProgramManager; -using System.Threading.Tasks; -using Shared.Contracts.PmUser.Queries; - -namespace AccountManagement.Domain.PmDomains.PmUserAgg; - -public interface IPmUserRepository : IRepository -{ - /// - /// دریافت کاربر پروگرام منیجر جهتد ویرایش - /// - /// - /// - Task GetByPmUsertoEditbyAccountId(long accountId); - /// - /// دریافت کرابر پروگرام منیجر با اکانت آی دی در گزارشگیر - /// - /// - /// - Task GetPmUserByAccountId(long accountId); -} \ No newline at end of file diff --git a/AccountManagement.Domain/PmDomains/PmUserAgg/PmUser.cs b/AccountManagement.Domain/PmDomains/PmUserAgg/PmUser.cs deleted file mode 100644 index 6b0c531a..00000000 --- a/AccountManagement.Domain/PmDomains/PmUserAgg/PmUser.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using _0_Framework.Domain; -using AccountManagement.Domain.PmDomains.PmRoleUserAgg; - - -namespace AccountManagement.Domain.PmDomains.PmUserAgg; - -/// -/// کاربر -/// -public class PmUser : EntityBase -{ - /// - /// ایجاد - /// - /// - /// - /// - /// - /// - /// - /// - public PmUser(string fullName, string userName, string password, string mobile, string email, long? accountId, List roles) - { - FullName = fullName; - UserName = userName; - Password = password; - Mobile = mobile; - Email = email; - IsActive = true; - AccountId = accountId; - RoleUser = roles; - } - - protected PmUser() - { - - } - /// - /// نام و نام خانوادگی - /// - public string FullName { get; private set; } - - /// - /// نام کاربری - /// - public string UserName { get; private set; } - - /// - /// گذرواژه - /// - public string Password { get; private set; } - - /// - /// مسیر عکس پروفایل - /// - public string ProfilePhotoPath { get; private set; } - - /// - /// شماره موبایل - /// - public string Mobile { get; set; } - - /// - /// ایمیل - /// - public string Email { get; private set; } - - /// - /// فعال/غیر فعال بودن یوزر - /// - public bool IsActive { get; private set; } - - - /// - /// کد یکبارمصرف ورود - /// - public string VerifyCode { get; private set; } - - /// - /// آی دی کاربر در گزارشگیر - /// - public long? AccountId { get; private set; } - - - /// - /// لیست پرمیشن کد ها - /// - public List RoleUser { get; private set; } - - - /// - /// آپدیت کاربر - /// - /// - /// - /// - /// - /// - public void Edit(string fullName, string userName, string mobile, List roles, bool isActive) - { - FullName = fullName; - UserName = userName; - Mobile = mobile; - RoleUser = roles; - IsActive = isActive; - } - - /// - /// غیرفعال سازی - /// - public void DeActive() - { - IsActive = false; - } - - /// - /// فعال سازی - /// - public void ReActive() - { - IsActive = true; - } - - -} \ No newline at end of file diff --git a/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmRoleMapping.cs b/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmRoleMapping.cs deleted file mode 100644 index 00324b3d..00000000 --- a/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmRoleMapping.cs +++ /dev/null @@ -1,24 +0,0 @@ -using AccountManagement.Domain.PmDomains.PmRoleAgg; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace AccountMangement.Infrastructure.EFCore.Mappings.PmMappings; - -public class PmRoleMapping : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("PmRoles", t => t.ExcludeFromMigrations()); - builder.HasKey(x => x.id); - - builder.Property(x => x.RoleName).HasMaxLength(100).IsRequired(); - - builder.OwnsMany(x => x.PmPermission, navigationBuilder => - { - navigationBuilder.HasKey(x => x.Id); - navigationBuilder.ToTable("PmRolePermissions", t => t.ExcludeFromMigrations()); - - navigationBuilder.WithOwner(x => x.Role); - }); - } -} \ No newline at end of file diff --git a/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmUserMapping.cs b/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmUserMapping.cs deleted file mode 100644 index 9ee5e126..00000000 --- a/AccountMangement.Infrastructure.EFCore/Mappings/PmMappings/PmUserMapping.cs +++ /dev/null @@ -1,30 +0,0 @@ -using AccountManagement.Domain.PmDomains.PmUserAgg; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace AccountMangement.Infrastructure.EFCore.Mappings.PmMappings; - -public class PmUserMapping :IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Users"); - builder.HasKey(x => x.id); - - builder.Property(x => x.FullName).HasMaxLength(100).IsRequired(); - builder.Property(x => x.UserName).HasMaxLength(100).IsRequired(); - builder.Property(x => x.Password).HasMaxLength(1000).IsRequired(); - builder.Property(x => x.ProfilePhotoPath).HasMaxLength(500).IsRequired(false); - builder.Property(x => x.Mobile).HasMaxLength(20).IsRequired(); - builder.Property(x => x.Email).HasMaxLength(150).IsRequired(false); ; - builder.Property(x => x.VerifyCode).HasMaxLength(10).IsRequired(false); - builder.OwnsMany(x => x.RoleUser, navigationBuilder => - { - navigationBuilder.HasKey(x => x.Id); - navigationBuilder.ToTable("RoleUsers"); - navigationBuilder.WithOwner(x => x.User); - }); - - - } -} \ No newline at end of file diff --git a/AccountMangement.Infrastructure.EFCore/PmDbConetxt/PmDbContext.cs b/AccountMangement.Infrastructure.EFCore/PmDbConetxt/PmDbContext.cs deleted file mode 100644 index a668490e..00000000 --- a/AccountMangement.Infrastructure.EFCore/PmDbConetxt/PmDbContext.cs +++ /dev/null @@ -1,32 +0,0 @@ -using AccountManagement.Domain.PmDomains.PmRoleAgg; -using AccountManagement.Domain.PmDomains.PmUserAgg; -using AccountMangement.Infrastructure.EFCore.Mappings; -using AccountMangement.Infrastructure.EFCore.Mappings.PmMappings; -using Microsoft.EntityFrameworkCore; - -namespace AccountMangement.Infrastructure.EFCore.PmDbConetxt; - -public class PmDbContext : DbContext -{ - public PmDbContext(DbContextOptions options) : base(options) - { - - } - public DbSet Users { get; set; } = null!; - public DbSet PmRoles { get; set; } = null!; - - - public PmDbContext() - { - - } - - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - var assembly = typeof(PmUserMapping).Assembly; - modelBuilder.ApplyConfigurationsFromAssembly(assembly); - //SubAccountPermissionSeeder.Seed(modelBuilder); - base.OnModelCreating(modelBuilder); - } -} \ No newline at end of file diff --git a/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmRoleRepository.cs b/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmRoleRepository.cs deleted file mode 100644 index e3f93e53..00000000 --- a/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmRoleRepository.cs +++ /dev/null @@ -1,49 +0,0 @@ -using _0_Framework.InfraStructure; -using AccountManagement.Application.Contracts.ProgramManager; -using AccountManagement.Domain.PmDomains.PmRoleAgg; -using AccountMangement.Infrastructure.EFCore.PmDbConetxt; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory; - -namespace AccountMangement.Infrastructure.EFCore.Repository.PmRepositories; - -public class PmRoleRepository : RepositoryBase, IPmRoleRepository -{ - private readonly PmDbContext _pmDbContext; - public PmRoleRepository(PmDbContext context) : base(context) - { - _pmDbContext = context; - } - - public async Task> GetPmRoleList(long? gozareshgirRoleId) - { - var query = _pmDbContext.PmRoles.AsQueryable(); - if (gozareshgirRoleId != null && gozareshgirRoleId > 0) - query = query.Where(x => x.GozareshgirRoleId == gozareshgirRoleId); - var res = await query - .Select(p => new GetPmRolesDto() - { - Id = p.id, - RoleName = p.RoleName, - GozareshgirRoleId = p.GozareshgirRoleId, - Permissions = p.PmPermission.Select(x => x.Code).ToList() - - }) - .ToListAsync(); - - return res; - } - - - - public async Task GetPmRoleToEdit(long gozareshgirRoleId) - { - return await _pmDbContext.PmRoles.FirstOrDefaultAsync(x => x.GozareshgirRoleId == gozareshgirRoleId); - - } - -} \ No newline at end of file diff --git a/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmUserRepository.cs b/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmUserRepository.cs deleted file mode 100644 index e4915a65..00000000 --- a/AccountMangement.Infrastructure.EFCore/Repository/PmRepositories/PmUserRepository.cs +++ /dev/null @@ -1,48 +0,0 @@ -using _0_Framework.InfraStructure; -using AccountManagement.Application.Contracts.ProgramManager; -using AccountManagement.Domain.PmDomains.PmUserAgg; -using AccountMangement.Infrastructure.EFCore.PmDbConetxt; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Shared.Contracts.PmUser.Queries; - -namespace AccountMangement.Infrastructure.EFCore.Repository.PmRepositories; - -public class PmUserRepository :RepositoryBase, IPmUserRepository -{ - private readonly PmDbContext _pmDbContext; - public PmUserRepository(PmDbContext context, PmDbContext pmDbContext) : base(context) - { - _pmDbContext = pmDbContext; - } - public async Task GetByPmUsertoEditbyAccountId(long accountId) - { - return await _pmDbContext.Users.FirstOrDefaultAsync(x => x.AccountId == accountId); - } - - public async Task GetPmUserByAccountId(long accountId) - { - var query = await _pmDbContext.Users.FirstOrDefaultAsync(x => x.AccountId == accountId); - if (query == null) - return new GetPmUserDto(); - List roles = query.RoleUser.Select(x => x.RoleId).ToList(); - return new GetPmUserDto() - { - FullName = query.FullName, - UserName = query.UserName, - ProfilePhotoPath = query.ProfilePhotoPath, - Mobile = query.Mobile, - IsActive = query.IsActive, - AccountId = query.AccountId, - Roles = roles, - RoleListDto = await _pmDbContext.PmRoles.Where(x => roles.Contains(x.id)).Select(x => new RoleListDto() - { - RoleName = x.RoleName, - RoleId = x.id, - Permissions = x.PmPermission.Select(x => x.Code).ToList() - }).ToListAsync(), - }; - } -} \ No newline at end of file diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj index d003ac92..3032b3a1 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj @@ -12,6 +12,7 @@ + diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs index 1425a1a7..b97ff4f8 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs @@ -47,6 +47,11 @@ public class JobSchedulerRegistrator () => SendBlockSms(), "*/1 * * * *" // هر 1 دقیقه یکبار چک کن ); + RecurringJob.AddOrUpdate( + "InstitutionContract.SendInstitutionContractConfirmSms", + () => SendInstitutionContractConfirmSms(), + "*/1 * * * *" // هر 1 دقیقه یکبار چک کن + ); } @@ -146,4 +151,15 @@ public class JobSchedulerRegistrator await _institutionContractRepository.SendBlockSmsForBackgroundTask(); } + + /// + /// ارسال پیامک یادآور تایید قراداد مالی + /// + /// + [DisableConcurrentExecution(timeoutInSeconds: 100)] + public async System.Threading.Tasks.Task SendInstitutionContractConfirmSms() + { + await _institutionContractRepository.SendInstitutionContractConfirmSmsTask(); + } + } \ No newline at end of file diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs index dda9d58e..3cb83458 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs @@ -7,11 +7,16 @@ using BackgroundInstitutionContract.Task; using BackgroundInstitutionContract.Task.Jobs; using CompanyManagment.App.Contracts.Hubs; using CompanyManagment.EFCore.Services; +using GozareshgirProgramManager.Application._Bootstrapper; +using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; +using GozareshgirProgramManager.Infrastructure; +using GozareshgirProgramManager.Infrastructure.Persistence.Seed; using Hangfire; using Microsoft.AspNetCore.Identity; using MongoDB.Driver; using PersonalContractingParty.Config; using Query.Bootstrapper; +using Shared.Contracts.PmUser.Queries; using WorkFlow.Infrastructure.Config; var builder = WebApplication.CreateBuilder(args); @@ -38,10 +43,15 @@ builder.Services.AddSingleton(mongoDatabase); #endregion +builder.Services.AddProgramManagerApplication(); +builder.Services.AddProgramManagerInfrastructure(builder.Configuration); + + PersonalBootstrapper.Configure(builder.Services, connectionString); TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb); AccountManagementBootstrapper.Configure(builder.Services, connectionString); WorkFlowBootstrapper.Configure(builder.Services, connectionString); + QueryBootstrapper.Configure(builder.Services); JobsBootstrapper.Configure(builder.Services); builder.Services.AddHttpClient(); diff --git a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs index 74f06914..4d045c9a 100644 --- a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs +++ b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs @@ -142,6 +142,11 @@ public interface IInstitutionContractRepository : IRepository Task SendReminderSmsToContractingParties(List smsListData, string typeOfSms, string sendMessStart, string sendMessEnd); + /// + /// ارسال پیامک یادآور تایید قراداد مالی + /// + /// + Task SendInstitutionContractConfirmSmsTask(); #endregion #region CreateMontlyTransaction diff --git a/Company.Domain/InsuranceListAgg/IInsuranceListRepository.cs b/Company.Domain/InsuranceListAgg/IInsuranceListRepository.cs index 214df689..b8b95235 100644 --- a/Company.Domain/InsuranceListAgg/IInsuranceListRepository.cs +++ b/Company.Domain/InsuranceListAgg/IInsuranceListRepository.cs @@ -73,6 +73,7 @@ public interface IInsuranceListRepository:IRepository Task GetInsuranceOperationDetails(long id); Task GetTabCounts(InsuranceListSearchModel searchModel); + Task> GetInsuranceClientList(InsuranceClientSearchModel searchModel); #endregion diff --git a/CompanyManagement.Infrastructure.Excel/CWS/CustomizeWorkshopGroupSettingExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/CWS/CustomizeWorkshopGroupSettingExcelGenerator.cs index 4d27f8bc..9a828e93 100644 --- a/CompanyManagement.Infrastructure.Excel/CWS/CustomizeWorkshopGroupSettingExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/CWS/CustomizeWorkshopGroupSettingExcelGenerator.cs @@ -26,7 +26,7 @@ public class CustomizeWorkshopGroupSettingExcelGenerator { public static byte[] Generate(List groups) { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using (var package = new ExcelPackage()) { var worksheet = package.Workbook.Worksheets.Add("GroupsAndEmployees"); diff --git a/CompanyManagement.Infrastructure.Excel/CaseManagement/CaseManagementExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/CaseManagement/CaseManagementExcelGenerator.cs index 1387a76a..17d3ad48 100644 --- a/CompanyManagement.Infrastructure.Excel/CaseManagement/CaseManagementExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/CaseManagement/CaseManagementExcelGenerator.cs @@ -24,7 +24,7 @@ public class CaseManagementExcelGenerator }; public static byte[] GenerateCheckoutTempExcelInfo(List data) { - OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new ExcelPackage(); CreateSheet(data, package,"همه"); CreateSheet(data.Where(x=>x.Status ==2).ToList(), package,"فعال"); diff --git a/CompanyManagement.Infrastructure.Excel/Checkout/CustomizeCheckoutExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/Checkout/CustomizeCheckoutExcelGenerator.cs index 313b456a..68c3f6e4 100644 --- a/CompanyManagement.Infrastructure.Excel/Checkout/CustomizeCheckoutExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/Checkout/CustomizeCheckoutExcelGenerator.cs @@ -46,7 +46,7 @@ public class CustomizeCheckoutExcelGenerator }; public static byte[] GenerateCheckoutTempExcelInfo(List data, List selectedParameters) { - OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("Sheet1"); diff --git a/CompanyManagement.Infrastructure.Excel/EmployeeBankInfo/EmployeeBankInfoExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/EmployeeBankInfo/EmployeeBankInfoExcelGenerator.cs index 9e71b3b3..ec3f14ea 100644 --- a/CompanyManagement.Infrastructure.Excel/EmployeeBankInfo/EmployeeBankInfoExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/EmployeeBankInfo/EmployeeBankInfoExcelGenerator.cs @@ -7,7 +7,7 @@ public class EmployeeBankInfoExcelGenerator { public static byte[] Generate(List list) { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("EmployeeBankInfo"); @@ -166,7 +166,7 @@ public class EmployeeBankInfoExcelGenerator public static byte[] Generate2(List list) { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new ExcelPackage(); foreach (var employee in list) { @@ -220,4 +220,4 @@ public class EmployeeBankInfoExcelGenerator cell.Style.VerticalAlignment = ExcelVerticalAlignment.Center; cell.Style.Fill.PatternType = ExcelFillStyle.Solid; } -} \ No newline at end of file +} diff --git a/CompanyManagement.Infrastructure.Excel/InstitutionContract/InstitutionContractExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/InstitutionContract/InstitutionContractExcelGenerator.cs index 67098ba7..e17f21df 100644 --- a/CompanyManagement.Infrastructure.Excel/InstitutionContract/InstitutionContractExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/InstitutionContract/InstitutionContractExcelGenerator.cs @@ -13,7 +13,7 @@ public class InstitutionContractExcelGenerator public static byte[] GenerateExcel(List institutionContractViewModels) { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new ExcelPackage(); var allWorksheet = package.Workbook.Worksheets.Add("همه"); diff --git a/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs b/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs index b7455351..8c749dd4 100644 --- a/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs +++ b/CompanyManagement.Infrastructure.Excel/RollCall/RollCallExcelGenerator.cs @@ -8,7 +8,7 @@ public class RollCallExcelGenerator : ExcelGenerator { public static byte[] CaseHistoryExcelForEmployee(CaseHistoryRollCallExcelForEmployeeViewModel data) { - OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new OfficeOpenXml.ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("Sheet1"); var rollCalls = data.RollCalls; @@ -181,7 +181,7 @@ public class RollCallExcelGenerator : ExcelGenerator public static byte[] CaseHistoryExcelForOneDay(CaseHistoryRollCallForOneDayViewModel data) { - OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using var package = new OfficeOpenXml.ExcelPackage(); var worksheet = package.Workbook.Worksheets.Add("Sheet1"); var rollCalls = data.RollCalls; diff --git a/CompanyManagement.Infrastructure.Excel/SalaryAid/SalaryAidImportExcel.cs b/CompanyManagement.Infrastructure.Excel/SalaryAid/SalaryAidImportExcel.cs index fe393695..fc45ab9b 100644 --- a/CompanyManagement.Infrastructure.Excel/SalaryAid/SalaryAidImportExcel.cs +++ b/CompanyManagement.Infrastructure.Excel/SalaryAid/SalaryAidImportExcel.cs @@ -43,7 +43,7 @@ public class SalaryAidImportExcel ValidData = [] }; - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); if (file == null || file.Length == 0) { diff --git a/CompanyManagement.Infrastructure.Excel/WorkshopsRollCall/WorkshopRollCallExcelExporter.cs b/CompanyManagement.Infrastructure.Excel/WorkshopsRollCall/WorkshopRollCallExcelExporter.cs index 86676126..23032db6 100644 --- a/CompanyManagement.Infrastructure.Excel/WorkshopsRollCall/WorkshopRollCallExcelExporter.cs +++ b/CompanyManagement.Infrastructure.Excel/WorkshopsRollCall/WorkshopRollCallExcelExporter.cs @@ -9,7 +9,7 @@ public class WorkshopRollCallExcelExporter { public static byte[] Export(List workshops) { - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization"); using (var package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("Workshops"); diff --git a/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs b/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs index 89e15168..1e40cf51 100644 --- a/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs +++ b/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs @@ -60,7 +60,7 @@ public interface IEmployeeApplication /// Task> ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode, - string birthDate, long workshopId); + string birthDate,bool authorizedCanceled, long workshopId); /// /// پرسنل هایی که در کارگاهی از سمت ادمین شروع به کار کرده اند diff --git a/CompanyManagment.App.Contracts/EmployeeDocuments/WorkshopWithEmployeeDocumentsViewModel.cs b/CompanyManagment.App.Contracts/EmployeeDocuments/WorkshopWithEmployeeDocumentsViewModel.cs index bfc63e07..df9aedd1 100644 --- a/CompanyManagment.App.Contracts/EmployeeDocuments/WorkshopWithEmployeeDocumentsViewModel.cs +++ b/CompanyManagment.App.Contracts/EmployeeDocuments/WorkshopWithEmployeeDocumentsViewModel.cs @@ -13,5 +13,6 @@ namespace CompanyManagment.App.Contracts.EmployeeDocuments public string EmployerName { get; set; } public List SubmittedItems { get; set; } public int EmployeesWithoutDocumentCount { get; set; } + public long EmployeeId { get; set; } } } diff --git a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionCreationVerificationSmsDto.cs b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionCreationVerificationSmsDto.cs new file mode 100644 index 00000000..b0151e87 --- /dev/null +++ b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionCreationVerificationSmsDto.cs @@ -0,0 +1,12 @@ +using System; + +namespace CompanyManagment.App.Contracts.InstitutionContract; + +public record InstitutionCreationVerificationSmsDto +{ + public string Number{ get; set; } + public string FullName { get; set; } + public Guid InstitutionId { get; set; } + public long ContractingPartyId { get; set; } + public long InstitutionContractId { get; set; } +}; \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/InsuranceList/IInsuranceListApplication.cs b/CompanyManagment.App.Contracts/InsuranceList/IInsuranceListApplication.cs index 9d48019c..1a36dafb 100644 --- a/CompanyManagment.App.Contracts/InsuranceList/IInsuranceListApplication.cs +++ b/CompanyManagment.App.Contracts/InsuranceList/IInsuranceListApplication.cs @@ -90,8 +90,27 @@ public interface IInsuranceListApplication Task GetInsuranceOperationDetails(long id); Task GetTabCounts(InsuranceListSearchModel searchModel); + Task> GetInsuranceClientList(InsuranceClientSearchModel searchModel); + #endregion Task> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel); +} + +public class InsuranceClientSearchModel:PaginationRequest +{ + public int Year { get; set; } + public int Month { get; set; } + public string Sorting { get; set; } +} +public class InsuranceClientListViewModel +{ + public long Id { get; set; } + public string Year { get; set; } + public string Month { get; set; } + public long WorkShopId { get; set; } + public int YearInt { get; set; } + public string MonthName { get; set; } + public int MonthInt { get; set; } } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/RollCallEmployee/IRollCallEmployeeApplication.cs b/CompanyManagment.App.Contracts/RollCallEmployee/IRollCallEmployeeApplication.cs index b736b0bc..8691b2f1 100644 --- a/CompanyManagment.App.Contracts/RollCallEmployee/IRollCallEmployeeApplication.cs +++ b/CompanyManagment.App.Contracts/RollCallEmployee/IRollCallEmployeeApplication.cs @@ -1,6 +1,7 @@ using _0_Framework.Application; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace CompanyManagment.App.Contracts.RollCallEmployee; diff --git a/CompanyManagment.Application/EmployeeAplication.cs b/CompanyManagment.Application/EmployeeAplication.cs index 5d10be05..5323a5ed 100644 --- a/CompanyManagment.Application/EmployeeAplication.cs +++ b/CompanyManagment.Application/EmployeeAplication.cs @@ -1263,7 +1263,7 @@ public class EmployeeAplication : RepositoryBase, IEmployeeAppli System.IO.File.WriteAllBytes(filePath, bytes); } public async Task> - ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode, string birthDate, long workshopId) + ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode, string birthDate,bool authorizedCanceled, long workshopId) { var op = new OperationResult(); @@ -1279,65 +1279,25 @@ public class EmployeeAplication : RepositoryBase, IEmployeeAppli var employee = _EmployeeRepository.GetByNationalCodeIgnoreQueryFilter(nationalCode); - if (employee == null) + if (employee == null && !authorizedCanceled) { var personalInfo = await _uidService.GetPersonalInfo(nationalCode, birthDate); - - if (personalInfo.ResponseContext.Status.Code == 14) + if (personalInfo != null) { - return op.Failed("سامانه احراز هویت در دسترس نمیباشد لطفا اطلاعات پرسنل را به صورت دستی وارد کنید", new EmployeeByNationalCodeInWorkshopViewModel() { AuthorizedCanceled = true }); - } - if (personalInfo.ResponseContext.Status.Code != 0) - { - return op.Failed("کد ملی و تاریخ تولد با هم همخانی ندارند"); - } + if (personalInfo.ResponseContext.Status.Code == 14) + { + return op.Failed("سامانه احراز هویت در دسترس نمیباشد لطفا اطلاعات پرسنل را به صورت دستی وارد کنید", new EmployeeByNationalCodeInWorkshopViewModel() { AuthorizedCanceled = true }); + } + if (personalInfo.ResponseContext.Status.Code != 0) + { + return op.Failed("کد ملی و تاریخ تولد با هم همخانی ندارند"); + } - var basicInfo = personalInfo.BasicInformation; - var identityInfo = personalInfo.IdentificationInformation; - DateTime apiBirthDate = identityInfo.BirthDate.ToGeorgianDateTime(); + var basicInfo = personalInfo.BasicInformation; + var identityInfo = personalInfo.IdentificationInformation; + DateTime apiBirthDate = identityInfo.BirthDate.ToGeorgianDateTime(); - var dateOfIssue = new DateTime(1922, 1, 1); - - var gender = basicInfo.GenderEnum switch - { - Gender.Female => "زن", - Gender.Male => "مرد", - _ => throw new AggregateException() - }; - - var idNumber = identityInfo.ShenasnamehNumber == "0" ? identityInfo.NationalId : identityInfo.ShenasnamehNumber; - - var newEmployee = new Employee(basicInfo.FirstName, basicInfo.LastName, basicInfo.FatherName, apiBirthDate, - dateOfIssue, null, identityInfo.NationalId, idNumber, gender, "ایرانی", identityInfo.ShenasnameSerial, identityInfo.ShenasnameSeri); - newEmployee.Authorized(); - await _EmployeeRepository.CreateAsync(newEmployee); - await _EmployeeRepository.SaveChangesAsync(); - - return op.Succcedded(new EmployeeByNationalCodeInWorkshopViewModel() - { - EmployeeId = newEmployee.id, - EmployeeFName = newEmployee.FName, - Gender = newEmployee.Gender, - Nationality = newEmployee.Nationality, - EmployeeLName = newEmployee.LName - }); - } - - if (_leftWorkTempRepository.ExistsIgnoreQueryFilter(x => - x.EmployeeId == employee.id && x.WorkshopId == workshopId && x.LeftWorkType == LeftWorkTempType.StartWork)) - { - return op.Failed("این پرسنل در کارگاه شما قبلا افزوده شده است و در انتظار تایید میباشد"); - } - - if (employee.IsAuthorized == false) - { - var personalInfoResponse = await _uidService.GetPersonalInfo(nationalCode, birthDate); - - if (personalInfoResponse.ResponseContext.Status.Code == 0) - { - var basicInfo = personalInfoResponse.BasicInformation; - var identityInfo = personalInfoResponse.IdentificationInformation; - var apiBirthDate = identityInfo.BirthDate.ToGeorgianDateTime(); + var dateOfIssue = new DateTime(1922, 1, 1); var gender = basicInfo.GenderEnum switch { @@ -1348,31 +1308,90 @@ public class EmployeeAplication : RepositoryBase, IEmployeeAppli var idNumber = identityInfo.ShenasnamehNumber == "0" ? identityInfo.NationalId : identityInfo.ShenasnamehNumber; - - employee.Edit(basicInfo.FirstName, basicInfo.LastName, basicInfo.FatherName, apiBirthDate, - employee.DateOfIssue, employee.PlaceOfIssue, identityInfo.NationalId, idNumber, - gender, "ایرانی", employee.Phone, employee.Address, employee.State, employee.City, - employee.MaritalStatus, employee.MilitaryService, employee.LevelOfEducation, - employee.FieldOfStudy, employee.BankCardNumber, employee.BankBranch, employee.InsuranceCode, employee.InsuranceHistoryByYear, - employee.InsuranceHistoryByMonth, employee.NumberOfChildren, - employee.OfficePhone, employee.MclsUserName, employee.MclsPassword, - employee.EserviceUserName, employee.EservicePassword, employee.TaxOfficeUserName, - employee.TaxOfficepassword, employee.SanaUserName, employee.SanaPassword); - - employee.Authorized(); - + var newEmployee = new Employee(basicInfo.FirstName, basicInfo.LastName, basicInfo.FatherName, apiBirthDate, + dateOfIssue, null, identityInfo.NationalId, idNumber, gender, "ایرانی", identityInfo.ShenasnameSerial, identityInfo.ShenasnameSeri); + newEmployee.Authorized(); + await _EmployeeRepository.CreateAsync(newEmployee); await _EmployeeRepository.SaveChangesAsync(); + return op.Succcedded(new EmployeeByNationalCodeInWorkshopViewModel() + { + EmployeeId = newEmployee.id, + EmployeeFName = newEmployee.FName, + Gender = newEmployee.Gender, + Nationality = newEmployee.Nationality, + EmployeeLName = newEmployee.LName + }); } else + { + return op.Failed("سامانه احراز هویت در دسترس نمیباشد لطفا اطلاعات پرسنل را به صورت دستی وارد کنید", new EmployeeByNationalCodeInWorkshopViewModel() { AuthorizedCanceled = true }); + } + + + + + } + else if (employee == null && authorizedCanceled) + { + return op.Succcedded(new EmployeeByNationalCodeInWorkshopViewModel()); + } + + if (_leftWorkTempRepository.ExistsIgnoreQueryFilter(x => + x.EmployeeId == employee.id && x.WorkshopId == workshopId && x.LeftWorkType == LeftWorkTempType.StartWork)) + { + return op.Failed("این پرسنل در کارگاه شما قبلا افزوده شده است و در انتظار تایید میباشد"); + } + + var personalInfoResponse = await _uidService.GetPersonalInfo(nationalCode, birthDate); + if (personalInfoResponse != null) + { + if (employee.IsAuthorized == false) + { + + + if (personalInfoResponse.ResponseContext.Status.Code == 0) + { + var basicInfo = personalInfoResponse.BasicInformation; + var identityInfo = personalInfoResponse.IdentificationInformation; + var apiBirthDate = identityInfo.BirthDate.ToGeorgianDateTime(); + + var gender = basicInfo.GenderEnum switch + { + Gender.Female => "زن", + Gender.Male => "مرد", + _ => throw new AggregateException() + }; + + var idNumber = identityInfo.ShenasnamehNumber == "0" ? identityInfo.NationalId : identityInfo.ShenasnamehNumber; + + + employee.Edit(basicInfo.FirstName, basicInfo.LastName, basicInfo.FatherName, apiBirthDate, + employee.DateOfIssue, employee.PlaceOfIssue, identityInfo.NationalId, idNumber, + gender, "ایرانی", employee.Phone, employee.Address, employee.State, employee.City, + employee.MaritalStatus, employee.MilitaryService, employee.LevelOfEducation, + employee.FieldOfStudy, employee.BankCardNumber, employee.BankBranch, employee.InsuranceCode, employee.InsuranceHistoryByYear, + employee.InsuranceHistoryByMonth, employee.NumberOfChildren, + employee.OfficePhone, employee.MclsUserName, employee.MclsPassword, + employee.EserviceUserName, employee.EservicePassword, employee.TaxOfficeUserName, + employee.TaxOfficepassword, employee.SanaUserName, employee.SanaPassword); + + employee.Authorized(); + + await _EmployeeRepository.SaveChangesAsync(); + + } + else + { + return op.Failed("کد ملی با تاریخ تولد وارد شده مطابقت ندارد"); + } + } + else if (employee.DateOfBirth.ToFarsi() != birthDate || employee.NationalCode != nationalCode) { return op.Failed("کد ملی با تاریخ تولد وارد شده مطابقت ندارد"); } } - else if (employee.DateOfBirth.ToFarsi() != birthDate || employee.NationalCode != nationalCode) - { - return op.Failed("کد ملی با تاریخ تولد وارد شده مطابقت ندارد"); - } + var leftWorkViewModel = _leftWorkRepository.GetLastLeftWorkByEmployeeIdAndWorkshopId(workshopId, employee.id); if (leftWorkViewModel == null) diff --git a/CompanyManagment.Application/InsuranceListApplication.cs b/CompanyManagment.Application/InsuranceListApplication.cs index 2cac4299..5a3c5fb0 100644 --- a/CompanyManagment.Application/InsuranceListApplication.cs +++ b/CompanyManagment.Application/InsuranceListApplication.cs @@ -2371,6 +2371,11 @@ public class InsuranceListApplication : IInsuranceListApplication return _insuranceListRepositpry.GetTabCounts(searchModel); } + public async Task> GetInsuranceClientList(InsuranceClientSearchModel searchModel) + { + return await _insuranceListRepositpry.GetInsuranceClientList(searchModel); + } + public async Task> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel) { return await _insuranceListRepositpry.GetNotCreatedWorkshop(searchModel); diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 3b7357c4..d3641a20 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -384,6 +384,7 @@ public class RollCallApplication : IRollCallApplication var workshopSettings = _customizeWorkshopSettingsRepository.GetBy(command.WorkshopId); + var employeeSettings = _customizeWorkshopEmployeeSettingsRepository.GetByEmployeeIdAndWorkshopIdIncludeGroupSettings( command.WorkshopId, command.EmployeeId)?.WorkshopShiftStatus; diff --git a/CompanyManagment.Application/RollCallEmployeeApplication.cs b/CompanyManagment.Application/RollCallEmployeeApplication.cs index 9f4630cd..134807e2 100644 --- a/CompanyManagment.Application/RollCallEmployeeApplication.cs +++ b/CompanyManagment.Application/RollCallEmployeeApplication.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Transactions; +using _0_Framework.Application.FaceEmbedding; using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace CompanyManagment.Application; @@ -23,7 +24,9 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication private readonly ILeftWorkRepository _leftWorkRepository; private readonly IRollCallEmployeeStatusRepository _rollCallEmployeeStatusRepository; private readonly IWebHostEnvironment _webHostEnvironment; - public RollCallEmployeeApplication(IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ILeftWorkRepository leftWorkRepository, IRollCallEmployeeStatusRepository rollCallEmployeeStatusRepository, IWebHostEnvironment webHostEnvironment) + private readonly IFaceEmbeddingService _faceEmbeddingService; + + public RollCallEmployeeApplication(IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ILeftWorkRepository leftWorkRepository, IRollCallEmployeeStatusRepository rollCallEmployeeStatusRepository, IWebHostEnvironment webHostEnvironment, IFaceEmbeddingService faceEmbeddingService) { _rollCallEmployeeRepository = rollCallEmployeeRepository; _employeeRepository = employeeRepository; @@ -31,6 +34,7 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication _leftWorkRepository = leftWorkRepository; _rollCallEmployeeStatusRepository = rollCallEmployeeStatusRepository; _webHostEnvironment = webHostEnvironment; + _faceEmbeddingService = faceEmbeddingService; } public OperationResult Create(CreateRollCallEmployee command) @@ -213,9 +217,18 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication if (entity.IsActiveString != "true") return result.Failed("امکان تغییر نام برای کارمند غیر فعال وجود ندارد"); - + var transaction = _rollCallEmployeeRepository.BeginTransactionAsync().GetAwaiter().GetResult(); + entity.ChangeName(fName, lName); _rollCallEmployeeRepository.SaveChanges(); + + var embeddingRes =_faceEmbeddingService + .UpdateEmbeddingFullNameAsync(entity.EmployeeId, entity.WorkshopId, fullName) + .GetAwaiter().GetResult(); + if (!embeddingRes.IsSuccedded) + return result.Failed("خطا در به روز رسانی نام در سیستم تشخیص چهره: " + embeddingRes.Message); + + transaction.Commit(); return result.Succcedded(); } #endregion diff --git a/CompanyManagment.EFCore/Repository/CheckoutRepository.cs b/CompanyManagment.EFCore/Repository/CheckoutRepository.cs index cb843e5a..a78ff18e 100644 --- a/CompanyManagment.EFCore/Repository/CheckoutRepository.cs +++ b/CompanyManagment.EFCore/Repository/CheckoutRepository.cs @@ -64,7 +64,7 @@ public class CheckoutRepository : RepositoryBase, ICheckoutRepos } /// - /// چیک میکند که آیا پرسنل در سال و ماه درخواستی در این کارگاه فیش حقوقی دارد یا خیر + /// چک میکند که آیا پرسنل در سال و ماه درخواستی در این کارگاه فیش حقوقی دارد یا خیر /// /// /// @@ -74,12 +74,21 @@ public class CheckoutRepository : RepositoryBase, ICheckoutRepos public (bool hasChekout, double FamilyAlloance, double OverTimePay, double RotatingShift, double Nightwork, double Fridaywork, double YraesPay) HasCheckout(long workshopId, long employeId, string year, string month) { var farisMonthName = Tools.ToFarsiMonthByNumber(month); - + var res = _context.CheckoutSet.FirstOrDefault(x => x.WorkshopId == workshopId && x.EmployeeId == employeId && x.Year == year && x.Month == farisMonthName && x.IsActiveString == "true"); if (res == null) - return (false, 0, 0,0,0,0,0); + { + var checkLeftDate = ($"{year}/{month}/01").ToGeorgianDateTime(); + var hasLeftwork = _context.LeftWorkList.Any(x => + x.EmployeeId == employeId && x.WorkshopId == workshopId && x.LeftWorkDate == checkLeftDate); + if(hasLeftwork) + return (true, 0, 0, 0, 0, 0, 0); + + return (false, 0, 0, 0, 0, 0, 0); + } + return (true, res.FamilyAllowance, res.OvertimePay, res.ShiftPay, res.NightworkPay, res.FridayPay,res.YearsPay); } diff --git a/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs b/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs index 7635c7e9..1cffdc1d 100644 --- a/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs +++ b/CompanyManagment.EFCore/Repository/EmployeeDocumentsRepository.cs @@ -1194,41 +1194,99 @@ public class EmployeeDocumentsRepository : RepositoryBase(); } + // Step 1: Get employee client temps in memory + var employeeClientTempData = await _companyContext.EmployeeClientTemps + .Where(x => workshops.Contains(x.WorkshopId)) + .Select(x => new { x.WorkshopId, x.EmployeeId }) + .ToListAsync(); + // Step 2: Get employee documents with simplified filter + var employeeDocuments = await _companyContext.EmployeeDocuments + .Where(x => workshops.Contains(x.WorkshopId) && !x.IsConfirmed && !x.IsSentToChecker) + .Select(x => new + { + x.id, + x.WorkshopId, + x.EmployeeId, + x.IsConfirmed, + x.IsSentToChecker, + WorkshopName = x.Workshop.WorkshopName + }) + .ToListAsync(); - var employeeClientTemp = _companyContext.EmployeeClientTemps.Where(x => workshops.Contains(x.WorkshopId)); + var filteredDocuments = employeeDocuments + .Where(x => employeeClientTempData.Any(temp => + temp.WorkshopId == x.WorkshopId && temp.EmployeeId == x.EmployeeId)) + .ToList(); + var groupedByWorkshop = filteredDocuments + .GroupBy(x => x.WorkshopId) + .Select(g => new + { + WorkshopId = g.Key, + WorkshopName = g.First().WorkshopName, + Count = g.Count() + }) + .ToList(); - var query = _companyContext.EmployeeDocuments - .Where(x => workshops.Contains(x.WorkshopId) && - employeeClientTemp.Any(temp => x.EmployeeId == temp.EmployeeId && temp.WorkshopId == x.WorkshopId) && x.IsConfirmed == false &&x.IsSentToChecker == false) - .Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection) - .GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel() - { - WorkshopId = x.Key, - WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopFullName, - EmployeesWithoutDocumentCount = x.Count() - }); + // Step 5: Get workshop employers for the filtered workshops + var workshopIds = groupedByWorkshop.Select(x => x.WorkshopId).ToList(); + var workshopEmployers = await _companyContext.WorkshopEmployers + .Where(x => workshopIds.Contains(x.WorkshopId)) + .Include(x => x.Employer) + .GroupBy(x => x.WorkshopId) + .Select(g => g.FirstOrDefault()) + .ToListAsync(); + + // Step 6: Build result + var res = groupedByWorkshop + .Select(x => new WorkshopWithEmployeeDocumentsViewModel() + { + WorkshopId = x.WorkshopId, + WorkshopFullName = x.WorkshopName, + EmployeesWithoutDocumentCount = x.Count, + EmployerName = workshopEmployers + .FirstOrDefault(y => y.WorkshopId == x.WorkshopId)? + .Employer?.FullName + }) + .Where(x => x.EmployeesWithoutDocumentCount > 0) + .OrderByDescending(x => x.EmployeesWithoutDocumentCount) + .ToList(); + + return res; + + //var employeeClientTemp = _companyContext.EmployeeClientTemps.Where(x => workshops.Contains(x.WorkshopId)); + + // var query = _companyContext.EmployeeDocuments + // .Where(x => workshops.Contains(x.WorkshopId) && + // employeeClientTemp.Any(temp => x.EmployeeId == temp.EmployeeId && temp.WorkshopId == x.WorkshopId) && x.IsConfirmed == false &&x.IsSentToChecker == false) + // .Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection) + // .GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel() + // { + // WorkshopId = x.Key, + // WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopFullName, + // EmployeesWithoutDocumentCount = x.Count() + // }); - var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer) - .Where(x => query.Any(y => y.WorkshopId == x.WorkshopId)) - .GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync(); + // var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer) + // .Where(x => query.Any(y => y.WorkshopId == x.WorkshopId)) + // .GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync(); - var result = await query.ToListAsync(); + // var result = await query.ToListAsync(); - result.ForEach(x => - { - var employer = workshopEmployers.FirstOrDefault(y => y.WorkshopId == x.WorkshopId)?.Employer; - x.EmployerName = employer?.FullName; + // result.ForEach(x => + // { + // var employer = workshopEmployers.FirstOrDefault(y => y.WorkshopId == x.WorkshopId)?.Employer; + // x.EmployerName = employer?.FullName; - //x.SubmittedItems.ForEach(y=>y.PicturePath= medias.FirstOrDefault(z=>z.id == y.MediaId)?.Path ?? ""); - }); + // //x.SubmittedItems.ForEach(y=>y.PicturePath= medias.FirstOrDefault(z=>z.id == y.MediaId)?.Path ?? ""); + // }); - return result.Where(x => x.EmployeesWithoutDocumentCount > 0).OrderByDescending(x => x.EmployeesWithoutDocumentCount).ToList(); + // return result.Where(x => x.EmployeesWithoutDocumentCount > 0).OrderByDescending(x => x.EmployeesWithoutDocumentCount).ToList(); } public async Task> GetCreatedEmployeesDocumentByWorkshopIdForAdmin(long workshopId) @@ -1347,33 +1405,37 @@ public class EmployeeDocumentsRepository : RepositoryBase workshops.Contains(x.WorkshopId)) - .Include(x => x.Employer).Select(x => x.Employer.ContractingPartyId).Distinct(); + .Include(x => x.Employer).Select(x => x.Employer.ContractingPartyId).Distinct().ToList(); var accountIds = await _companyContext.ContractingPartyAccounts .Where(x => contractingPartyIds.Contains(x.PersonalContractingPartyId)).Select(x => x.AccountId) .ToListAsync(); - var query = _companyContext.EmployeeDocuments - .Where(x => workshops.Contains(x.WorkshopId) && - (allActiveEmployees.Any(y => y.WorkshopId == x.WorkshopId && y.EmployeeId == x.EmployeeId))) + var query =await _companyContext.EmployeeDocuments + .Where(x => workshops.Contains(x.WorkshopId)) .Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection) .Where(x => x.IsSentToChecker == false && x.HasRejectedItems && x.EmployeeDocumentItemCollection.Any(i => i.DocumentStatus == DocumentStatus.Rejected && accountIds.Contains(i.UploaderId))) .GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel() { WorkshopId = x.Key, WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopName, - EmployeesWithoutDocumentCount = x.Count() - }); + EmployeesWithoutDocumentCount = x.Count(), + EmployeeId = x.First().EmployeeId + }).ToListAsync(); + query = query.Where(x => + (allActiveEmployees.Any(y => y.WorkshopId == x.WorkshopId && y.EmployeeId == x.EmployeeId))).ToList(); + + var resWorkshopIds = query.Select(x => x.WorkshopId).ToList(); var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer) - .Where(x => query.Any(y => y.WorkshopId == x.WorkshopId)) + .Where(x => resWorkshopIds.Contains(x.WorkshopId)) .GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync(); - var result = await query.ToListAsync(); + var result = query; result.ForEach(x => diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 3940fc48..da0a8632 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Diagnostics.Metrics; -using System.Drawing; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using _0_Framework.Application; +using _0_Framework.Application; using _0_Framework.Application.Enums; using _0_Framework.Application.Sms; using _0_Framework.Exceptions; @@ -38,6 +27,7 @@ using CompanyManagment.App.Contracts.Law; using CompanyManagment.App.Contracts.TemporaryClientRegistration; using CompanyManagment.App.Contracts.Workshop; using CompanyManagment.App.Contracts.WorkshopPlan; +using CompanyManagment.EFCore.Migrations; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; @@ -47,10 +37,23 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using MongoDB.Driver; using OfficeOpenXml.Packaging.Ionic.Zip; using PersianTools.Core; -using static System.Runtime.InteropServices.JavaScript.JSType; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.Metrics; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; -using SmsResult = CompanyManagment.EFCore.Migrations.SmsResult; +using static System.Runtime.InteropServices.JavaScript.JSType; +using ContractingPartyAccount = Company.Domain.ContractingPartyAccountAgg.ContractingPartyAccount; +using FinancialStatment = Company.Domain.FinancialStatmentAgg.FinancialStatment; using String = System.String; +using Workshop = Company.Domain.WorkshopAgg.Workshop; namespace CompanyManagment.EFCore.Repository; @@ -102,69 +105,69 @@ public class InstitutionContractRepository : RepositoryBase new EditInstitutionContract() - { - Id = x.id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - RepresentativeId = x.RepresentativeId, - ContractingPartyId = x.ContractingPartyId, - ContractDateFa = x.ContractDateFa, - State = x.State, - City = x.City, - Address = x.Address, - Description = x.Description, - WorkshopManualCount = x.WorkshopManualCount, - EmployeeManualCount = x.EmployeeManualCount, - ContractAmountString = x.ContractAmount.ToMoney(), - ContractAmount = x.ContractAmount, - DailyCompenseationString = x.DailyCompenseation.ToMoney(), - ObligationString = x.Obligation.ToMoney(), - TotalAmountString = x.TotalAmount.ToMoney(), - ExtensionNo = x.ExtensionNo, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature, - HasValueAddedTax = x.HasValueAddedTax, - ValueAddedTax = x.ValueAddedTax, - }) + { + Id = x.id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + RepresentativeId = x.RepresentativeId, + ContractingPartyId = x.ContractingPartyId, + ContractDateFa = x.ContractDateFa, + State = x.State, + City = x.City, + Address = x.Address, + Description = x.Description, + WorkshopManualCount = x.WorkshopManualCount, + EmployeeManualCount = x.EmployeeManualCount, + ContractAmountString = x.ContractAmount.ToMoney(), + ContractAmount = x.ContractAmount, + DailyCompenseationString = x.DailyCompenseation.ToMoney(), + ObligationString = x.Obligation.ToMoney(), + TotalAmountString = x.TotalAmount.ToMoney(), + ExtensionNo = x.ExtensionNo, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature, + HasValueAddedTax = x.HasValueAddedTax, + ValueAddedTax = x.ValueAddedTax, + }) .FirstOrDefault(x => x.Id == id); } public EditInstitutionContract GetFirstContract(long contractingPartyId, string typeOfContract) { return _context.InstitutionContractSet.Select(x => new EditInstitutionContract() - { - Id = x.id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - RepresentativeId = x.RepresentativeId, - ContractingPartyId = x.ContractingPartyId, - ContractDateFa = x.ContractDateFa, - State = x.State, - City = x.City, - Address = x.Address, - Description = x.Description, - WorkshopManualCount = x.WorkshopManualCount, - EmployeeManualCount = x.EmployeeManualCount, - ContractAmountString = x.ContractAmount.ToMoney(), - DailyCompenseationString = x.DailyCompenseation.ToMoney(), - ObligationString = x.Obligation.ToMoney(), - TotalAmountString = x.TotalAmount.ToMoney(), - ExtensionNo = x.ExtensionNo, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature - }) + { + Id = x.id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + RepresentativeId = x.RepresentativeId, + ContractingPartyId = x.ContractingPartyId, + ContractDateFa = x.ContractDateFa, + State = x.State, + City = x.City, + Address = x.Address, + Description = x.Description, + WorkshopManualCount = x.WorkshopManualCount, + EmployeeManualCount = x.EmployeeManualCount, + ContractAmountString = x.ContractAmount.ToMoney(), + DailyCompenseationString = x.DailyCompenseation.ToMoney(), + ObligationString = x.Obligation.ToMoney(), + TotalAmountString = x.TotalAmount.ToMoney(), + ExtensionNo = x.ExtensionNo, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature + }) .Where(x => x.ContractingPartyId == contractingPartyId && x.TypeOfContract == typeOfContract) .OrderBy(x => x.ExtensionNo).FirstOrDefault(); } @@ -582,40 +585,40 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractViewModel() - { - Id = x.Id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeId = x.RepresentativeId, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - ContractingPartyId = x.ContractingPartyId, - ContractAmount = x.ContractAmount, - TotalAmount = x.TotalAmount, - SearchAmount = x.SearchAmount, - IsActiveString = x.IsActiveString, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature, - ExpireColor = x.ExpireColor, - IsExpier = x.IsExpier, - BalanceDouble = x.BalanceDouble, - BalanceStr = x.BalanceStr, - EmployerViewModels = x.EmployerViewModels, - EmployerNo = x.EmployerNo, - EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), - WorkshopViewModels = x.WorkshopViewModels, - WorkshopCount = x.WorkshopCount, - IsContractingPartyBlock = x.IsContractingPartyBlock, - BlockTimes = x.BlockTimes, - EmployeeCount = + { + Id = x.Id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeId = x.RepresentativeId, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + ContractingPartyId = x.ContractingPartyId, + ContractAmount = x.ContractAmount, + TotalAmount = x.TotalAmount, + SearchAmount = x.SearchAmount, + IsActiveString = x.IsActiveString, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature, + ExpireColor = x.ExpireColor, + IsExpier = x.IsExpier, + BalanceDouble = x.BalanceDouble, + BalanceStr = x.BalanceStr, + EmployerViewModels = x.EmployerViewModels, + EmployerNo = x.EmployerNo, + EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), + WorkshopViewModels = x.WorkshopViewModels, + WorkshopCount = x.WorkshopCount, + IsContractingPartyBlock = x.IsContractingPartyBlock, + BlockTimes = x.BlockTimes, + EmployeeCount = ((x.WorkshopViewModels.Sum(w => w.LeftWorkIds.Count)) + (x.WorkshopViewModels.Sum(w => w.InsuranceLeftWorkIds.Count(c => !w.LeftWorkIds.Contains(c))))).ToString(), - ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, - }).OrderBy(x => x.WorkshopCount != "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) + ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, + }).OrderBy(x => x.WorkshopCount != "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.WorkshopCount == "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.IsExpier == "true") .ThenBy(x => x.ExpireColor == "purple") @@ -640,17 +643,17 @@ public class InstitutionContractRepository : RepositoryBase x.id == id); - + var prevInstitutionContracts = _context.InstitutionContractSet .Where(x => x.ContractingPartyId == institutionContarct.ContractingPartyId) .OrderByDescending(x => x.ContractEndGr).Skip(1).FirstOrDefault(); - + var transaction = _context.Database.BeginTransaction(); - + var contactInfo = _context.InstitutionContractContactInfos .Where(x => x.InstitutionContractId == id) .ToList(); - + if (contactInfo.Count > 0) { foreach (var item in contactInfo) @@ -673,20 +676,20 @@ public class InstitutionContractRepository : RepositoryBase x.FinancialTransactionList) - .FirstOrDefault(x=>x.ContractingPartyId == institutionContarct.ContractingPartyId); + .FirstOrDefault(x => x.ContractingPartyId == institutionContarct.ContractingPartyId); if (financialStatement != null) { - - var sumDebtor = financialStatement.FinancialTransactionList - .Sum(x => x.Deptor); + + var sumDebtor = financialStatement.FinancialTransactionList + .Sum(x => x.Deptor); var sumCreditor = financialStatement.FinancialTransactionList .Sum(x => x.Creditor); var balance = sumDebtor - sumCreditor; - if (balance>0 && prevInstitutionContracts.ContractEndGr 0 && prevInstitutionContracts.ContractEndGr < now) + { + prevInstitutionContracts.DeActiveBlue(); + _context.SaveChanges(); + } } } @@ -3822,19 +3825,19 @@ public class InstitutionContractRepository : RepositoryBase(); var institutionContracts = await _context.InstitutionContractSet.Select(x => new InstitutionContractViewModel - { - Id = x.id, - ContractingPartyId = x.ContractingPartyId, - ContractingPartyName = x.ContractingPartyName, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - IsActiveString = x.IsActiveString, - ContractAmountDouble = x.ContractAmount, - OfficialCompany = x.OfficialCompany - }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && - x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) + { + Id = x.id, + ContractingPartyId = x.ContractingPartyId, + ContractingPartyName = x.ContractingPartyName, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + IsActiveString = x.IsActiveString, + ContractAmountDouble = x.ContractAmount, + OfficialCompany = x.OfficialCompany + }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && + x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) .ToListAsync(); @@ -3928,9 +3931,12 @@ public class InstitutionContractRepository : RepositoryBase @@ -4507,6 +4556,88 @@ public class InstitutionContractRepository : RepositoryBase x.ContractingPartyId == contractingPartyId); } + #endregion + + + #region InstitutionContractConfirm + /// + /// ارسال پیامک یادآور تایید قراداد مالی + /// + /// + public async Task SendInstitutionContractConfirmSmsTask() + { + var now = DateTime.Now; + + + // تبدیل تاریخ میلادی به شمسی + var persianNow = now.ToFarsi(); + var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2)); + var dayOfMonth = int.Parse(persianNow.Substring(8, 2)); + var hour = now.Hour; + var minute = now.Minute; + var checkAnyToExecute = false; + + //اگر آخرین روز ماه باشد + //اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود + if (dayOfMonth == persianEndOfMonth) + { + checkAnyToExecute = await _context.SmsSettings + .AnyAsync(x => + x.DayOfMonth >= dayOfMonth && /// اگر بزرگتر یا مساوی رو جاری بود + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm && + x.IsActive + ); + } + else + { + checkAnyToExecute = await _context.SmsSettings + .AnyAsync(x => + x.DayOfMonth == dayOfMonth && + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm && + x.IsActive + ); + } + + + if (checkAnyToExecute) + { + //اجرای تسک + + //دریافت لیست قراداد های تایید نشده + var fromAmonthAgo = now.AddDays(-30); + var pendingContracts = await _context.InstitutionContractSet + .Where(x => x.CreationDate >= fromAmonthAgo && x.CreationDate.Date != now.Date && x.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify) + .Join(_context.PersonalContractingParties, + contract => contract.ContractingPartyId, + contractingParty => contractingParty.id, + (contract, contractingParty) => new { contract, contractingParty }).Select(x => new InstitutionCreationVerificationSmsDto + { + Number = x.contractingParty.Phone, + FullName = x.contractingParty.IsLegal == "حقیقی" ? $"{x.contractingParty.FName} {x.contractingParty.LName}" : $"{x.contractingParty.LName}", + ContractingPartyId = x.contract.ContractingPartyId, + InstitutionContractId = x.contract.id, + InstitutionId = x.contract.PublicId, + }).ToListAsync(); + + string typeOfSms = "یادآور تایید قرارداد مالی"; + foreach (var item in pendingContracts) + { + var sendResult = await _smsService.SendInstitutionCreationVerificationLink(item.Number, item.FullName, + item.InstitutionId, item.ContractingPartyId, item.InstitutionContractId, typeOfSms); + } + + Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute); + + } + + + } + + #endregion #endregion @@ -4550,7 +4681,7 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel - { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).Where(x => x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.ContractAmountDouble > 0) @@ -4594,7 +4725,7 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel - { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).ToListAsync(); diff --git a/CompanyManagment.EFCore/Repository/InsuranceListRepository.cs b/CompanyManagment.EFCore/Repository/InsuranceListRepository.cs index a2768060..da63d47b 100644 --- a/CompanyManagment.EFCore/Repository/InsuranceListRepository.cs +++ b/CompanyManagment.EFCore/Repository/InsuranceListRepository.cs @@ -1777,6 +1777,49 @@ public class InsuranceListRepository : RepositoryBase, IIns return res; } + public async Task> GetInsuranceClientList(InsuranceClientSearchModel searchModel) + { + var workshopId = _authHelper.GetWorkshopId(); + var query = _context.InsuranceListSet + .Select(x => new InsuranceClientListViewModel + { + Id = x.id, + WorkShopId = x.WorkshopId, + Year = x.Year, + YearInt = Convert.ToInt32(x.Year), + Month = x.Month, + MonthName = x.Month.ToFarsiMonthByNumber(), + MonthInt = Convert.ToInt32(x.Month), + }).Where(x => x.WorkShopId == workshopId); + + + if (searchModel.Year>0) + { + query = query.Where(x => x.YearInt == searchModel.Year); + } + if (searchModel.Month > 0) + { + query = query.Where(x => x.MonthInt == searchModel.Month); + } + + var res = new PagedResult + { + TotalCount = query.Count() + }; + query = searchModel.Sorting switch + { + "CreationDate-Max" => query.OrderByDescending(x => x.Id), + "CreationDate-Min" => query.OrderBy(x => x.Id), + "Month-Max" => query.OrderByDescending(x => x.MonthInt), + "Month-Min" => query.OrderBy(x => x.MonthInt), + "Year-Max" => query.OrderByDescending(x => x.YearInt), + "Year-Min" => query.OrderBy(x => x.YearInt), + _ => query.OrderByDescending(x => x.Id), + }; + res.List =await query.ApplyPagination(searchModel.PageIndex,searchModel.PageSize).ToListAsync(); + return res; + } + public async Task> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel) { if (string.IsNullOrEmpty(searchModel.Month) || string.IsNullOrEmpty(searchModel.Year)) diff --git a/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs b/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs index 4a781e52..904ce85f 100644 --- a/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs +++ b/CompanyManagment.EFCore/Repository/RollCallMandatoryRepository.cs @@ -1994,8 +1994,9 @@ public class RollCallMandatoryRepository : RepositoryBase, IRoll case "شنبه": w1 = 7; w2 = 14; - w3 = 28; - w4 = 31; + w3 = 21; + w4 = 28; + w5 = 31; break; case "یکشنبه": w1 = 6; @@ -2361,6 +2362,7 @@ public class RollCallMandatoryRepository : RepositoryBase, IRoll break; } } + } #endregion diff --git a/CompanyManagment.EFCore/Services/HolidayQueryService.cs b/CompanyManagment.EFCore/Services/HolidayQueryService.cs index 4b8aa51c..e8c2e4f3 100644 --- a/CompanyManagment.EFCore/Services/HolidayQueryService.cs +++ b/CompanyManagment.EFCore/Services/HolidayQueryService.cs @@ -1,14 +1,32 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using PersianTools.Core; using Shared.Contracts.Holidays; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; namespace CompanyManagment.EFCore.Services; public class HolidayQueryService : IHolidayQueryService { - public Task> GetHolidaysInDates(DateTime startDate, DateTime endDate) + private readonly CompanyContext _context; + + public HolidayQueryService(CompanyContext context) { - throw new NotImplementedException(); + _context = context; + } + + public async Task> GetHolidaysInDates(DateTime startDate, DateTime endDate) + { + return await _context.HolidayItems.Where(x => x.Holidaydate >= startDate && x.Holidaydate <= endDate).Select(x=> new HolidayDto() + { + Holidaydate = x.Holidaydate, + HolidayId = x.id, + HolidayYear = x.HolidayYear + }) + .ToListAsync(); + } } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Services/SmsService.cs b/CompanyManagment.EFCore/Services/SmsService.cs index 9a29b90b..55be5ff9 100644 --- a/CompanyManagment.EFCore/Services/SmsService.cs +++ b/CompanyManagment.EFCore/Services/SmsService.cs @@ -350,9 +350,12 @@ public class SmsService : ISmsService } - public async Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId) + public async Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms) { - var full = fullName; + typeOfSms = string.IsNullOrWhiteSpace(typeOfSms) ? "لینک تاییدیه ایجاد قرارداد مالی" : typeOfSms; + + + var full = fullName; var fullName1 = fullName; if (fullName.Length >= 25) { @@ -377,8 +380,9 @@ public class SmsService : ISmsService new("CODE1",firstPart), new("CODE2",secondPart) }); + - var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, "لینک تاییدیه ایجاد قرارداد مالی", + var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, typeOfSms, fullName, number, contractingPartyId, institutionContractId); await _smsResultRepository.CreateAsync(smsResult); await _smsResultRepository.SaveChangesAsync(); diff --git a/DadmehrGostar.sln b/DadmehrGostar.sln index f31d5bcb..342cf0ef 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -106,6 +106,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.I EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared.Contracts", "Shared.Contracts\Shared.Contracts.csproj", "{08B234B6-783B-44E9-9961-4F97EAD16308}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{F61F77F5-9B14-49CC-870B-1C61D2636586}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -275,6 +277,7 @@ Global {B57EB542-C028-4A77-9386-9DFF1E60FDCB} = {9D85672B-D48E-40B5-9804-0CE220E0E64C} {D2B4F1D7-6336-4B30-910C-219F4119303F} = {D74D1E3B-3BE3-47EE-9914-785A8AD536E5} {408281FE-615F-4CBE-BD95-2E86F5ACC6C3} = {C0AE9368-D4E7-450B-9713-929D319DE690} + {08B234B6-783B-44E9-9961-4F97EAD16308} = {F61F77F5-9B14-49CC-870B-1C61D2636586} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E6CFB3A7-A7C8-4E82-8F06-F750408F0BA9} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs index 3536ad0e..9b3fdcb8 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs @@ -185,7 +185,7 @@ public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandler> { - { TaskSectionStatus.ReadyToStart, new List { TaskSectionStatus.InProgress } }, - { TaskSectionStatus.InProgress, new List { TaskSectionStatus.Incomplete, TaskSectionStatus.Completed } }, - { TaskSectionStatus.Incomplete, new List { TaskSectionStatus.InProgress, TaskSectionStatus.Completed } }, - { TaskSectionStatus.Completed, new List { TaskSectionStatus.InProgress, TaskSectionStatus.Incomplete } }, // Can return to InProgress or Incomplete - { TaskSectionStatus.NotAssigned, new List { TaskSectionStatus.InProgress, TaskSectionStatus.ReadyToStart } } + { TaskSectionStatus.ReadyToStart, [TaskSectionStatus.InProgress] }, + { TaskSectionStatus.InProgress, [TaskSectionStatus.Incomplete, TaskSectionStatus.Completed] }, + { TaskSectionStatus.Incomplete, [TaskSectionStatus.InProgress, TaskSectionStatus.Completed] }, + { TaskSectionStatus.Completed, [TaskSectionStatus.InProgress, TaskSectionStatus.Incomplete] }, // Can return to InProgress or Incomplete + { TaskSectionStatus.NotAssigned, [TaskSectionStatus.InProgress, TaskSectionStatus.ReadyToStart] } }; if (!validTransitions.TryGetValue(currentStatus, out var allowedTargets)) diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs index 790e1f79..f81d63a9 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs @@ -8,6 +8,8 @@ public class CreateProjectCommandValidator:AbstractValidator x.Name) + .MaximumLength(25) + .WithMessage("نام نمیتواند بیشتر از 25 کاراکتر باشد") .NotEmpty() .NotNull() .WithMessage("نام نمیتواند خالی باشد"); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs index 3b1a7b1f..f6e9bafa 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs @@ -2,13 +2,14 @@ using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.Projects.DTOs; using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; using GozareshgirProgramManager.Domain.ProjectAgg.Entities; using GozareshgirProgramManager.Domain.ProjectAgg.Enums; using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; -public class SetTimeProjectCommandHandler:IBaseCommandHandler +public class SetTimeProjectCommandHandler : IBaseCommandHandler { private readonly IProjectRepository _projectRepository; private readonly IProjectPhaseRepository _projectPhaseRepository; @@ -16,7 +17,7 @@ public class SetTimeProjectCommandHandler:IBaseCommandHandler SetTimeForProject(SetTimeProjectCommand request, CancellationToken cancellationToken) + private async Task SetTimeForProject(SetTimeProjectCommand request, + CancellationToken cancellationToken) { var project = await _projectRepository.GetWithFullHierarchyAsync(request.Id); if (project == null) @@ -75,7 +76,8 @@ public class SetTimeProjectCommandHandler:IBaseCommandHandler SetTimeForProjectPhase(SetTimeProjectCommand request, CancellationToken cancellationToken) + private async Task SetTimeForProjectPhase(SetTimeProjectCommand request, + CancellationToken cancellationToken) { var phase = await _projectPhaseRepository.GetWithTasksAsync(request.Id); if (phase == null) @@ -103,13 +105,13 @@ public class SetTimeProjectCommandHandler:IBaseCommandHandler SetTimeForProjectTask(SetTimeProjectCommand request, CancellationToken cancellationToken) + private async Task SetTimeForProjectTask(SetTimeProjectCommand request, + CancellationToken cancellationToken) { var task = await _projectTaskRepository.GetWithSectionsAsync(request.Id); if (task == null) { return OperationResult.NotFound("تسک یافت نشد"); - return OperationResult.NotFound("�Ә ���� ���"); } long? addedByUserId = _userId; @@ -127,12 +129,17 @@ public class SetTimeProjectCommandHandler:IBaseCommandHandler x.SectionItems) .SetValidator(command => new SetTimeProjectSectionItemValidator()); + RuleFor(x => x.SectionItems) + .Must(sectionItems => sectionItems.Any(si => si.InitData?.Hours > 0)) + .WithMessage("حداقل یکی از بخش‌ها باید مقدار ساعت معتبری داشته باشد."); } } public class SetTimeProjectSectionItemValidator:AbstractValidator @@ -30,13 +34,14 @@ public class SetTimeProjectSectionItemValidator:AbstractValidatorx.AdditionalTime) - .SetValidator(new TimeDataValidator()); + .SetValidator(new AdditionalTimeDataValidator()); + } } -public class TimeDataValidator : AbstractValidator +public class AdditionalTimeDataValidator: AbstractValidator { - public TimeDataValidator() + public AdditionalTimeDataValidator() { RuleFor(x => x.Hours) .GreaterThanOrEqualTo(0) @@ -45,6 +50,13 @@ public class TimeDataValidator : AbstractValidator RuleFor(x=>x.Description) .MaximumLength(500) .WithMessage("توضیحات نمی‌تواند بیشتر از 500 کاراکتر باشد."); + } +} + +public class TimeDataValidator : AbstractValidator +{ + public TimeDataValidator() + { } } \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs index 523943aa..1815c2bc 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs @@ -132,91 +132,82 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler projects, CancellationToken cancellationToken) { + if (!projects.Any()) + return; + var projectIds = projects.Select(x => x.Id).ToList(); - - // تنها تسک‌ها sections دارند، بنابراین برای سطوح مختلف باید متفاوت عمل کنیم - List taskIds; - - switch (projects.FirstOrDefault()?.Level) + var hierarchyLevel = projects.First().Level; + + switch (hierarchyLevel) { case ProjectHierarchyLevel.Project: - // برای پروژه‌ها، باید تمام تسک‌های زیرمجموعه را پیدا کنیم - var phaseIds = await _context.ProjectPhases - .Where(ph => projectIds.Contains(ph.ProjectId)) - .Select(ph => ph.Id) - .ToListAsync(cancellationToken); - - taskIds = await _context.ProjectTasks - .Where(t => phaseIds.Contains(t.PhaseId)) - .Select(t => t.Id) - .ToListAsync(cancellationToken); + await SetSkillFlagsForProjects(projects, projectIds, cancellationToken); break; case ProjectHierarchyLevel.Phase: - // برای فازها، تمام تسک‌های آن فازها را پیدا کنیم - taskIds = await _context.ProjectTasks - .Where(t => projectIds.Contains(t.PhaseId)) - .Select(t => t.Id) - .ToListAsync(cancellationToken); + await SetSkillFlagsForPhases(projects, projectIds, cancellationToken); break; case ProjectHierarchyLevel.Task: - // برای تسک‌ها، خود آنها taskIds هستند - taskIds = projectIds; + await SetSkillFlagsForTasks(projects, projectIds, cancellationToken); break; - - default: - return; } + } - if (!taskIds.Any()) - return; - - var sections = await _context.TaskSections + private async Task SetSkillFlagsForProjects(List projects, List projectIds, CancellationToken cancellationToken) + { + var projectSections = await _context.ProjectSections .Include(x => x.Skill) - .Where(x => taskIds.Contains(x.TaskId)) + .Where(s => projectIds.Contains(s.ProjectId)) .ToListAsync(cancellationToken); + if (!projectSections.Any()) + return; + foreach (var project in projects) { - List relevantTaskIds; - - switch (project.Level) - { - case ProjectHierarchyLevel.Project: - // برای پروژه، تمام تسک‌های زیرمجموعه - var projectPhaseIds = await _context.ProjectPhases - .Where(ph => ph.ProjectId == project.Id) - .Select(ph => ph.Id) - .ToListAsync(cancellationToken); - - relevantTaskIds = await _context.ProjectTasks - .Where(t => projectPhaseIds.Contains(t.PhaseId)) - .Select(t => t.Id) - .ToListAsync(cancellationToken); - break; - - case ProjectHierarchyLevel.Phase: - // برای فاز، تمام تسک‌های آن فاز - relevantTaskIds = await _context.ProjectTasks - .Where(t => t.PhaseId == project.Id) - .Select(t => t.Id) - .ToListAsync(cancellationToken); - break; - - case ProjectHierarchyLevel.Task: - // برای تسک، خود آن - relevantTaskIds = new List { project.Id }; - break; - - default: - continue; - } - - var projectSections = sections.Where(x => relevantTaskIds.Contains(x.TaskId)).ToList(); - project.HasBackend = projectSections.Any(x => x.Skill.Name == "Backend"); - project.HasFront = projectSections.Any(x => x.Skill.Name == "Frontend"); - project.HasDesign = projectSections.Any(x => x.Skill.Name == "UI/UX Design"); + var sections = projectSections.Where(s => s.ProjectId == project.Id).ToList(); + project.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); + project.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); + project.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); + } + } + + private async Task SetSkillFlagsForPhases(List projects, List phaseIds, CancellationToken cancellationToken) + { + var phaseSections = await _context.PhaseSections + .Include(x => x.Skill) + .Where(s => phaseIds.Contains(s.PhaseId)) + .ToListAsync(cancellationToken); + + if (!phaseSections.Any()) + return; + + foreach (var phase in projects) + { + var sections = phaseSections.Where(s => s.PhaseId == phase.Id).ToList(); + phase.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); + phase.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); + phase.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); + } + } + + private async Task SetSkillFlagsForTasks(List projects, List taskIds, CancellationToken cancellationToken) + { + var taskSections = await _context.TaskSections + .Include(x => x.Skill) + .Where(s => taskIds.Contains(s.TaskId)) + .ToListAsync(cancellationToken); + + if (!taskSections.Any()) + return; + + foreach (var task in projects) + { + var sections = taskSections.Where(s => s.TaskId == task.Id).ToList(); + task.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); + task.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); + task.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); } } diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs new file mode 100644 index 00000000..467ed43e --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs @@ -0,0 +1,74 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardDetail; + +public record ProjectBoardDetailQuery(Guid SectionId) : IBaseQuery; + +public record ProjectBoardDetailResponse(List Users, string TotalTime); + +public record ProjectBoardDetailUserResponse +{ + public List Histories { get; set; } = new(); + public string UserFullName { get; set; } + public long UserId { get; set; } +} + +public class ProjectBoardDetailUserHistoryResponse +{ + public string Date { get; set; } + public string startTime { get; set; } + public string EndTime { get; set; } + public string TotalTime { get; set; } +} + +public class ProjectBoardDetailQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _programManagerDbContext; + + public ProjectBoardDetailQueryHandler(IProgramManagerDbContext programManagerDbContext) + { + _programManagerDbContext = programManagerDbContext; + } + + public async Task> Handle(ProjectBoardDetailQuery request, + CancellationToken cancellationToken) + { + var section = await _programManagerDbContext.TaskSections + .Include(x => x.Activities) + .FirstOrDefaultAsync(x => x.Id == request.SectionId, cancellationToken: cancellationToken); + + if (section == null) + return OperationResult.NotFound("بخش مورد نظر یافت نشد"); + + var userIds = section.Activities.Select(x => x.UserId).Distinct().ToList(); + + var usersDict = await _programManagerDbContext.Users + .Where(x => userIds.Contains(x.Id)) + .ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken); + + var totalTimeSpan = section.Activities + .Select(x => x.GetTimeSpent()) + .Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next)); + + var users = section.Activities.GroupBy(x => x.UserId).Select(x => + { + return new ProjectBoardDetailUserResponse() + { + UserId = x.Key, + UserFullName = usersDict[x.Key], + Histories = x.Select(h => new ProjectBoardDetailUserHistoryResponse() + { + Date = h.StartDate.ToFarsi(), + startTime = h.StartDate.ToString("HH:mm"), + EndTime = h.EndDate?.ToString("HH:mm") ?? "-", + TotalTime = h.GetTimeSpent().ToString(@"hh\:mm") + }).ToList() + }; + }).ToList(); + var response = new ProjectBoardDetailResponse(users, $"{(int)totalTimeSpan.TotalHours}:{totalTimeSpan.Minutes:D2}"); + return OperationResult.Success(response); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs index db180808..2d42152a 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs @@ -6,5 +6,5 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.Project public record ProjectBoardListQuery: IBaseQuery> { -} - + public TaskSectionStatus? Status { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs index 0edfdc0b..5a085060 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs @@ -1,6 +1,9 @@ +using GozareshgirProgramManager.Application._Common.Constants; using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query.Internal; namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; @@ -19,21 +22,35 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.CurrentAssignedUserId == currentUserId) + var queryable = _programManagerDbContext.TaskSections.AsNoTracking() .Where(x => x.InitialEstimatedHours > TimeSpan.Zero) .Include(x => x.Task) .ThenInclude(x => x.Phase) .ThenInclude(x => x.Project) .Include(x => x.Activities) - .Include(x => x.AdditionalTimes) - .ToListAsync(cancellationToken); + .Include(x => x.AdditionalTimes).AsQueryable(). + Include(x => x.Skill).AsQueryable(); + + if (!_authHelper.HasPermission(ProgramManagerPermissionCode.Board.ViewAllUsersProjects.Code)) + { + queryable = queryable.Where(x => x.CurrentAssignedUserId == currentUserId); + } + if (request.Status != null) + { + queryable = queryable.Where(x => x.Status == request.Status); + } + + var data = await queryable.ToListAsync(cancellationToken); var activityUserIds = data.SelectMany(x => x.Activities).Select(a => a.UserId).Distinct().ToList(); + var assignedUser = data.Select(x => x.CurrentAssignedUserId) + .Concat(data.Select(x => x.OriginalAssignedUserId)).ToList(); + var allUserIds = activityUserIds.Concat(assignedUser).Distinct().ToList(); var users = await _programManagerDbContext.Users.AsNoTracking() - .Where(x => activityUserIds.Contains(x.Id)) + .Where(x => allUserIds.Contains(x.Id)) .Select(x => new { x.Id, x.FullName }) .ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken); + var result = data.Select(x => { @@ -89,7 +106,11 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler a.TotalSeconds), Histories = mergedHistories - } + }, + OriginalUser = users.GetValueOrDefault(x.OriginalAssignedUserId, "ناشناس"), + AssignedUser = x.CurrentAssignedUserId == x.OriginalAssignedUserId ? null + : users.GetValueOrDefault(x.CurrentAssignedUserId, "ناشناس"), + SkillName = x.Skill?.Name??"-", }; }).ToList(); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs index 83421e89..ab38750e 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs @@ -10,6 +10,10 @@ public class ProjectBoardListResponse public string TaskName { get; set; } public ProjectProgressDto Progress { get; set; } public TaskSectionStatus SectionStatus { get; set; } + public string? AssignedUser { get; set; } + public string OriginalUser { get; set; } + public string SkillName { get; set; } + } public class ProjectProgressDto { diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs new file mode 100644 index 00000000..bd4230c3 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs @@ -0,0 +1,270 @@ +using System.Reflection; + +namespace GozareshgirProgramManager.Application._Common.Constants; + +public static class ProgramManagerPermissionCode +{ + /// + /// دسترسی به بخش مدیریت پروژه + /// + public const int Code = 99; + + #region DeveloperUsers[تب کاربران برنامه نویسی] + /// + /// تب کاربران برنامه نویسی + /// + public static class DeveloperUsers + { + public const int Code = 9900; + + /// + /// تب تعیین حقوق + /// + public static class SalaryDetermination + { + public const int Code = 990001; + + /// + /// تعیین زمان + /// + public const int WorkingHoursDetermination = 990001; + } + + /// + /// تب وضعیت کارکرد + /// + public static class WorkingStatus + { + public const int Code = 990002; + } + + /// + /// تب فیش حقوقی + /// + public static class Checkout + { + public const int Code = 990003; + + /// + /// ایجاد فیش + /// + public const int Create = 99000301; + + /// + /// حذف تکی فیش + /// + public const int SingleDeletion = 99000302; + + /// + /// حذف گروهی فیش ها + /// + public const int GroupDeletion = 99000303; + + /// + /// محاسبه مجدد گروهی فیش ها + /// + public const int GroupReCompute = 99000304; + + /// + /// محاسبه مجدد تکی فیش + /// + public const int SingleReCompute = 99000305; + + } + + } + + #endregion + + #region ProgramManager[تب مدیریت پروژه] + + /// + /// تب مدیریت پروژه + /// + public static class ProgramManager + { + public const int Code = 9901; + + /// + /// ایجاد پروژه + /// + public static class CreateProject + { + public const int Code = 9901; + } + + /// + /// همه پروژه ها + /// + public static class AllProjects + { + public const int Code = 990102; + + } + + /// + /// تعیین کاربر + /// + public static class UserDetermination + { + public const int Code = 990106; + } + + /// + /// تعیین زمان پروژه + /// + public static class ProjectTimeSetting + { + public const int Code = 990107; + } + + /// + /// ویرایش پروژه + /// + public static class EditProject + { + public const int Code = 990108; + } + + /// + /// حذف پروژه + /// + public static class DeleteProject + { + public const int Code = 990109; + } + + /// + /// ایجاد بخش اصلی + /// + public static class CreateMainSection + { + public const int Code = 990110; + } + + /// + /// ایجاد بخش فرعی + /// + public static class CreateSubSection + { + public const int Code = 990111; + } + } + + #endregion + + #region Board[تب اجرا] + + /// + ///تب اجرا + /// + public static class Board + { + public const int Code = 9902; + + /// + /// تب همه + /// + public static class All + { + public const int Code = 990201; + } + + /// + /// آماده اجرا + /// + public static class ReadyToRun + { + public const int Code = 990202; + } + + /// + /// در حال اجرا + /// + public static class Running + { + public const int Code = 990203; + } + + + /// + /// نیمه کاره + /// + public static class Unfinished + { + public const int Code = 990204; + } + + /// + /// اتمام اجرا + /// + public static class Finished + { + public const int Code = 990204; + } + + /// + /// دیدن پروژه همه کاربران + /// + public static class ViewAllUsersProjects + { + public const int Code = 990206; + } + + /// + /// ارجاع به دیگران + /// + public static class ReferralToOthers + { + public const int Code = 990207; + } + + /// + /// چت + /// + public static class Chat + { + public const int Code = 990208; + } + } + + #endregion + + + public static Dictionary GetAllCodes() + { + var result = new Dictionary(); + + void Collect(Type type, Dictionary dict) + { + // Collect const int fields directly declared on this type + var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly); + foreach (var f in fields) + { + if (f.FieldType == typeof(int) && f.IsLiteral && !f.IsInitOnly) + { + var raw = f.GetRawConstantValue(); + if (raw is int value) + { + dict[f.Name] = value; + } + } + } + + // Recurse into nested types + var nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); + foreach (var nt in nestedTypes) + { + var nestedDict = new Dictionary(); + Collect(nt, nestedDict); + if (nestedDict.Count > 0) + { + dict[nt.Name] = nestedDict; + } + } + } + + Collect(typeof(ProgramManagerPermissionCode), result); + return result; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs index a41dad2b..314c5984 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs @@ -71,6 +71,10 @@ public interface IAuthHelper /// دریافت نام کامل کاربر جاری از Claims /// string? GetCurrentFullName(); + bool HasPermission(int permission); + List GetPermissions(); + + } diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj index 9ae2365c..9b9a0605 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj @@ -8,6 +8,7 @@ + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs deleted file mode 100644 index fabc5c3a..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs +++ /dev/null @@ -1,25 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.HolidayItemAgg; - -namespace GozareshgirProgramManager.Domain.HolidayAgg; - -public class Holiday : EntityBase -{ - public Holiday(string year) - { - Year = year; - - } - - public string Year { get; private set; } - public List HolidayItems { get; set; } - - public Holiday() - { - HolidayItems = new List(); - } - public void Edit(string year) - { - Year = year; - } -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs deleted file mode 100644 index 3a66bd58..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.HolidayAgg; - -namespace GozareshgirProgramManager.Domain.HolidayItemAgg; - -public class HolidayItem : EntityBase -{ - public HolidayItem(DateTime holidaydate, long holidayId, string holidayYear) - { - Holidaydate = holidaydate; - HolidayId = holidayId; - HolidayYear = holidayYear; - } - - public DateTime Holidaydate { get; private set; } - public long HolidayId { get; private set; } - public string HolidayYear { get; private set; } - - public Holiday Holidayss { get; set; } - - public void Edit(DateTime holidaydate, long holidayId, string holidayYear) - { - Holidaydate = holidaydate; - HolidayId = holidayId; - HolidayYear = holidayYear; - - } -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs index 33bdfcdf..05c7bb83 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs @@ -1,4 +1,5 @@ using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SkillAgg.Entities; namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; @@ -22,6 +23,7 @@ public class PhaseSection : EntityBase // Navigation property public ProjectPhase Phase { get; private set; } = null!; + public Skill? Skill { get; set; } public void UpdateUser(long userId) { diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs index 67820d49..d41c5eb0 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs @@ -1,4 +1,5 @@ using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SkillAgg.Entities; namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; @@ -21,6 +22,7 @@ public class ProjectSection : EntityBase public Guid SkillId { get; private set; } public Project Project { get; private set; } = null!; + public Skill? Skill { get; set; } public void UpdateUser(long userId) { diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs index b2a6fd91..7fd3f3e8 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs @@ -104,13 +104,8 @@ public class TaskSection : EntityBase UpdateStatus(TaskSectionStatus.NotAssigned); } - public void StartWork(long userId, string? notes = null) + public void StartWork(string? notes = null) { - if (CurrentAssignedUserId != userId) - { - throw new BadRequestException("کاربر مجاز به شروع این بخش نیست"); - } - // if (Status == TaskSectionStatus.Completed) // { // throw new BadRequestException("این بخش قبلاً تکمیل شده است"); @@ -121,14 +116,14 @@ public class TaskSection : EntityBase throw new BadRequestException("یک فعالیت در حال انجام وجود دارد"); } - var activity = new TaskSectionActivity(Id, userId, notes); + var activity = new TaskSectionActivity(Id, CurrentAssignedUserId, notes); _activities.Add(activity); UpdateStatus(TaskSectionStatus.InProgress); } - public void StopWork(long userId, TaskSectionStatus taskSectionStatus, string? endNotes = null) + public void StopWork(TaskSectionStatus taskSectionStatus, string? endNotes = null) { var activeActivity = _activities.FirstOrDefault(a => a.IsActive); if (activeActivity == null) @@ -136,11 +131,6 @@ public class TaskSection : EntityBase throw new BadRequestException("هیچ فعالیت فعالی یافت نشد"); } - if (activeActivity.UserId != userId) - { - throw new BadRequestException("کاربر مجاز به توقف این فعالیت نیست"); - } - UpdateStatus(taskSectionStatus); activeActivity.StopWork(endNotes); } @@ -220,4 +210,11 @@ public class TaskSection : EntityBase { _additionalTimes.Clear(); } + + public bool HasRemainingTime() + { + var totalSpent = GetTotalTimeSpent(); + var finalEstimate = FinalEstimatedHours; + return totalSpent < finalEstimate; + } } \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs index bedf59bf..d9c11d75 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs @@ -9,4 +9,6 @@ public interface ITaskSectionRepository: IRepository Task GetByIdWithFullDataAsync(Guid id, CancellationToken cancellationToken = default); + + Task> GetAssignedToUserAsync(long userId); } \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs index 0f1ed2da..a7ff25de 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs @@ -1,5 +1,7 @@ using System.Globalization; using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Bson; using PersianTools.Core; @@ -1704,25 +1706,25 @@ public static class Tools // return Convert.ToBase64String(bsonData); //} ////بیسان هایی که بصورت لیست بودند استخراج میشود - //public static List DeserializeFromBsonList(string base64Data) - //{ - // byte[] data = Convert.FromBase64String(base64Data); + public static List DeserializeFromBsonList(string base64Data) + { + byte[] data = Convert.FromBase64String(base64Data); - // using MemoryStream memoryStream = new MemoryStream(data); - // using BsonDataReader reader = new BsonDataReader(memoryStream); - // reader.ReadRootValueAsArray = true; - // JsonSerializer serializer = new JsonSerializer(); - // return serializer.Deserialize>(reader); - //} - ////بیسان هایی که بصورت تکی بودند استخراج میشود - //public static T DeserializeFromBson(string base64Data) - //{ - // byte[] bsonData = Convert.FromBase64String(base64Data); - // using MemoryStream memoryStream = new MemoryStream(bsonData); - // using BsonDataReader bsonReader = new BsonDataReader(memoryStream); - // JsonSerializer serializer = new JsonSerializer(); - // return serializer.Deserialize(bsonReader); - //} + using MemoryStream memoryStream = new MemoryStream(data); + using BsonDataReader reader = new BsonDataReader(memoryStream); + reader.ReadRootValueAsArray = true; + JsonSerializer serializer = new JsonSerializer(); + return serializer.Deserialize>(reader); + } + //بیسان هایی که بصورت تکی بودند استخراج میشود + public static T DeserializeFromBson(string base64Data) + { + byte[] bsonData = Convert.FromBase64String(base64Data); + using MemoryStream memoryStream = new MemoryStream(bsonData); + using BsonDataReader bsonReader = new BsonDataReader(memoryStream); + JsonSerializer serializer = new JsonSerializer(); + return serializer.Deserialize(bsonReader); + } //public static TimeOnly CalculateOffset(ICollection shiftDetailsRegularShifts) //{ diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.Designer.cs new file mode 100644 index 00000000..2fbb0fa8 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.Designer.cs @@ -0,0 +1,857 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251215155149_add relation to phase section and projectsection to skill")] + partial class addrelationtophasesectionandprojectsectiontoskill + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CheckoutEndDate") + .HasColumnType("datetime2"); + + b.Property("CheckoutStartDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeductionFromSalary") + .HasColumnType("float"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MandatoryHours") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("MonthlySalaryDefined") + .HasColumnType("float"); + + b.Property("MonthlySalaryPay") + .HasColumnType("float"); + + b.Property("RemainingHours") + .HasColumnType("int"); + + b.Property("TotalDaysWorked") + .HasColumnType("int"); + + b.Property("TotalHoursWorked") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Checkouts", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.HasIndex("SkillId"); + + b.ToTable("PhaseSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.HasIndex("SkillId"); + + b.ToTable("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("TaskSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("PmRoles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("PhaseSections") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany() + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Phase"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("ProjectSections") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany() + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Project"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("PmRolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + + b.Navigation("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("PhaseSections"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.cs new file mode 100644 index 00000000..3f63a30b --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251215155149_add relation to phase section and projectsection to skill.cs @@ -0,0 +1,63 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class addrelationtophasesectionandprojectsectiontoskill : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + migrationBuilder.CreateIndex( + name: "IX_ProjectSections_SkillId", + table: "ProjectSections", + column: "SkillId"); + + migrationBuilder.CreateIndex( + name: "IX_PhaseSections_SkillId", + table: "PhaseSections", + column: "SkillId"); + + migrationBuilder.AddForeignKey( + name: "FK_PhaseSections_Skills_SkillId", + table: "PhaseSections", + column: "SkillId", + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections", + column: "SkillId", + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PhaseSections_Skills_SkillId", + table: "PhaseSections"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections"); + + migrationBuilder.DropIndex( + name: "IX_ProjectSections_SkillId", + table: "ProjectSections"); + + migrationBuilder.DropIndex( + name: "IX_PhaseSections_SkillId", + table: "PhaseSections"); + + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs index 8e4c3871..9ea2308c 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("ProductVersion", "10.0.1") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -102,56 +102,6 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations b.ToTable("Customers", (string)null); }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CreationDate") - .HasColumnType("datetime2"); - - b.Property("Year") - .IsRequired() - .HasMaxLength(4) - .HasColumnType("nvarchar(4)"); - - b.HasKey("Id"); - - b.ToTable("Holidays", (string)null); - }); - - modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CreationDate") - .HasColumnType("datetime2"); - - b.Property("HolidayId") - .HasColumnType("bigint"); - - b.Property("HolidayYear") - .IsRequired() - .HasMaxLength(4) - .HasColumnType("nvarchar(4)"); - - b.Property("Holidaydate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("HolidayId"); - - b.ToTable("Holidayitems", (string)null); - }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => { b.Property("Id") @@ -174,6 +124,8 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations b.HasIndex("PhaseId"); + b.HasIndex("SkillId"); + b.ToTable("PhaseSections"); }); @@ -284,6 +236,8 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations b.HasIndex("ProjectId"); + b.HasIndex("SkillId"); + b.ToTable("ProjectSections"); }); @@ -630,17 +584,6 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations b.ToTable("UserRefreshTokens", (string)null); }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => - { - b.HasOne("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", "Holidayss") - .WithMany("HolidayItems") - .HasForeignKey("HolidayId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Holidayss"); - }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => { b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") @@ -649,7 +592,14 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany() + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Restrict); + b.Navigation("Phase"); + + b.Navigation("Skill"); }); modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => @@ -671,7 +621,14 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany() + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Restrict); + b.Navigation("Project"); + + b.Navigation("Skill"); }); modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => @@ -856,11 +813,6 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations b.Navigation("User"); }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => - { - b.Navigation("HolidayItems"); - }); - modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => { b.Navigation("Phases"); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs deleted file mode 100644 index 42eff124..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs +++ /dev/null @@ -1,20 +0,0 @@ -using GozareshgirProgramManager.Domain.HolidayItemAgg; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; - -public class HolidayItemMapping : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Holidayitems"); - builder.HasKey(x => x.Id); - - builder.Property(x => x.HolidayYear).HasMaxLength(4); - - builder.HasOne(x => x.Holidayss) - .WithMany(x => x.HolidayItems) - .HasForeignKey(x => x.HolidayId); - } -} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs deleted file mode 100644 index 3038d89a..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs +++ /dev/null @@ -1,20 +0,0 @@ -using GozareshgirProgramManager.Domain.HolidayAgg; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; - -public class HolidayMapping : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Holidays"); - builder.HasKey(x => x.Id); - - builder.Property(x => x.Year).HasMaxLength(4); - - builder.HasMany(x => x.HolidayItems) - .WithOne(x => x.Holidayss) - .HasForeignKey(x => x.HolidayId); - } -} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs index c1db7d49..1b4a829f 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs @@ -17,5 +17,11 @@ public class PhaseSectionMapping:IEntityTypeConfiguration .WithMany(p => p.PhaseSections) .HasForeignKey(ps => ps.PhaseId) .OnDelete(DeleteBehavior.Cascade); + + builder.HasOne(ps => ps.Skill) + .WithMany() + .HasForeignKey(ps => ps.SkillId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); } } \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs index ebc8df44..454ab86d 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs @@ -16,5 +16,11 @@ public class ProjectSectionMapping:IEntityTypeConfiguration .WithMany(x => x.ProjectSections) .HasForeignKey(x => x.ProjectId) .OnDelete(DeleteBehavior.Cascade); + + builder.HasOne(x => x.Skill) + .WithMany() + .HasForeignKey(x => x.SkillId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); } } \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs index 80564915..41551be5 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs @@ -28,4 +28,11 @@ public class TaskSectionRepository:RepositoryBase,ITaskSection .Include(x => x.AdditionalTimes) .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); } + + public async Task> GetAssignedToUserAsync(long userId) + { + return await _context.TaskSections + .Where(x => x.CurrentAssignedUserId == userId) + .ToListAsync(); + } } \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs index ec2ccd4f..aeb76f2e 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain._Common; using Microsoft.AspNetCore.Http; namespace GozareshgirProgramManager.Infrastructure.Services.Authentication; @@ -106,6 +107,21 @@ public class AuthHelper : IAuthHelper return _httpContextAccessor.HttpContext?.User?.FindFirst("FullName")?.Value; } + public bool HasPermission(int permission) + { + return GetPermissions().Any(x => x == permission); + } + + public List GetPermissions() + { + if (!IsAuthenticated()) + return new List(); + + var permissions = _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(x => x.Type == "permissions") + ?.Value; + return Tools.DeserializeFromBsonList(permissions); //Mahan + } + // /// // /// دریافت AccountId کاربر جاری از Claims // /// diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index d054b470..06514f9a 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -1,4 +1,5 @@ -using GozareshgirProgramManager.Application._Common.Models; +using System.Runtime.InteropServices; +using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject; using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection; using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; @@ -8,6 +9,7 @@ using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimePro using GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectAssignDetails; using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardDetail; using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; using MediatR; @@ -99,4 +101,11 @@ public class ProjectController : ProgramManagerBaseController var res = await _mediator.Send(query); return res; } + [HttpGet("board/details")] + public async Task>> GetProjectBoardDetails(Guid id) + { + var query = new ProjectBoardDetailQuery(id); + var res = await _mediator.Send(query); + return res; + } } \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml index 4819c826..fede8b2a 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml @@ -129,7 +129,7 @@
- فعالیت کاربر در پروگرام منیجر + فعالیت کاربر در مدیریت پروژه