From 5faa2062b9c803969df19b48b2cb0f039a44567b Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 24 Dec 2025 13:54:51 +0330 Subject: [PATCH 01/22] add: implement reactivation logic for contracting parties and associated employers after extension --- .../InstitutionContractRepository.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 8e6e4c18..bfb11406 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -2834,7 +2834,8 @@ public class InstitutionContractRepository : RepositoryBasex.id ==contractingPartyId); + + if (contractingParty != null) + { + if (contractingParty.IsActiveString == "false") + { + contractingParty.Active(); + _context.SaveChanges(); + } + + var employers = + _employerRepository.GetEmployerByContracrtingPartyID(contractingPartyId); + + foreach (var employer in employers) + { + var res = _employerRepository.ActiveAll(employer.Id); + } + } + } #endregion From 4f0e5a34a45107240caf15d49d9557fdb4b42af9 Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 24 Dec 2025 15:40:06 +0330 Subject: [PATCH 02/22] add: implement reactivation logic for institution contracts and retrieve previous contracts --- .../IInstitutionContractRepository.cs | 1 + .../InstitutionContractApplication.cs | 5 +- .../InstitutionContractRepository.cs | 39 +++++------- .../Pages/Company/AndroidApk/Index.cshtml.cs | 61 ++++++++++++++----- 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs index e10f15ed..54f0e897 100644 --- a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs +++ b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs @@ -159,4 +159,5 @@ public interface IInstitutionContractRepository : IRepository GetIdByInstallmentId(long installmentId); + Task GetPreviousContract(long currentInstitutionContractId); } \ No newline at end of file diff --git a/CompanyManagment.Application/InstitutionContractApplication.cs b/CompanyManagment.Application/InstitutionContractApplication.cs index bebd9ab9..6434a78b 100644 --- a/CompanyManagment.Application/InstitutionContractApplication.cs +++ b/CompanyManagment.Application/InstitutionContractApplication.cs @@ -1608,7 +1608,10 @@ public class InstitutionContractApplication : IInstitutionContractApplication } institutionContract.SetSigningType(signingType); - + var previousInstitutionContract = await _institutionContractRepository + .GetPreviousContract(institutionContract.id); + previousInstitutionContract.DeActive(); + ReActiveAllAfterCreateNew(institutionContract.ContractingPartyId); await _institutionContractRepository.SaveChangesAsync(); return op.Succcedded(); } diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index bfb11406..c6121f80 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -2834,8 +2834,6 @@ public class InstitutionContractRepository : RepositoryBasex.id ==contractingPartyId); - - if (contractingParty != null) - { - if (contractingParty.IsActiveString == "false") - { - contractingParty.Active(); - _context.SaveChanges(); - } - - var employers = - _employerRepository.GetEmployerByContracrtingPartyID(contractingPartyId); - - foreach (var employer in employers) - { - var res = _employerRepository.ActiveAll(employer.Id); - } - } - } #endregion @@ -4830,7 +4806,20 @@ public class InstitutionContractRepository : RepositoryBase x.Installments.Any(i => i.Id == installmentId)) .Select(x => x.id).FirstOrDefaultAsync(); } - + + public async Task GetPreviousContract(long currentInstitutionContractId) + { + var institutionContract =await _context.InstitutionContractSet + .FirstOrDefaultAsync(x=>x.id ==currentInstitutionContractId); + if (institutionContract == null) + return null; + var previousContract = await _context.InstitutionContractSet + .Where(x => x.ContractingPartyId == institutionContract.ContractingPartyId) + .Where(x => x.ContractStartGr < institutionContract.ContractStartGr) + .OrderByDescending(x => x.ContractEndGr) + .FirstOrDefaultAsync(); + return previousContract; + } #endregion diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs index 7d6eedfd..660a659c 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs +++ b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs @@ -52,6 +52,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk private readonly IOnlinePayment _onlinePayment; private readonly IFaceEmbeddingService _faceEmbeddingService; private readonly IAuthHelper _authHelper; + private readonly IInstitutionContractApplication _institutionContractApplication; [BindProperty] public IFormFile File { get; set; } @@ -77,7 +78,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk public IndexModel(IAndroidApkVersionApplication application, IRollCallDomainService rollCallDomainService, CompanyContext context, AccountContext accountContext, IHttpClientFactory httpClientFactory, IOptions appSetting, - ITemporaryClientRegistrationApplication clientRegistrationApplication, IOnlinePayment onlinePayment, IFaceEmbeddingService faceEmbeddingService, IAuthHelper authHelper) + ITemporaryClientRegistrationApplication clientRegistrationApplication, IOnlinePayment onlinePayment, + IFaceEmbeddingService faceEmbeddingService, IAuthHelper authHelper, IInstitutionContractApplication institutionContractApplication) { _application = application; _rollCallDomainService = rollCallDomainService; @@ -88,6 +90,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk _onlinePayment = onlinePayment; _faceEmbeddingService = faceEmbeddingService; _authHelper = authHelper; + _institutionContractApplication = institutionContractApplication; _paymentGateway = new SepehrPaymentGateway(httpClientFactory); } @@ -152,31 +155,60 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk { //await UpdateInstitutionContract(); //await UpdateFaceEmbeddingNames(); - await SetInstitutionContractSigningType(); + //await SetInstitutionContractSigningType(); + await ReActivateInstitution(); ViewData["message"] = "تومام یک"; return Page(); } + private async System.Threading.Tasks.Task ReActivateInstitution() + { + var blueInstitutionContracts = await _context.InstitutionContractSet.Where(x => + x.IsActiveString == "blue").ToListAsync(); + + + var blueContracts = new List(); + + foreach (var blueContract in blueInstitutionContracts) + { + var verifiedContracts = await _context.InstitutionContractSet + .Where(x => x.ContractingPartyId == blueContract.ContractingPartyId + && x.VerificationStatus == InstitutionContractVerificationStatus.Verified + && x.ContractStartGr > blueContract.ContractEndGr) + .ToListAsync(); + + if (verifiedContracts.Any()) + { + blueContracts.Add(blueContract); + } + } + + foreach (var institutionContract in blueContracts) + { + institutionContract.DeActive(); + _institutionContractApplication.ReActiveAllAfterCreateNew(institutionContract.ContractingPartyId); + } + } + private async System.Threading.Tasks.Task SetInstitutionContractSigningType() { var query = _context.InstitutionContractSet - .Where(x=>x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify); - - - var otpSigned = query.Where(x=>x.VerifierFullName != null && x.LawId != 0).ToList(); + .Where(x => x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify); + + + var otpSigned = query.Where(x => x.VerifierFullName != null && x.LawId != 0).ToList(); foreach (var institutionContract in otpSigned) { institutionContract.SetSigningType(InstitutionContractSigningType.OtpBased); } - var lagacySigned = query.Where(x=>x.VerifierFullName == null && x.LawId == 0).ToList(); + + var lagacySigned = query.Where(x => x.VerifierFullName == null && x.LawId == 0).ToList(); foreach (var institutionContract in lagacySigned) { institutionContract.SetSigningType(InstitutionContractSigningType.Legacy); } await _context.SaveChangesAsync(); - - } public async Task OnPostShiftDateNew2() @@ -326,6 +358,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk //TranslateCode(result?.ErrorCode); return Page(); } + [DisableConcurrentExecution(timeoutInSeconds: 120)] public async Task OnPostUploadFrontEnd(CancellationToken cancellationToken) { @@ -368,8 +401,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk TempData["Message"] = "فرآیند Deploy شروع شد. لاگ را بررسی کنید."; return RedirectToPage(); } - return Forbid(); + return Forbid(); } /// @@ -395,13 +428,10 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk { contractingPartyIdList.Add(employer.Employer.ContractingPartyId); } - } if (contractingPartyIdList.Count > 0) { - - if (contractingPartyIdList.Count == 1) { workshop.AddContractingPartyId(contractingPartyIdList[0]); @@ -422,7 +452,6 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk ViewData["message"] = "آی دی های طرف حساب اضافه شد"; return Page(); - } /// @@ -441,8 +470,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk var content = System.IO.File.ReadAllText(logPath, Encoding.UTF8); return Content(content); } - return Content("شما مجاز به دیدن لاگ نیستید"); + return Content("شما مجاز به دیدن لاگ نیستید"); } @@ -1055,7 +1084,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk x.PersonnelCount, x.Price, x.InstitutionContractWorkshopGroupId, group, - x.WorkshopId.Value,x.id); + x.WorkshopId.Value, x.id); entity.SetEmployers(x.Employers.Select(e => e.EmployerId).ToList()); return entity; From d77bffabdda887a198a7d2920eb0a6af786bbde7 Mon Sep 17 00:00:00 2001 From: SamSys Date: Wed, 24 Dec 2025 15:56:00 +0330 Subject: [PATCH 03/22] add SeriLog on Backgroundtask InstitutionContract --- .../BackgroundInstitutionContract.Task.csproj | 5 + .../Jobs/JobSchedulerRegistrator.cs | 46 +- .../Program.cs | 33 + .../appsettings.Development.json | 4 +- .../InstitutionContractRepository.cs | 11 +- .../Services/SmsService.cs | 891 +++++++++--------- 6 files changed, 522 insertions(+), 468 deletions(-) diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj index 3032b3a1..22ef8bc5 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj @@ -17,4 +17,9 @@ + + + + + diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs index b4487ac7..7c6847af 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs @@ -15,41 +15,43 @@ public class JobSchedulerRegistrator private static DateTime? _lastRunCreateTransaction; private static DateTime? _lastRunSendMonthlySms; private readonly ISmsService _smsService; + private readonly ILogger _logger; - public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository, ISmsService smsService) + public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository, ISmsService smsService, ILogger logger) { _smsReminder = smsReminder; _backgroundJobClient = backgroundJobClient; _institutionContractRepository = institutionContractRepository; _smsService = smsService; + _logger = logger; } public void Register() { + _logger.LogInformation("hangfire Started"); + //RecurringJob.AddOrUpdate( + // "InstitutionContract.CreateFinancialTransaction", + // () => CreateFinancialTransaction(), + // "*/30 * * * *" // هر 30 دقیقه یکبار چک کن + //); - RecurringJob.AddOrUpdate( - "InstitutionContract.CreateFinancialTransaction", - () => CreateFinancialTransaction(), - "*/30 * * * *" // هر 30 دقیقه یکبار چک کن - ); + //RecurringJob.AddOrUpdate( + // "InstitutionContract.SendMonthlySms", + // () => SendFirstDayOfMonthSms(), + // "*/20 * * * *" // هر 30 دقیقه یکبار چک کن + //); - RecurringJob.AddOrUpdate( - "InstitutionContract.SendMonthlySms", - () => SendFirstDayOfMonthSms(), - "*/20 * * * *" // هر 30 دقیقه یکبار چک کن - ); - - RecurringJob.AddOrUpdate( - "InstitutionContract.SendReminderSms", - () => SendReminderSms(), - "*/1 * * * *" // هر 1 دقیقه یکبار چک کن - ); - RecurringJob.AddOrUpdate( - "InstitutionContract.SendBlockSms", - () => SendBlockSms(), - "*/1 * * * *" // هر 1 دقیقه یکبار چک کن - ); + //RecurringJob.AddOrUpdate( + // "InstitutionContract.SendReminderSms", + // () => SendReminderSms(), + // "*/1 * * * *" // هر 1 دقیقه یکبار چک کن + //); + //RecurringJob.AddOrUpdate( + // "InstitutionContract.SendBlockSms", + // () => SendBlockSms(), + // "*/1 * * * *" // هر 1 دقیقه یکبار چک کن + //); RecurringJob.AddOrUpdate( "InstitutionContract.SendInstitutionContractConfirmSms", () => SendInstitutionContractConfirmSms(), diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs index c08fcf29..1319cee2 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs @@ -17,9 +17,37 @@ using Microsoft.AspNetCore.Identity; using MongoDB.Driver; using PersonalContractingParty.Config; using Query.Bootstrapper; +using Serilog; +using Serilog.Events; using Shared.Contracts.PmUser.Queries; using WorkFlow.Infrastructure.Config; +var logDirectory = @"C:\Logs\Hangfire\BackgroundInstitutionContract\"; + +if (!Directory.Exists(logDirectory)) +{ + Directory.CreateDirectory(logDirectory); +} + +Log.Logger = new LoggerConfiguration() + //NO EF Core log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + + //NO DbCommand log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) + + //NO Microsoft Public log + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + + .WriteTo.File( + path: Path.Combine(logDirectory, "institution-contract-log-.txt"), + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 30, + shared: true, + outputTemplate: + "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}" + ).CreateLogger(); + var builder = WebApplication.CreateBuilder(args); var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb"); builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString)); @@ -59,7 +87,12 @@ builder.Services.AddHttpClient(); builder.Services.AddHttpContextAccessor(); builder.Services.AddSignalR(); + +builder.Host.UseSerilog(); + + var app = builder.Build(); + app.MapHub("/sendSmsHub"); app.MapHangfireDashboard(); diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json index 07d44356..539c3b25 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json @@ -25,8 +25,8 @@ //mahan Docker //"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;", - //"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;", - "HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;" + "HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;", + //"HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;" }, "GoogleRecaptchaV3": { diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 8e6e4c18..bc82722e 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -25,6 +25,7 @@ using CompanyManagment.App.Contracts.TemporaryClientRegistration; using CompanyManagment.App.Contracts.Workshop; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using MongoDB.Driver; using PersianTools.Core; using System; @@ -54,6 +55,7 @@ public class InstitutionContractRepository : RepositoryBase _hubContext; + private readonly ILogger _logger; private readonly InstitutionContratVerificationParty _firstParty = new() { @@ -69,7 +71,7 @@ public class InstitutionContractRepository : RepositoryBase hubContext) : base(context) + IFinancialStatmentRepository financialStatmentRepository, IHubContext hubContext, ILogger logger) : base(context) { _context = context; _employerRepository = employerRepository; @@ -80,6 +82,7 @@ public class InstitutionContractRepository : RepositoryBase("InstitutionContractExtensionTemp"); _institutionAmendmentTemp = @@ -4378,7 +4381,7 @@ public class InstitutionContractRepository : RepositoryBase _testNumbers; - public SmsIr SmsIr { get; set; } + private readonly IConfiguration _configuration; + private readonly ISmsResultRepository _smsResultRepository; + private readonly bool _isDevEnvironment; + private readonly List _testNumbers; + private readonly ILogger _logger; + public SmsIr SmsIr { get; set; } - public SmsService(IConfiguration configuration, ISmsResultRepository smsResultRepository) - { - _configuration = configuration; - _smsResultRepository = smsResultRepository; - SmsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + public SmsService(IConfiguration configuration, ISmsResultRepository smsResultRepository, ILogger logger) + { + _configuration = configuration; + _smsResultRepository = smsResultRepository; + _logger = logger; + SmsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - // خواندن تنظیمات SMS از appsettings - var smsSettings = _configuration.GetSection("SmsSettings"); - _isDevEnvironment = smsSettings.GetValue("IsTestMode"); - _testNumbers = smsSettings.GetSection("TestNumbers").Get>() ?? new List(); - } + // خواندن تنظیمات SMS از appsettings + var smsSettings = _configuration.GetSection("SmsSettings"); + _isDevEnvironment = smsSettings.GetValue("IsTestMode"); + _testNumbers = smsSettings.GetSection("TestNumbers").Get>() ?? new List(); + } - /// - /// متد مرکزی برای ارسال پیامک که محیط dev را چک می‌کند - /// - private async Task> VerifySendSmsAsync(string number, int templateId, VerifySendParameter[] parameters) - { - // اگر محیط dev است و شماره‌های تست وجود دارد، به شماره‌های تست ارسال می‌شود - if (_isDevEnvironment && _testNumbers is { Count: > 0 }) - { - // ارسال به همه شماره‌های تست - SmsIrResult lastResult = null; - foreach (var testNumber in _testNumbers) - { - lastResult = await SmsIr.VerifySendAsync(testNumber, templateId, parameters); - } - return lastResult; // برگرداندن نتیجه آخرین ارسال - } - else - { - // ارسال به شماره واقعی - return await SmsIr.VerifySendAsync(number, templateId, parameters); - } - } + /// + /// متد مرکزی برای ارسال پیامک که محیط dev را چک می‌کند + /// + private async Task> VerifySendSmsAsync(string number, int templateId, VerifySendParameter[] parameters) + { + // اگر محیط dev است و شماره‌های تست وجود دارد، به شماره‌های تست ارسال می‌شود + if (_isDevEnvironment && _testNumbers is { Count: > 0 }) + { + // ارسال به همه شماره‌های تست + SmsIrResult lastResult = null; + foreach (var testNumber in _testNumbers) + { + lastResult = await SmsIr.VerifySendAsync(testNumber, templateId, parameters); + } + return lastResult; // برگرداندن نتیجه آخرین ارسال + } + else + { + // ارسال به شماره واقعی + return await SmsIr.VerifySendAsync(number, templateId, parameters); + } + } - public void Send(string number, string message) - { - //var token = GetToken(); - //var lines = new SmsLine().GetSmsLines(token); - //if (lines == null) return; + public void Send(string number, string message) + { + //var token = GetToken(); + //var lines = new SmsLine().GetSmsLines(token); + //if (lines == null) return; - //var line = lines.SMSLines.Last().LineNumber.ToString(); - //var data = new MessageSendObject - //{ - // Messages = new List - // {message}.ToArray(), - // MobileNumbers = new List {number}.ToArray(), - // LineNumber = line, - // SendDateTime = DateTime.Now, - // CanContinueInCaseOfError = true - //}; - //var messageSendResponseObject = - // new MessageSend().Send(token, data); + //var line = lines.SMSLines.Last().LineNumber.ToString(); + //var data = new MessageSendObject + //{ + // Messages = new List + // {message}.ToArray(), + // MobileNumbers = new List {number}.ToArray(), + // LineNumber = line, + // SendDateTime = DateTime.Now, + // CanContinueInCaseOfError = true + //}; + //var messageSendResponseObject = + // new MessageSend().Send(token, data); - //if (messageSendResponseObject.IsSuccessful) return; + //if (messageSendResponseObject.IsSuccessful) return; - //line = lines.SMSLines.First().LineNumber.ToString(); - //data.LineNumber = line; - //new MessageSend().Send(token, data); - } - public bool VerifySend(string number, string message) - { - var verificationSendResult = VerifySendSmsAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", message) }); - Thread.Sleep(2000); - if (verificationSendResult.IsCompletedSuccessfully) - { + //line = lines.SMSLines.First().LineNumber.ToString(); + //data.LineNumber = line; + //new MessageSend().Send(token, data); + } + public bool VerifySend(string number, string message) + { + var verificationSendResult = VerifySendSmsAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", message) }); + Thread.Sleep(2000); + if (verificationSendResult.IsCompletedSuccessfully) + { - var resStartStatus = verificationSendResult.Result; - var b = resStartStatus.Status; - var resResult = verificationSendResult.Status; - var a = verificationSendResult.IsCompleted; - var reseExceptiont = verificationSendResult.Exception; - return true; - } - else - { + var resStartStatus = verificationSendResult.Result; + var b = resStartStatus.Status; + var resResult = verificationSendResult.Status; + var a = verificationSendResult.IsCompleted; + var reseExceptiont = verificationSendResult.Exception; + return true; + } + else + { - var resStartStatus = verificationSendResult.Status; - var resResult = verificationSendResult.Status; - var reseExceptiont = verificationSendResult.Exception; + var resStartStatus = verificationSendResult.Status; + var resResult = verificationSendResult.Status; + var reseExceptiont = verificationSendResult.Exception; - return false; - } + return false; + } - } + } - public bool LoginSend(string number, string message) - { - var verificationSendResult = VerifySendSmsAsync(number, 635330, new VerifySendParameter[] { new VerifySendParameter("LOGINCODE", message) }); - Thread.Sleep(2000); - if (verificationSendResult.IsCompletedSuccessfully) - { + public bool LoginSend(string number, string message) + { + var verificationSendResult = VerifySendSmsAsync(number, 635330, new VerifySendParameter[] { new VerifySendParameter("LOGINCODE", message) }); + Thread.Sleep(2000); + if (verificationSendResult.IsCompletedSuccessfully) + { - var resStartStatus = verificationSendResult.Result; - var b = resStartStatus.Status; - var resResult = verificationSendResult.Status; - var a = verificationSendResult.IsCompleted; - var reseExceptiont = verificationSendResult.Exception; - return true; - } - else - { + var resStartStatus = verificationSendResult.Result; + var b = resStartStatus.Status; + var resResult = verificationSendResult.Status; + var a = verificationSendResult.IsCompleted; + var reseExceptiont = verificationSendResult.Exception; + return true; + } + else + { - var resStartStatus = verificationSendResult.Status; - var resResult = verificationSendResult.Status; - var reseExceptiont = verificationSendResult.Exception; + var resStartStatus = verificationSendResult.Status; + var resResult = verificationSendResult.Status; + var reseExceptiont = verificationSendResult.Exception; - return false; - } - } + return false; + } + } - public async Task SendVerifyCodeToClient(string number, string code) - { - var result = new SentSmsViewModel(); - var sendResult = await VerifySendSmsAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", code) }); - Thread.Sleep(2000); + public async Task SendVerifyCodeToClient(string number, string code) + { + var result = new SentSmsViewModel(); + var sendResult = await VerifySendSmsAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", code) }); + Thread.Sleep(2000); - if (sendResult.Message == "موفق") - { - var status = sendResult.Status; - var message = sendResult.Message; - var messaeId = sendResult.Data.MessageId; - return result.Succedded(status, message, messaeId); - } - else - { - var status = sendResult.Status; - var message = sendResult.Message; - var messaeId = sendResult.Data.MessageId; - return result.Failed(status, message, messaeId); - } - } + if (sendResult.Message == "موفق") + { + var status = sendResult.Status; + var message = sendResult.Message; + var messaeId = sendResult.Data.MessageId; + return result.Succedded(status, message, messaeId); + } + else + { + var status = sendResult.Status; + var message = sendResult.Message; + var messaeId = sendResult.Data.MessageId; + return result.Failed(status, message, messaeId); + } + } - public bool SendAccountsInfo(string number, string fullName, string userName) - { + public bool SendAccountsInfo(string number, string fullName, string userName) + { - var checkLength = fullName.Length; - if (checkLength > 25) - fullName = fullName.Substring(0, 24); + var checkLength = fullName.Length; + if (checkLength > 25) + fullName = fullName.Substring(0, 24); - var sendResult = VerifySendSmsAsync(number, 725814, new VerifySendParameter[] { new VerifySendParameter("FULLNAME", fullName), new VerifySendParameter("USERNAME", userName), new VerifySendParameter("PASSWORD", userName) }); + var sendResult = VerifySendSmsAsync(number, 725814, new VerifySendParameter[] { new VerifySendParameter("FULLNAME", fullName), new VerifySendParameter("USERNAME", userName), new VerifySendParameter("PASSWORD", userName) }); - Console.WriteLine(userName + " - " + sendResult.Result.Status); - if (sendResult.IsCompletedSuccessfully) - { - return true; - } - else - { - return false; - } + Console.WriteLine(userName + " - " + sendResult.Result.Status); + if (sendResult.IsCompletedSuccessfully) + { + return true; + } + else + { + return false; + } - } + } - public async Task GetByMessageId(int messId) - { + public async Task GetByMessageId(int messId) + { - SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - var response = await smsIr.GetReportAsync(messId); - MessageReportResult messages = response.Data; + SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + var response = await smsIr.GetReportAsync(messId); + MessageReportResult messages = response.Data; - var appendData = new ApiResultViewModel() - { - MessageId = messages.MessageId, - LineNumber = messages.LineNumber, - Mobile = messages.Mobile, - MessageText = messages.MessageText, - SendUnixTime = UnixTimeStampToDateTime(messages.SendDateTime), - DeliveryState = DeliveryStatus(messages.DeliveryState), - DeliveryUnixTime = UnixTimeStampToDateTime(messages.DeliveryDateTime), - DeliveryColor = DeliveryColorStatus(messages.DeliveryState), - }; - return appendData; - } - public async Task> GetApiResult(string startDate, string endDate) - { - var st = new DateTime(2024, 6, 2); - var ed = new DateTime(2024, 7, 1); - if (!string.IsNullOrWhiteSpace(startDate) && startDate.Length == 10) - { - st = startDate.ToGeorgianDateTime(); - } - if (!string.IsNullOrWhiteSpace(endDate) && endDate.Length == 10) - { - ed = endDate.ToGeorgianDateTime(); - } - var res = new List(); - Int32 unixTimestamp = (int)st.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; - Int32 unixTimestamp2 = (int)ed.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; - // int? fromDateUnixTime = null; // unix time - for instance: 1700598600 - //int? toDateUnixTime = null; // unix time - for instance: 1703190600 - int pageNumber = 2; - int pageSize = 100; // max: 100 - SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - var response = await smsIr.GetArchivedReportAsync(pageNumber, pageSize, unixTimestamp, unixTimestamp2); + var appendData = new ApiResultViewModel() + { + MessageId = messages.MessageId, + LineNumber = messages.LineNumber, + Mobile = messages.Mobile, + MessageText = messages.MessageText, + SendUnixTime = UnixTimeStampToDateTime(messages.SendDateTime), + DeliveryState = DeliveryStatus(messages.DeliveryState), + DeliveryUnixTime = UnixTimeStampToDateTime(messages.DeliveryDateTime), + DeliveryColor = DeliveryColorStatus(messages.DeliveryState), + }; + return appendData; + } + public async Task> GetApiResult(string startDate, string endDate) + { + var st = new DateTime(2024, 6, 2); + var ed = new DateTime(2024, 7, 1); + if (!string.IsNullOrWhiteSpace(startDate) && startDate.Length == 10) + { + st = startDate.ToGeorgianDateTime(); + } + if (!string.IsNullOrWhiteSpace(endDate) && endDate.Length == 10) + { + ed = endDate.ToGeorgianDateTime(); + } + var res = new List(); + Int32 unixTimestamp = (int)st.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + Int32 unixTimestamp2 = (int)ed.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + // int? fromDateUnixTime = null; // unix time - for instance: 1700598600 + //int? toDateUnixTime = null; // unix time - for instance: 1703190600 + int pageNumber = 2; + int pageSize = 100; // max: 100 + SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + var response = await smsIr.GetArchivedReportAsync(pageNumber, pageSize, unixTimestamp, unixTimestamp2); - MessageReportResult[] messages = response.Data; - foreach (var message in messages) - { - var appendData = new ApiResultViewModel() - { - MessageId = message.MessageId, - LineNumber = message.LineNumber, - Mobile = message.Mobile, - MessageText = message.MessageText, - SendUnixTime = UnixTimeStampToDateTime(message.SendDateTime), - DeliveryState = DeliveryStatus(message.DeliveryState), - DeliveryUnixTime = UnixTimeStampToDateTime(message.DeliveryDateTime), - DeliveryColor = DeliveryColorStatus(message.DeliveryState), - }; - res.Add(appendData); - } + MessageReportResult[] messages = response.Data; + foreach (var message in messages) + { + var appendData = new ApiResultViewModel() + { + MessageId = message.MessageId, + LineNumber = message.LineNumber, + Mobile = message.Mobile, + MessageText = message.MessageText, + SendUnixTime = UnixTimeStampToDateTime(message.SendDateTime), + DeliveryState = DeliveryStatus(message.DeliveryState), + DeliveryUnixTime = UnixTimeStampToDateTime(message.DeliveryDateTime), + DeliveryColor = DeliveryColorStatus(message.DeliveryState), + }; + res.Add(appendData); + } - return res; - } + return res; + } - public string DeliveryStatus(byte? dv) - { - string mess = ""; - switch (dv) - { - case 1: - mess = "رسیده به گوشی"; - break; - case 2: - mess = "نرسیده به گوشی"; - break; - case 3: - mess = "پردازش در مخابرات"; - break; - case 4: - mess = "نرسیده به مخابرات"; - break; - case 5: - mess = "سیده به مخابرات"; - break; - case 6: - mess = "خطا"; - break; - case 7: - mess = "لیست سیاه"; - break; - default: - mess = ""; - break; + public string DeliveryStatus(byte? dv) + { + string mess = ""; + switch (dv) + { + case 1: + mess = "رسیده به گوشی"; + break; + case 2: + mess = "نرسیده به گوشی"; + break; + case 3: + mess = "پردازش در مخابرات"; + break; + case 4: + mess = "نرسیده به مخابرات"; + break; + case 5: + mess = "سیده به مخابرات"; + break; + case 6: + mess = "خطا"; + break; + case 7: + mess = "لیست سیاه"; + break; + default: + mess = ""; + break; - } + } - return mess; - } - public string DeliveryColorStatus(byte? dv) - { - string mess = ""; - switch (dv) - { - case 1: - mess = "successSend"; - break; - case 2: - mess = "errSend"; - break; - case 3: - mess = "pSend"; - break; - case 4: - mess = "noSend"; - break; - case 5: - mess = "itcSend"; - break; - case 6: - mess = "redSend"; - break; - case 7: - mess = "blockSend"; - break; - default: - mess = ""; - break; + return mess; + } + public string DeliveryColorStatus(byte? dv) + { + string mess = ""; + switch (dv) + { + case 1: + mess = "successSend"; + break; + case 2: + mess = "errSend"; + break; + case 3: + mess = "pSend"; + break; + case 4: + mess = "noSend"; + break; + case 5: + mess = "itcSend"; + break; + case 6: + mess = "redSend"; + break; + case 7: + mess = "blockSend"; + break; + default: + mess = ""; + break; - } + } - return mess; - } - public string UnixTimeStampToDateTime(int? unixTimeStamp) - { - if (unixTimeStamp != null) - { - // Unix timestamp is seconds past epoch - DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - dateTime = dateTime.AddSeconds(Convert.ToDouble(unixTimeStamp)).ToLocalTime(); - var time = dateTime.ToFarsiFull(); - return time; - } + return mess; + } + public string UnixTimeStampToDateTime(int? unixTimeStamp) + { + if (unixTimeStamp != null) + { + // Unix timestamp is seconds past epoch + DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + dateTime = dateTime.AddSeconds(Convert.ToDouble(unixTimeStamp)).ToLocalTime(); + var time = dateTime.ToFarsiFull(); + return time; + } - return ""; - } - private string GetToken() - { - return ""; - //var smsSecrets = _configuration.GetSection("SmsSecrets"); - //var tokenService = new Token(); - //return tokenService.GetToken("x-api-key", "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - } + return ""; + } + private string GetToken() + { + return ""; + //var smsSecrets = _configuration.GetSection("SmsSecrets"); + //var tokenService = new Token(); + //return tokenService.GetToken("x-api-key", "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + } - #region Mahan + #region Mahan - public async Task GetCreditAmount() - { - try - { - var credit = await SmsIr.GetCreditAsync(); - return (double)credit.Data; - } - catch - { - return -1; - } + public async Task GetCreditAmount() + { + try + { + var credit = await SmsIr.GetCreditAsync(); + return (double)credit.Data; + } + catch + { + return -1; + } - } + } - public async Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms) - { + public async Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms) + { typeOfSms = string.IsNullOrWhiteSpace(typeOfSms) ? "لینک تاییدیه ایجاد قرارداد مالی" : typeOfSms; - - + + var full = fullName; - var fullName1 = fullName; - if (fullName.Length >= 25) - { - fullName1 = fullName.Substring(0, 25); - } - var fullName2 = ""; - if (full.Length > 25) - { - fullName2 = full.Substring(25); - if (fullName2.Length>25) - { - fullName2 = fullName2.Substring(0, 25); - } - } - var guidStr = institutionId.ToString(); - var firstPart = guidStr.Substring(0, 15); - var secondPart = guidStr.Substring(15); - var verificationSendResult = await VerifySendSmsAsync(number, 527519, new VerifySendParameter[] - { - new("FULLNAME1", fullName1), - new("FULLNAME2", fullName2), - new("CODE1",firstPart), - new("CODE2",secondPart) - }); - + var fullName1 = fullName; + if (fullName.Length >= 25) + { + fullName1 = fullName.Substring(0, 25); + } + var fullName2 = ""; + if (full.Length > 25) + { + fullName2 = full.Substring(25); + if (fullName2.Length > 25) + { + fullName2 = fullName2.Substring(0, 25); + } + } + var guidStr = institutionId.ToString(); + var firstPart = guidStr.Substring(0, 15); + var secondPart = guidStr.Substring(15); + var verificationSendResult = await VerifySendSmsAsync(number, 527519, new VerifySendParameter[] + { + new("FULLNAME1", fullName1), + new("FULLNAME2", fullName2), + new("CODE1",firstPart), + new("CODE2",secondPart) + }); + if (verificationSendResult.Status == 1) + { + _logger.LogInformation("ارسال لینک قراداد مالی موفق بود"); + } + else + { + _logger.LogError("خطا در ارسال لینک قراداد مالی"); + } var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, typeOfSms, - fullName, number, contractingPartyId, institutionContractId); - await _smsResultRepository.CreateAsync(smsResult); - await _smsResultRepository.SaveChangesAsync(); - return verificationSendResult.Status == 0; - } + fullName, number, contractingPartyId, institutionContractId); + await _smsResultRepository.CreateAsync(smsResult); + await _smsResultRepository.SaveChangesAsync(); + _logger.LogInformation("ذخیره در دیتابیس موفق بود"); + return verificationSendResult.Status == 0; + } - public async Task SendInstitutionAmendmentVerificationLink(string number, string fullName, Guid institutionId, - long contractingPartyId, long institutionContractId) - { - var guidStr = institutionId.ToString(); - var firstPart = guidStr.Substring(0, 15); - var secondPart = guidStr.Substring(15); - var verificationSendResult = await VerifySendSmsAsync(number, 527519, new VerifySendParameter[] - { - new("FULLNAME", fullName), - new("CODE1",firstPart), - new("CODE2",secondPart) - }); - var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, "لینک تاییدیه ارتقا قرارداد مالی", - fullName, number, contractingPartyId, institutionContractId); - await _smsResultRepository.CreateAsync(smsResult); - await _smsResultRepository.SaveChangesAsync(); - return verificationSendResult.Status == 0; - } + public async Task SendInstitutionAmendmentVerificationLink(string number, string fullName, Guid institutionId, + long contractingPartyId, long institutionContractId) + { + var guidStr = institutionId.ToString(); + var firstPart = guidStr.Substring(0, 15); + var secondPart = guidStr.Substring(15); + var verificationSendResult = await VerifySendSmsAsync(number, 527519, new VerifySendParameter[] + { + new("FULLNAME", fullName), + new("CODE1",firstPart), + new("CODE2",secondPart) + }); + var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, "لینک تاییدیه ارتقا قرارداد مالی", + fullName, number, contractingPartyId, institutionContractId); + await _smsResultRepository.CreateAsync(smsResult); + await _smsResultRepository.SaveChangesAsync(); + return verificationSendResult.Status == 0; + } - public async Task SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName, - long contractingPartyId, long institutionContractId) - { - var verificationSendResult = await VerifySendSmsAsync(number, 965348, new VerifySendParameter[] - { - new("VERIFYCODE", code) - }); + public async Task SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName, + long contractingPartyId, long institutionContractId) + { + var verificationSendResult = await VerifySendSmsAsync(number, 965348, new VerifySendParameter[] + { + new("VERIFYCODE", code) + }); - var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, "کد تاییدیه قرارداد مالی", - contractingPartyFullName, number, contractingPartyId, institutionContractId); - await _smsResultRepository.CreateAsync(smsResult); - await _smsResultRepository.SaveChangesAsync(); - return verificationSendResult.Status == 0; - } + var smsResult = new SmsResult(verificationSendResult.Data.MessageId, verificationSendResult.Message, "کد تاییدیه قرارداد مالی", + contractingPartyFullName, number, contractingPartyId, institutionContractId); + await _smsResultRepository.CreateAsync(smsResult); + await _smsResultRepository.SaveChangesAsync(); + return verificationSendResult.Status == 0; + } - public _0_Framework.Application.Sms.SmsResult TaskReminderSms(string number, string taskCount) - { - throw new NotImplementedException(); - } + public _0_Framework.Application.Sms.SmsResult TaskReminderSms(string number, string taskCount) + { + throw new NotImplementedException(); + } - #endregion + #endregion - #region InstitutionContractSMS + #region InstitutionContractSMS - public async Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBillNew(string number, int tamplateId, string fullname, string amount, string code1, - string code2) - { + public async Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBillNew(string number, int tamplateId, string fullname, string amount, string code1, + string code2) + { - var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - var result = new ValueTuple(); - var sendResult = await smsIr.VerifySendAsync(number, tamplateId, - new VerifySendParameter[] - { new("FULLNAME", fullname), new("AMOUNT", amount), new("CODE1", code1), new("CODE2", code2) }); - Thread.Sleep(500); + var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + var result = new ValueTuple(); + var sendResult = await smsIr.VerifySendAsync(number, tamplateId, + new VerifySendParameter[] + { new("FULLNAME", fullname), new("AMOUNT", amount), new("CODE1", code1), new("CODE2", code2) }); + Thread.Sleep(500); - if (sendResult.Message == "موفق") - { + if (sendResult.Message == "موفق") + { - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); - return result; - } + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); + return result; + } - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); - return result; + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); + return result; - } + } - public async Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBill(string number, int tamplateId, string fullname, string amount, string id, - string aprove) - { + public async Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBill(string number, int tamplateId, string fullname, string amount, string id, + string aprove) + { - var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - var result = new ValueTuple(); - var sendResult = await smsIr.VerifySendAsync(number, tamplateId, - new VerifySendParameter[] - { new("FULLNAME", fullname), new("AMOUNT", amount), new("ID", id), new("APROVE", aprove) }); - Thread.Sleep(500); + var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + var result = new ValueTuple(); + var sendResult = await smsIr.VerifySendAsync(number, tamplateId, + new VerifySendParameter[] + { new("FULLNAME", fullname), new("AMOUNT", amount), new("ID", id), new("APROVE", aprove) }); + Thread.Sleep(500); - if (sendResult.Message == "موفق") - { + if (sendResult.Message == "موفق") + { - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); - return result; - } + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); + return result; + } - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); - return result; - } + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); + return result; + } - public async Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, - string aprove) - { - var tamplateId = 117946; - var result = new ValueTuple(); - var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + public async Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, + string aprove) + { + var tamplateId = 117946; + var result = new ValueTuple(); + var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - var sendResult = await smsIr.VerifySendAsync(number, tamplateId, - new VerifySendParameter[] - { - new("FULLNAME", fullname), new("AMOUNT", amount), new("ACCOUNTTYPE", accountType), new("ID", id), - new("APROVE", aprove) - }); - Thread.Sleep(500); + var sendResult = await smsIr.VerifySendAsync(number, tamplateId, + new VerifySendParameter[] + { + new("FULLNAME", fullname), new("AMOUNT", amount), new("ACCOUNTTYPE", accountType), new("ID", id), + new("APROVE", aprove) + }); + Thread.Sleep(500); - if (sendResult.Message == "موفق") - { + if (sendResult.Message == "موفق") + { - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); - return result; - } + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true); + return result; + } - result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); - return result; - } + result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false); + return result; + } - #endregion + #endregion - #region AlarmMessage + #region AlarmMessage - public async Task Alarm(string number, string message) - { - var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + public async Task Alarm(string number, string message) + { + var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); - //var bulkSendResult = smsIr.BulkSendAsync(95007079000006, "your text message", new string[] { "9120000000" }); + //var bulkSendResult = smsIr.BulkSendAsync(95007079000006, "your text message", new string[] { "9120000000" }); - var verificationSendResult = - smsIr.VerifySendAsync(number, 662874, new VerifySendParameter[] { new("ALARM", message) }); - Thread.Sleep(1000); - var status = verificationSendResult.Result.Status; - var mess = verificationSendResult.Result.Message; - var messaeId = verificationSendResult.Result.Data.MessageId; - if (verificationSendResult.IsCompletedSuccessfully) return true; + var verificationSendResult = + smsIr.VerifySendAsync(number, 662874, new VerifySendParameter[] { new("ALARM", message) }); + Thread.Sleep(1000); + var status = verificationSendResult.Result.Status; + var mess = verificationSendResult.Result.Message; + var messaeId = verificationSendResult.Result.Data.MessageId; + if (verificationSendResult.IsCompletedSuccessfully) return true; - var resStartStatus = verificationSendResult.Result; - var resResult = verificationSendResult.Status; - var reseExceptiont = verificationSendResult.Exception; + var resStartStatus = verificationSendResult.Result; + var resResult = verificationSendResult.Status; + var reseExceptiont = verificationSendResult.Exception; - return false; - } + return false; + } - #endregion + #endregion } From 7b648b135e5ac39840263c7dc6c416287a2a9dcc Mon Sep 17 00:00:00 2001 From: SamSys Date: Wed, 24 Dec 2025 16:22:51 +0330 Subject: [PATCH 04/22] add new logs --- .../BackgroundInstitutionContract.Task/Program.cs | 1 + .../Repository/InstitutionContractRepository.cs | 5 +++-- CompanyManagment.EFCore/Services/SmsService.cs | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs index 1319cee2..4d36161f 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs @@ -89,6 +89,7 @@ builder.Services.AddSignalR(); builder.Host.UseSerilog(); +Log.Information("SERILOG STARTED SUCCESSFULLY"); var app = builder.Build(); diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index eb7885ad..4a14ceba 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -3493,7 +3493,7 @@ public class InstitutionContractRepository : RepositoryBase 18 ? item.PartyName.Substring(0, 18) : item.PartyName; string errMess = $"{name}-خطا"; + _logger.LogError(errMess); await _smsService.Alarm("09114221321", errMess); } @@ -4399,7 +4400,7 @@ public class InstitutionContractRepository : RepositoryBase Date: Wed, 24 Dec 2025 16:31:32 +0330 Subject: [PATCH 05/22] add: create EmployeeController to manage employee selection for workshops --- .../Client/Controllers/EmployeeController.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 ServiceHost/Areas/Client/Controllers/EmployeeController.cs diff --git a/ServiceHost/Areas/Client/Controllers/EmployeeController.cs b/ServiceHost/Areas/Client/Controllers/EmployeeController.cs new file mode 100644 index 00000000..71703125 --- /dev/null +++ b/ServiceHost/Areas/Client/Controllers/EmployeeController.cs @@ -0,0 +1,25 @@ +using _0_Framework.Application; +using CompanyManagment.App.Contracts.Employee; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Client.Controllers; + +public class EmployeeController:ClientBaseController +{ + private readonly IEmployeeApplication _employeeApplication; + private readonly long _workshopId; + + public EmployeeController(IEmployeeApplication employeeApplication,IAuthHelper authHelper) + { + _employeeApplication = employeeApplication; + _workshopId = authHelper.GetWorkshopId(); + } + + [HttpGet("select-list")] + public async Task>> GetEmployeeSelectList() + { + var result = await _employeeApplication.WorkedEmployeesInWorkshopSelectList(_workshopId); + return result; + } +} \ No newline at end of file From 6046f55ece9ce2219864e21966881540dfebb472 Mon Sep 17 00:00:00 2001 From: SamSys Date: Wed, 24 Dec 2025 16:58:35 +0330 Subject: [PATCH 06/22] backgroundTask change --- .../Jobs/JobSchedulerRegistrator.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs index 7c6847af..c0d08602 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs @@ -30,28 +30,28 @@ public class JobSchedulerRegistrator public void Register() { _logger.LogInformation("hangfire Started"); - //RecurringJob.AddOrUpdate( - // "InstitutionContract.CreateFinancialTransaction", - // () => CreateFinancialTransaction(), - // "*/30 * * * *" // هر 30 دقیقه یکبار چک کن - //); + RecurringJob.AddOrUpdate( + "InstitutionContract.CreateFinancialTransaction", + () => CreateFinancialTransaction(), + "*/30 * * * *" // هر 30 دقیقه یکبار چک کن + ); - //RecurringJob.AddOrUpdate( - // "InstitutionContract.SendMonthlySms", - // () => SendFirstDayOfMonthSms(), - // "*/20 * * * *" // هر 30 دقیقه یکبار چک کن - //); + RecurringJob.AddOrUpdate( + "InstitutionContract.SendMonthlySms", + () => SendFirstDayOfMonthSms(), + "*/20 * * * *" // هر 30 دقیقه یکبار چک کن + ); - //RecurringJob.AddOrUpdate( - // "InstitutionContract.SendReminderSms", - // () => SendReminderSms(), - // "*/1 * * * *" // هر 1 دقیقه یکبار چک کن - //); - //RecurringJob.AddOrUpdate( - // "InstitutionContract.SendBlockSms", - // () => SendBlockSms(), - // "*/1 * * * *" // هر 1 دقیقه یکبار چک کن - //); + RecurringJob.AddOrUpdate( + "InstitutionContract.SendReminderSms", + () => SendReminderSms(), + "*/1 * * * *" // هر 1 دقیقه یکبار چک کن + ); + RecurringJob.AddOrUpdate( + "InstitutionContract.SendBlockSms", + () => SendBlockSms(), + "*/1 * * * *" // هر 1 دقیقه یکبار چک کن + ); RecurringJob.AddOrUpdate( "InstitutionContract.SendInstitutionContractConfirmSms", () => SendInstitutionContractConfirmSms(), From fc315cc908450dff50fe3b5e37c3e87f8053e9c6 Mon Sep 17 00:00:00 2001 From: SamSys Date: Wed, 24 Dec 2025 17:18:21 +0330 Subject: [PATCH 07/22] change backgrooundTask --- .../Repository/InstitutionContractRepository.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 4a14ceba..4833ca6f 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -4382,7 +4382,7 @@ public class InstitutionContractRepository : RepositoryBase Date: Wed, 24 Dec 2025 17:20:26 +0330 Subject: [PATCH 08/22] fix --- .../Repository/InstitutionContractRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 4833ca6f..2d97b743 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -4382,7 +4382,7 @@ public class InstitutionContractRepository : RepositoryBase Date: Wed, 24 Dec 2025 18:07:43 +0330 Subject: [PATCH 09/22] add employee client api --- .../EmployeeAgg/IEmployeeRepository.cs | 1 + .../Employee/IEmployeeApplication.cs | 35 ++++++ .../EmployeeAplication.cs | 5 + .../Repository/EmployeeRepository .cs | 113 +++++++++++++++++- 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/Company.Domain/EmployeeAgg/IEmployeeRepository.cs b/Company.Domain/EmployeeAgg/IEmployeeRepository.cs index 43a2564a..f0ecc290 100644 --- a/Company.Domain/EmployeeAgg/IEmployeeRepository.cs +++ b/Company.Domain/EmployeeAgg/IEmployeeRepository.cs @@ -76,6 +76,7 @@ public interface IEmployeeRepository : IRepository #region Api Task> GetSelectList(string searchText,long id); Task> GetList(GetEmployeeListSearchModel searchModel); + Task> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId); #endregion diff --git a/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs b/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs index 396047da..bbf28757 100644 --- a/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs +++ b/CompanyManagment.App.Contracts/Employee/IEmployeeApplication.cs @@ -94,7 +94,42 @@ public interface IEmployeeApplication /// /// Task> GetList(GetEmployeeListSearchModel searchModel); + + /// + /// لیست کل پرسنل کلاینت + /// + /// + /// + /// + Task> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId); #endregion +} + +public class GetClientEmployeeListSearchModel +{ +} + +public class GetClientEmployeeListViewModel +{ + public string FullName { get; set; } + public long EmployeeId { get; set; } + public long WorkshopId { get; set; } + public long PersonnelCode { get; set; } + public string MaritalStatus { get; set; } + public string NationalCode { get; set; } + public string IdNumber { get; set; } + public string DateOfBirthFa { get; set; } + public string FatherName { get; set; } + public int ChildrenCount { get; set; } + public string LastStartInsuranceWork { get; set; } + public string LastLeftInsuranceWork { get; set; } + public string LastStartContractWork { get; set; } + public string LastLeftContractWork { get; set; } + public bool HasContractLeftWork { get; set; } + public bool HasInsuranceLeftWork { get; set; } + public bool LeftWorkCompletely { get; set; } + public bool PendingStartWork { get; set; } + public bool PendingLeftWork { get; set; } } \ No newline at end of file diff --git a/CompanyManagment.Application/EmployeeAplication.cs b/CompanyManagment.Application/EmployeeAplication.cs index 4af00ab9..352d2173 100644 --- a/CompanyManagment.Application/EmployeeAplication.cs +++ b/CompanyManagment.Application/EmployeeAplication.cs @@ -1729,5 +1729,10 @@ public class EmployeeAplication : RepositoryBase, IEmployeeAppli return await _EmployeeRepository.GetList(searchModel); } + public async Task> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId) + { + return await _EmployeeRepository.GetClientEmployeeList(searchModel, workshopId); + } + #endregion } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/EmployeeRepository .cs b/CompanyManagment.EFCore/Repository/EmployeeRepository .cs index bd02e8fa..74c27f31 100644 --- a/CompanyManagment.EFCore/Repository/EmployeeRepository .cs +++ b/CompanyManagment.EFCore/Repository/EmployeeRepository .cs @@ -1062,5 +1062,116 @@ public class EmployeeRepository : RepositoryBase, IEmployeeRepos } - #endregion + public Task> GetClientEmployeeList(GetClientEmployeeListSearchModel searchModel, long workshopId) + { + // var leftDate = Tools.GetUndefinedDateTime(); + // + // var personnelCodes = _context.PersonnelCodeSet.Include(x => x.Employee) + // .ThenInclude(x => x.EmployeeChildrenList).IgnoreQueryFilters().Where(x => x.WorkshopId == workshopId).ToList(); + // + // var contractLeftWork = + // _context.LeftWorkList.Where(x => x.WorkshopId == workshopId) + // .GroupBy(x => x.EmployeeId).Select(x => x.OrderByDescending(y => y.LeftWork).First()).ToList(); + // + // + // + // + // var insuranceLeftWork = _context.LeftWorkInsuranceList.Where(x => x.WorkshopId == workshopId).Select(x => new + // { + // EmployeeId = x.EmployeeId, + // FullName = x.EmployeeFullName, + // PersonnelCode = 0, + // InsurancePerson = true, + // InsuranceLeft = x.LeftWorkDate != null, + // StartWork = x.StartWorkDate, + // LeftWork = x.LeftWorkDate ?? leftDate, + // LastStartInsuranceWork = x.StartWorkDate.ToFarsi(), + // LastLeftInsuranceWork = x.LeftWorkDate != null ? x.LeftWorkDate.ToFarsi() : "-", + // LastStartContractWork = "-", + // LastLeftContractWork = "-" + // }).GroupBy(x => x.EmployeeId) + // .Select(x => x.OrderByDescending(y => y.LeftWork).First()).ToList(); + // + // var leftWorkTemp = _context.LeftWorkTemps.Where(x => x.WorkshopId == workshopId).Select(x => new + // { + // WorkshopId = x.WorkshopId, + // EmployeeId = x.EmployeeId, + // PersonnelCode = 0, + // ContractPerson = true, + // ContractLeft = x.LeftWork != leftDate, + // StartWork = x.StartWork, + // LeftWork = x.LeftWork, + // LastStartContractWork = x.StartWork.ToFarsi(), + // LastLeftContractWork = x.LeftWork != leftDate ? x.LeftWork.ToFarsi() : "-", + // LastStartInsuranceWork = "-", + // LastLeftInsuranceWork = "-", + // LefWorkTemp = x.LeftWorkType == LeftWorkTempType.LeftWork, + // CreatedByClient = x.LeftWorkType == LeftWorkTempType.StartWork + // }).ToList(); + // + // + // var employeeClientTemp = _context.EmployeeClientTemps.Where(x => x.WorkshopId == workshopId).Select(x => new + // { + // WorkshopId = x.WorkshopId, + // EmployeeId = x.EmployeeId, + // PersonnelCode = 0, + // CreatedByClient = true, + // ContractPerson = true + // }).ToList(); + // + // var resultTemp = employeeClientTemp.Concat(leftWorkTemp).ToList().GroupBy(x => x.EmployeeId); + // + // + // + // var result = contractLeftWork.Concat(insuranceLeftWork).GroupBy(x => x.EmployeeId).ToList(); + // + // result = result.Concat(resultTemp).GroupBy(x => x.First().EmployeeId).Select(x => x.First()).ToList(); + // + // var employeeClientTempList = employeeClientTemp.ToList(); + // var startWorkTempsForWorkshop = leftWorkTemp.Where(x => x.CreatedByClient).ToList(); + // var leftWorkTempsForWorkshop = leftWorkTemp.Where(x => x.LefWorkTemp).ToList(); + // + // return result.Select(x => + // { + // var insurance = x.FirstOrDefault(y => y.InsurancePerson); + // var contract = x.FirstOrDefault(y => y.ContractPerson); + // var personnelCode = personnelCodes.FirstOrDefault(y => y.EmployeeId == x.Key); + // var employee = personnelCode.Employee; + // var employeeClient = employeeClientTempList.FirstOrDefault(t => t.EmployeeId == x.First().EmployeeId); + // var startWorkTemp = startWorkTempsForWorkshop.FirstOrDefault(s => s.EmployeeId == x.First().EmployeeId); + // var leftWorkTemp = leftWorkTempsForWorkshop.FirstOrDefault(s => s.EmployeeId == x.First().EmployeeId); + // + // + // return new GetClientEmployeeListViewModel() + // { + // EmployeeId = x.Key, + // FullName = employee.FullName, + // PersonnelCode = personnelCode?.PersonnelCode ?? 0, + // HasContractLeftWork = insurance != null, + // HasInsuranceLeftWork = contract != null, + // + // LeftWorkCompletely = (insurance?.InsuranceLeft ?? false) && (contract?.ContractLeft ?? false), + // + // LastStartInsuranceWork = insurance != null ? insurance.LastStartInsuranceWork : "-", + // LastLeftInsuranceWork = insurance != null ? insurance.LastLeftInsuranceWork : "-", + // LastStartContractWork = contract != null ? contract.LastStartContractWork : "-", + // LastLeftContractWork = contract != null ? contract.LastLeftContractWork : "-", + // + // NationalCode = employee.NationalCode, + // IdNumber = employee.IdNumber, + // MaritalStatus = employee.MaritalStatus, + // DateOfBirthFa = employee.DateOfBirth.ToFarsi(), + // FatherName = employee.FatherName, + // ChildrenCount = employee.EmployeeChildrenList.Count, + // + // PendingStartWork = employeeClient != null || startWorkTemp != null, + // PendingLeftWork = leftWorkTemp != null, + // + // + // }; + // }).OrderByDescending(x => x.StartWork).ToList(); +throw new NotImplementedException(); + } + + #endregion } \ No newline at end of file From 74bd802a3dee251b26f0da96299fb027e6f6c3b3 Mon Sep 17 00:00:00 2001 From: SamSys Date: Wed, 24 Dec 2025 18:24:37 +0330 Subject: [PATCH 10/22] sms settings frontEnd bug fixed --- .../_SmsSettingPartials/_CreateSmsSetting.cshtml | 3 +++ .../_SmsSettingPartials/_EditSmsSetting.cshtml | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_CreateSmsSetting.cshtml b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_CreateSmsSetting.cshtml index 487fddcf..6d7af3b4 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_CreateSmsSetting.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_CreateSmsSetting.cshtml @@ -43,6 +43,9 @@ case TypeOfSmsSetting.Warning: break; + case TypeOfSmsSetting.InstitutionContractConfirm: + + break; } } diff --git a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_EditSmsSetting.cshtml b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_EditSmsSetting.cshtml index ccbd15f0..339cd14f 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_EditSmsSetting.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/_SmsSettingPartials/_EditSmsSetting.cshtml @@ -41,6 +41,10 @@ case TypeOfSmsSetting.Warning: break; + case TypeOfSmsSetting.InstitutionContractConfirm: + + break; + } } public string PaymentAmount { get; set; } + /// + /// مجموع مبالغ بدون تخفیف + /// + public string TotalAmountWithoutDiscount { get; set; } + + /// + /// مبلغ یک ماه بدون تخفیف + /// + public string OneMonthPaymentWithoutDiscount { get; set; } + public string DiscountedAmount { get; set; } public int DiscountPercetage { get; set; } } diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 2d97b743..57c29eb3 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -2361,6 +2361,10 @@ public class InstitutionContractRepository : RepositoryBase=100) + { + throw new BadRequestException("مقدار تخفیف نمی‌تواند برابر یا بیشتر از صد باشد"); + } var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId) .FirstOrDefaultAsync(); if (institutionTemp == null) @@ -2378,7 +2382,7 @@ public class InstitutionContractRepository : RepositoryBase 0) throw new BadRequestException("تخفیف قبلا برای این قرارداد اعمال شده است"); } - + var selectedPlan = institutionTemp.Duration switch { InstitutionContractDuration.OneMonth => institutionTemp.OneMonth, @@ -2401,6 +2405,12 @@ public class InstitutionContractRepository : RepositoryBase Date: Thu, 25 Dec 2025 11:28:29 +0330 Subject: [PATCH 14/22] fix: improve error handling and streamline activation process in ActiveAll method --- .../Repository/EmployerRepository.cs | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/CompanyManagment.EFCore/Repository/EmployerRepository.cs b/CompanyManagment.EFCore/Repository/EmployerRepository.cs index 626cdfa4..c92d2f2e 100644 --- a/CompanyManagment.EFCore/Repository/EmployerRepository.cs +++ b/CompanyManagment.EFCore/Repository/EmployerRepository.cs @@ -722,34 +722,33 @@ public class EmployerRepository : RepositoryBase, IEmployerRepos public OperationResult ActiveAll(long id) { OperationResult result = new OperationResult(); - using (var transaction = _context.Database.BeginTransaction()) + try { - try + var employer = _context.Employers.FirstOrDefault(x => x.id == id); + if (employer == null) { - var employer = _context.Employers.FirstOrDefault(x => x.id == id); - employer.Active(); - - var workshopIds = _context.WorkshopEmployers.Where(x => x.EmployerId == id).Select(x => x.WorkshopId) - .ToList(); - var workshops = _context.Workshops.Where(x => workshopIds.Contains(x.id)).ToList(); - workshops.ForEach(x => x.Active(x.ArchiveCode)); - - var contracts = _context.Contracts.Where(x => workshopIds.Contains(x.WorkshopIds)).ToList(); - contracts.ForEach(x => x.Active()); - - var contractIds = contracts.Select(x => x.id).ToList(); - var checkouts = _context.CheckoutSet.Where(x => contractIds.Contains(x.ContractId)).ToList(); - checkouts.ForEach(x => x.Active()); - - _context.SaveChanges(); - transaction.Commit(); - result.Succcedded(); - } - catch (Exception) - { - result.Failed("فعال کردن کارفرما با خطا مواجه شد"); - transaction.Rollback(); + return result.Failed("کارفرما یافت نشد"); } + employer.Active(); + + var workshopIds = _context.WorkshopEmployers.Where(x => x.EmployerId == id).Select(x => x.WorkshopId) + .ToList(); + var workshops = _context.Workshops.Where(x => workshopIds.Contains(x.id)).ToList(); + workshops.ForEach(x => x.Active(x.ArchiveCode)); + + var contracts = _context.Contracts.Where(x => workshopIds.Contains(x.WorkshopIds)).ToList(); + contracts.ForEach(x => x.Active()); + + var contractIds = contracts.Select(x => x.id).ToList(); + var checkouts = _context.CheckoutSet.Where(x => contractIds.Contains(x.ContractId)).ToList(); + checkouts.ForEach(x => x.Active()); + + _context.SaveChanges(); + result.Succcedded(); + } + catch (Exception) + { + result.Failed("فعال کردن کارفرما با خطا مواجه شد"); } return result; From d254da13931c9ed7fd701f19ab14396051d8d2d8 Mon Sep 17 00:00:00 2001 From: SamSys Date: Thu, 25 Dec 2025 12:32:10 +0330 Subject: [PATCH 15/22] bacgrountTask InstitutionContract some changes --- .../Jobs/JobSchedulerRegistrator.cs | 7 +++++-- .../BackgroundInstitutionContract.Task/Program.cs | 2 +- .../Repository/InstitutionContractRepository.cs | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs index c0d08602..b4a0c823 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs @@ -70,7 +70,7 @@ public class JobSchedulerRegistrator var now =DateTime.Now; var endOfMonth = now.ToFarsi().FindeEndOfMonth(); var endOfMonthGr = endOfMonth.ToGeorgianDateTime(); - + _logger.LogInformation("CreateFinancialTransaction job run"); if (now.Date == endOfMonthGr.Date && now.Hour >= 2 && now.Hour < 4 && now.Date != _lastRunCreateTransaction?.Date) { @@ -115,7 +115,7 @@ public class JobSchedulerRegistrator var now = DateTime.Now; var endOfMonth = now.ToFarsi().FindeEndOfMonth(); var endOfMonthGr = endOfMonth.ToGeorgianDateTime(); - + _logger.LogInformation("SendFirstDayOfMonthSms job run"); if (now.Date == endOfMonthGr.Date && now.Hour >= 10 && now.Hour < 11 && now.Date != _lastRunSendMonthlySms?.Date) { @@ -143,6 +143,7 @@ public class JobSchedulerRegistrator [DisableConcurrentExecution(timeoutInSeconds: 1200)] public async System.Threading.Tasks.Task SendReminderSms() { + _logger.LogInformation("SendReminderSms job run"); await _institutionContractRepository.SendReminderSmsForBackgroundTask(); } @@ -153,6 +154,7 @@ public class JobSchedulerRegistrator [DisableConcurrentExecution(timeoutInSeconds: 100)] public async System.Threading.Tasks.Task SendBlockSms() { + _logger.LogInformation("SendBlockSms job run"); await _institutionContractRepository.SendBlockSmsForBackgroundTask(); } @@ -164,6 +166,7 @@ public class JobSchedulerRegistrator [DisableConcurrentExecution(timeoutInSeconds: 100)] public async System.Threading.Tasks.Task SendInstitutionContractConfirmSms() { + _logger.LogInformation("SendInstitutionContractConfirmSms job run"); await _institutionContractRepository.SendInstitutionContractConfirmSmsTask(); } diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs index 4d36161f..f0bea1de 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs @@ -38,7 +38,7 @@ Log.Logger = new LoggerConfiguration() //NO Microsoft Public log .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - + //.MinimumLevel.Information() .WriteTo.File( path: Path.Combine(logDirectory, "institution-contract-log-.txt"), rollingInterval: RollingInterval.Day, diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 57c29eb3..d474ee53 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -3476,7 +3476,7 @@ public class InstitutionContractRepository : RepositoryBase SendReminderSmsForBackgroundTask() { var now = DateTime.Now; - + _logger.LogInformation("================>> SendReminderSmsForBackgroundTask job run"); // تبدیل تاریخ میلادی به شمسی var persianNow = now.ToFarsi(); From 649242fc761cdea776b05fab48d0a3dcf66c58a3 Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 25 Dec 2025 14:33:00 +0330 Subject: [PATCH 16/22] refactor: optimize institution contract list retrieval and improve workshop group loading --- .../InstitutionContractRepository.cs | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 57c29eb3..96dcc2a3 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1098,19 +1098,27 @@ public class InstitutionContractRepository : RepositoryBase> GetList( InstitutionContractListSearchModel searchModel) { - var query = _context.InstitutionContractSet - .Include(x => x.WorkshopGroup) - .ThenInclude(x => x.InitialWorkshops) - .Include(x => x.WorkshopGroup) - .ThenInclude(x => x.CurrentWorkshops) - .Include(x => x.ContactInfoList).AsNoTracking(); - var now = DateTime.Today; var nowFa = now.ToFarsi(); var endFa = nowFa.FindeEndOfMonth(); var endThisMontGr = endFa.ToGeorgianDateTime(); - var joinedQuery = query.Join(_context.PersonalContractingParties + var contractsWithExtension = await _context.InstitutionContractSet + .Where(x => x.IsActiveString == "true") + .Select(x => new { x.ContractingPartyId, x.ExtensionNo }) + .ToListAsync(); + + var contractsWithExtensionLookup = contractsWithExtension + .GroupBy(x => x.ContractingPartyId) + .ToDictionary( + g => g.Key, + g => g.Max(x => x.ExtensionNo) + ); + + var joinedQuery = _context.InstitutionContractSet + .AsNoTracking() + .Join(_context.PersonalContractingParties + .AsNoTracking() .Include(x => x.Employers) .ThenInclude(x => x.WorkshopEmployers) .ThenInclude(x => x.Workshop), @@ -1138,7 +1146,8 @@ public class InstitutionContractRepository : RepositoryBase e.WorkshopEmployers.Select(we => we.Workshop)).Any() + .SelectMany(e => e.WorkshopEmployers + .Select(we => we.Workshop)).Any() ? (int)InstitutionContractListStatus.WithoutWorkshop : (int)InstitutionContractListStatus.Active }); @@ -1301,6 +1310,15 @@ public class InstitutionContractRepository : RepositoryBase x.contractingParty.id).ToList(); + var contractIds = list.Select(x => x.contract.id).ToList(); + + // بارگذاری WorkshopGroups فقط برای قراردادهای صفحه فعلی + var workshopGroups = await _context.InstitutionContractWorkshopGroups + .AsNoTracking() + .Include(x=>x.InitialWorkshops ) + .Include(x => x.CurrentWorkshops) + .Where(x => contractIds.Contains(x.InstitutionContractId)) + .ToDictionaryAsync(x => x.InstitutionContractId, x => x); var financialStatements = _context.FinancialStatments.Include(x => x.FinancialTransactionList) .Where(x => contractingPartyIds.Contains(x.ContractingPartyId)).ToList(); @@ -1324,13 +1342,19 @@ public class InstitutionContractRepository : RepositoryBase(x.StatusPriority.ToString()); - List currentStateWorkshops = x.contract.WorkshopGroup?.CurrentWorkshops + + // دریافت WorkshopGroup از dictionary بارگذاری شده + workshopGroups.TryGetValue(x.contract.id, out var workshopGroup); + + List currentStateWorkshops = workshopGroup?.CurrentWorkshops .Cast().ToList(); var statement = financialStatements.FirstOrDefault(f => f.ContractingPartyId == x.contractingParty.id); - currentStateWorkshops?.AddRange( - x.contract.WorkshopGroup?.InitialWorkshops.Where(w => !w.WorkshopCreated) ?? []); + if (currentStateWorkshops != null && workshopGroup != null) + { + currentStateWorkshops.AddRange(workshopGroup.InitialWorkshops.Where(w => !w.WorkshopCreated)); + } var workshopDetails = currentStateWorkshops?.Select(w => { @@ -1380,7 +1404,7 @@ public class InstitutionContractRepository : RepositoryBase y.Services.ContractInPerson) ?? true, IsOldContract = x.contract.SigningType == InstitutionContractSigningType.Legacy }; From a98621283404bf896d08c8823edc9fa06854208e Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 25 Dec 2025 15:11:27 +0330 Subject: [PATCH 17/22] add from form to verify gateway --- ServiceHost/Controllers/GeneralController.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ServiceHost/Controllers/GeneralController.cs b/ServiceHost/Controllers/GeneralController.cs index 455c60b4..4854bd4c 100644 --- a/ServiceHost/Controllers/GeneralController.cs +++ b/ServiceHost/Controllers/GeneralController.cs @@ -75,7 +75,7 @@ public class GeneralController : GeneralBaseController } [HttpGet("/api/callback"), HttpPost("/api/callback")] - public async Task Verify(SepehrGatewayPayResponse payResponse) + public async Task Verify([FromForm]SepehrGatewayPayResponse payResponse) { if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId)) { @@ -133,7 +133,12 @@ public class GeneralController : GeneralBaseController DigitalReceipt = payResponse.digitalreceipt }; + var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None); +#if DEBUG + verifyRes.IsSuccess = true; +#endif + _financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now); if (verifyRes.IsSuccess) @@ -158,14 +163,18 @@ public class GeneralController : GeneralBaseController payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(), payResponse.digitalreceipt); - if (financialInvoice.Items?.Any(x => x.Type is FinancialInvoiceItemType.BuyInstitutionContract or FinancialInvoiceItemType.BuyInstitutionContractInstallment) ?? false) + if (financialInvoice.Items?.Any(x => + x.Type is FinancialInvoiceItemType.BuyInstitutionContract + or FinancialInvoiceItemType.BuyInstitutionContractInstallment) ?? false) { var financialItems = financialInvoice.Items .Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContract); foreach (var editFinancialInvoiceItem in financialItems) { - await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId,InstitutionContractSigningType.OtpBased); + await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId, + InstitutionContractSigningType.OtpBased); } + var financialInstallmentItems = financialInvoice.Items .Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContractInstallment); @@ -174,7 +183,8 @@ public class GeneralController : GeneralBaseController var institutionContractId = await _institutionContractApplication.GetIdByInstallmentId( editFinancialInvoiceItem.EntityId); - await _institutionContractApplication.SetPendingWorkflow(institutionContractId,InstitutionContractSigningType.OtpBased); + await _institutionContractApplication.SetPendingWorkflow(institutionContractId, + InstitutionContractSigningType.OtpBased); } } From a6389131721bb5f341b550a930fd9eab3c522a2b Mon Sep 17 00:00:00 2001 From: SamSys Date: Thu, 25 Dec 2025 16:16:50 +0330 Subject: [PATCH 18/22] create levave api and get rotating shift api --- .../Leave/CheckIsInvalidLeaveDto.cs | 15 + .../Leave/CreateLeaveDto.cs | 78 +++++ .../Leave/ILeaveApplication.cs | 28 +- .../Leave/PaidLeaveType.cs | 17 + .../Leave/RotatingShiftDto.cs | 17 + .../LeaveApplication.cs | 311 +++++++++++++++++- .../Client/Controllers/LeaveController.cs | 48 +++ 7 files changed, 501 insertions(+), 13 deletions(-) create mode 100644 CompanyManagment.App.Contracts/Leave/CheckIsInvalidLeaveDto.cs create mode 100644 CompanyManagment.App.Contracts/Leave/CreateLeaveDto.cs create mode 100644 CompanyManagment.App.Contracts/Leave/PaidLeaveType.cs create mode 100644 CompanyManagment.App.Contracts/Leave/RotatingShiftDto.cs diff --git a/CompanyManagment.App.Contracts/Leave/CheckIsInvalidLeaveDto.cs b/CompanyManagment.App.Contracts/Leave/CheckIsInvalidLeaveDto.cs new file mode 100644 index 00000000..656e8e36 --- /dev/null +++ b/CompanyManagment.App.Contracts/Leave/CheckIsInvalidLeaveDto.cs @@ -0,0 +1,15 @@ +namespace CompanyManagment.App.Contracts.Leave; + +public class CheckIsInvalidLeaveDto +{ + /// + /// آیا تعطیل است + /// + public bool IsHoliday { get; set; } + + /// + /// فاقد/دارای اعتبار فیش غیر رسمی + /// + public bool CanCreateInvalid { get; set; } + +} \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/Leave/CreateLeaveDto.cs b/CompanyManagment.App.Contracts/Leave/CreateLeaveDto.cs new file mode 100644 index 00000000..8f9c9f63 --- /dev/null +++ b/CompanyManagment.App.Contracts/Leave/CreateLeaveDto.cs @@ -0,0 +1,78 @@ +using CompanyManagment.App.Contracts.CustomizeWorkshopSettings; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using _0_Framework.Domain.CustomizeCheckoutShared.Enums; + +namespace CompanyManagment.App.Contracts.Leave; + +public class CreateLeaveDto +{ + /// + /// تاریخ شروع مرخصی + /// + [Required(ErrorMessage = "این مقدار نمی تواند خالی باشد")] + public string StartLeave { get; set; } + + + /// + /// تاریخ پایان مرخصی + /// + [Required(ErrorMessage = "این مقدار نمی تواند خالی باشد")] + public string EndLeave { get; set; } + + /// + /// آی دی کارگاه + /// + public long WorkshopId { get; set; } + + /// + /// آی دی پرسنل + /// + public long EmployeeId { get; set; } + + /// + /// نوع مدت مرخص روزانه/ ساعتی + /// + public PaidLeaveType PaidLeaveType { get; set; } + + /// + /// نوع مرخصی استحقاقی/استعلاجی + /// + public LeaveType LeaveType { get; set; } + + /// + /// نام کامل کارگاه + /// + public string WorkshopName { get; set; } + + /// + /// ساعت شروع مرخصی + /// + public string StartHoures { get; set; } + + /// + /// ساعت پایان مرخصی + /// + public string EndHours { get; set; } + + /// + /// موافقت / عدم موافقت کارفرما + /// + public bool IsAccepted { get; set; } + + /// + /// توضیحات + /// + public string Decription { get; set; } + + + public List RotatingShifts { get; set; } + + /// + /// دارای اعتبار / فاقد اعتبار فیش غیررسمی + /// + public bool IsInvallid { get; set; } + public CustomizeRotatingShiftsViewModel SelectedShift { get; set; } + +} \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs index 4185d007..3234526e 100644 --- a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs +++ b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs @@ -70,7 +70,33 @@ public interface ILeaveApplication Task> PrintAllAsync(List ids, long workshopId); Task PrintOneAsync(long id, long workshopId); - + + /// + /// چک میکند که تاریخ وارد شده در شروع مرخصی تعطیل است یا خیر + /// دارای/فاقد اعتبار فیش غیررسمی را چک میکند + /// + /// + /// + /// + Task> CheckIsInvalidLeave(string startLeaveDate, long workshopId); + + /// + /// ایجاد مرخصی از ای پی آی + /// + /// + /// + Task CreateLeave(CreateLeaveDto command); + + /// + /// چک میکند که آیا پرسنل حضور غیاب دارای شیفت گردشی دارد یا خیر + /// اگر داشت دریافت شیف گردشی + /// + /// + /// + /// + /// + Task> HasRotatingShift(long workshopId, long employeeId, string startLeaveDate); + } public class LeavePrintResponseViewModel diff --git a/CompanyManagment.App.Contracts/Leave/PaidLeaveType.cs b/CompanyManagment.App.Contracts/Leave/PaidLeaveType.cs new file mode 100644 index 00000000..b77340bf --- /dev/null +++ b/CompanyManagment.App.Contracts/Leave/PaidLeaveType.cs @@ -0,0 +1,17 @@ +namespace CompanyManagment.App.Contracts.Leave; + +/// +/// نوع مدت مرخصی +/// +public enum PaidLeaveType +{ + /// + /// روزانه + /// + Daily, + + /// + /// ساعتی + /// + Hourly, +} \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/Leave/RotatingShiftDto.cs b/CompanyManagment.App.Contracts/Leave/RotatingShiftDto.cs new file mode 100644 index 00000000..b22120e6 --- /dev/null +++ b/CompanyManagment.App.Contracts/Leave/RotatingShiftDto.cs @@ -0,0 +1,17 @@ +using CompanyManagment.App.Contracts.CustomizeWorkshopSettings; +using System.Collections.Generic; + +namespace CompanyManagment.App.Contracts.Leave; + +public class RotatingShiftDto +{ + /// + /// آیا حضورغیاب به همراه گروهبندی گردشی دارد + /// + public bool HasRollCall {get; set;} + + /// + /// لیست شیفت های گردشی پرسنل + /// + public List RotatingShifts { get; set; } +} \ No newline at end of file diff --git a/CompanyManagment.Application/LeaveApplication.cs b/CompanyManagment.Application/LeaveApplication.cs index 63c50d32..1b3a998a 100644 --- a/CompanyManagment.Application/LeaveApplication.cs +++ b/CompanyManagment.Application/LeaveApplication.cs @@ -1,18 +1,25 @@ -using System; +using _0_Framework.Application; +using _0_Framework.Domain.CustomizeCheckoutShared.Enums; +using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg; +using Company.Domain.EmployeeAgg; +using Company.Domain.HolidayItemAgg; +using Company.Domain.LeaveAgg; +using Company.Domain.RollCallAgg; +using Company.Domain.RollCallServiceAgg; +using Company.Domain.WorkshopAgg; +using CompanyManagment.App.Contracts.CustomizeWorkshopSettings; +using CompanyManagment.App.Contracts.HolidayItem; +using CompanyManagment.App.Contracts.Leave; +using CompanyManagment.App.Contracts.RollCallEmployeeStatus; +using CompanyManagment.App.Contracts.RollCallService; +using CompanyManagment.EFCore.Migrations; +using Microsoft.AspNetCore.Mvc; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; -using _0_Framework.Application; -using _0_Framework.Domain.CustomizeCheckoutShared.Enums; -using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg; -using Company.Domain.EmployeeAgg; -using Company.Domain.LeaveAgg; -using Company.Domain.RollCallAgg; -using Company.Domain.WorkshopAgg; -using CompanyManagment.App.Contracts.Leave; -using CompanyManagment.App.Contracts.RollCallEmployeeStatus; namespace CompanyManagment.Application; @@ -24,9 +31,12 @@ public class LeaveApplication : ILeaveApplication private readonly IRollCallRepository _rollCallRepository; private readonly ICustomizeWorkshopEmployeeSettingsRepository _employeeSettingsRepository; private readonly IRollCallEmployeeStatusApplication _rollCallEmployeeStatusApplication; + private readonly IHolidayItemRepository _holidayItemRepository; + private readonly IRollCallServiceRepository _rollCallServiceRepository; + - public LeaveApplication(ILeaveRepository leaveRepository, IEmployeeRepository employeeRepository, IWorkshopRepository workshopRepository, IRollCallRepository rollCallRepository, ICustomizeWorkshopEmployeeSettingsRepository employeeSettingsRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication) + public LeaveApplication(ILeaveRepository leaveRepository, IEmployeeRepository employeeRepository, IWorkshopRepository workshopRepository, IRollCallRepository rollCallRepository, ICustomizeWorkshopEmployeeSettingsRepository employeeSettingsRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, IHolidayItemRepository holidayItemRepository, IRollCallServiceRepository rollCallServiceRepository) { _leaveRepository = leaveRepository; _employeeRepository = employeeRepository; @@ -34,6 +44,8 @@ public class LeaveApplication : ILeaveApplication _rollCallRepository = rollCallRepository; _employeeSettingsRepository = employeeSettingsRepository; _rollCallEmployeeStatusApplication = rollCallEmployeeStatusApplication; + _holidayItemRepository = holidayItemRepository; + _rollCallServiceRepository = rollCallServiceRepository; } public OperationResult Create(CreateLeave command) @@ -238,7 +250,7 @@ public class LeaveApplication : ILeaveApplication var employeeFullName = _employeeRepository.GetDetails(command.EmployeeId).EmployeeFullName; var workshopName = _workshopRepository.GetDetails(command.WorkshopId).WorkshopName; - var leave = new Leave(start, end, totalhourses, command.WorkshopId, command.EmployeeId + var leave = new Company.Domain.LeaveAgg.Leave(start, end, totalhourses, command.WorkshopId, command.EmployeeId , command.PaidLeaveType, command.LeaveType, employeeFullName, workshopName, command.IsAccepted, command.Decription, year, month, shiftDuration, hasShiftDuration,command.IsInvallid); _leaveRepository.Create(leave); @@ -672,5 +684,280 @@ public class LeaveApplication : ILeaveApplication return (await _leaveRepository.PrintAllAsync([id],workshopId)).FirstOrDefault(); } + + public async Task> CheckIsInvalidLeave(string startLeaveDate, long workshopId) + { + var op = new OperationResult(); + var result = new CheckIsInvalidLeaveDto(); + if (startLeaveDate.TryToGeorgianDateTime(out var startLeaveDateGr) == false) + { + return op.Failed("تاریخ وارد شده صحیح نیست"); + } + + if (startLeaveDateGr.DayOfWeek == DayOfWeek.Friday || _holidayItemRepository.GetHoliday(startLeaveDateGr)) + { + result.IsHoliday = true; + } + + if (result.IsHoliday) + { + var rollCallService = _rollCallServiceRepository.GetActiveServiceByWorkshopId(workshopId); + if (rollCallService != null) + { + result.CanCreateInvalid = rollCallService.HasCustomizeCheckoutService == "true"; + } + } + + return op.Succcedded(result); + } + + + public async Task CreateLeave(CreateLeaveDto command) + { + TimeSpan shiftDuration = TimeSpan.Zero; + bool hasShiftDuration = false; + var startH = new TimeSpan(); + var endH = new TimeSpan(); + var op = new OperationResult(); + if ((command.PaidLeaveType == PaidLeaveType.Daily && command.LeaveType == LeaveType.PaidLeave) || command.LeaveType == LeaveType.SickLeave) + { + if (string.IsNullOrWhiteSpace(command.StartLeave)) + { + return op.Failed("لطفا تاریخ شروع را وارد کنید"); + } + if (string.IsNullOrWhiteSpace(command.EndLeave)) + { + return op.Failed("لطفا تاریخ پایان را وارد کنید"); + } + } + else if (command.PaidLeaveType == PaidLeaveType.Hourly) + { + if (string.IsNullOrWhiteSpace(command.StartLeave)) + return op.Failed("لطفا تاریخ شروع را وارد کنید"); + if (string.IsNullOrWhiteSpace(command.StartHoures) || string.IsNullOrWhiteSpace(command.EndHours)) + return op.Failed("ساعت شروع و پایان نمیتواند خالی باشد"); + + string pattern = @"^([01]\d|2[0-3]):[0-5]\d$"; + + if (!Regex.IsMatch(command.StartHoures, pattern)) + return op.Failed("لطفا ساعت شروع را به درستی وارد کنید"); + + if (!Regex.IsMatch(command.EndHours, pattern)) + return op.Failed("لطفا ساعت پایان را به درستی وارد کنید"); + + startH = TimeSpan.Parse(command.StartHoures); + endH = TimeSpan.Parse(command.EndHours); + if (startH == endH) + return op.Failed("ساعت شروع و پایان نباید برابر باشد"); + } + + + //if (command.LeaveType == LeaveType.SickLeave && string.IsNullOrWhiteSpace(command.StartLeave)) + // return op.Failed("لطفا تاریخ شروع را وارد کنید"); + //if (command.LeaveType == LeaveType.SickLeave && string.IsNullOrWhiteSpace(command.EndLeave)) + // return op.Failed("لطفا تاریخ پایان را وارد کنید"); + + + if (command.StartLeave.TryToGeorgianDateTime(out var start) == false) + { + return op.Failed("تاریخ شروع صحیح نیست"); + } + + var end = new DateTime(); + if (command.PaidLeaveType == PaidLeaveType.Daily) + { + if (command.EndLeave.TryToGeorgianDateTime(out end) == false) + { + return op.Failed("تاریخ پایان صحیح نیست"); + } + } + end = start; + + + var checkErr = _leaveRepository.CheckErrors(start, end, command.EmployeeId, command.WorkshopId, command.IsInvallid); + + + if (checkErr.HasChekout) + return op.Failed(checkErr.CheckoutErrMessage); + if (checkErr.HasNotContract) + return op.Failed(checkErr.ContractErrMessage); + if (checkErr.HasLeftWork) + return op.Failed(checkErr.LeftWorlErrMessage); + + if (start > end) + return op.Failed("تارخ شروع از پایان بزرگتر است"); + + + var totalhourses = "-"; + if (command.LeaveType == LeaveType.PaidLeave && command.PaidLeaveType == PaidLeaveType.Hourly) + { + + start = new DateTime(start.Year, start.Month, start.Day, startH.Hours, startH.Minutes, startH.Seconds); + end = new DateTime(start.Year, start.Month, start.Day, endH.Hours, endH.Minutes, endH.Seconds); + if (start > end) + end = end.AddDays(1); + + var totalLeavHourses = (end - start); + var h = totalLeavHourses.Hours < 10 ? $"0{totalLeavHourses.Hours}" : $"{totalLeavHourses.Hours}"; + var m = totalLeavHourses.Minutes < 10 ? $"0{totalLeavHourses.Minutes}" : $"{totalLeavHourses.Minutes}"; + totalhourses = $"{h}:{m}"; + + if (_leaveRepository.Exists(x => + x.StartLeave <= start && x.EndLeave >= start && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "ساعتی")) + return op.Failed("برای ساعت شروع سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave <= end && x.EndLeave >= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "ساعتی")) + return op.Failed("برای ساعت پایان سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave >= start && x.EndLeave <= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "ساعتی")) + return op.Failed("در بازه زمانی وارد شده مرخصی ثبت شده است"); + + var end24 = endH.Hours == 0 && endH.Minutes == 0 ? end.AddDays(-1) : end; + if (_leaveRepository.Exists(x => + (x.StartLeave.Date == start.Date || x.EndLeave.Date == end24.Date) && (x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه"))) + return op.Failed("در بازه زمانی وارد شده مرخصی ثبت شده است"); + } + else if (command.LeaveType == LeaveType.PaidLeave && command.PaidLeaveType == PaidLeaveType.Daily) + { + var totalLeavHourses = (end - start).TotalDays + 1; + totalhourses = $"{(int)totalLeavHourses}"; + if (_leaveRepository.Exists(x => + x.StartLeave <= start && x.EndLeave >= start && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("برای تاریخ شروع سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave <= end && x.EndLeave >= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("برای تاریخ پایان سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave >= start && x.EndLeave <= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("در بازه زمانی وارد شده مرخصی ثبت شده است"); + if (_leaveRepository.Exists(x => + x.StartLeave.Date >= start.Date && x.StartLeave.Date <= end.Date && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "ساعتی")) + return op.Failed("دربازه تاریخ وارد شده مرخصی ساعتی ثبت شده است"); + + var employeeSettings = _employeeSettingsRepository.GetByEmployeeIdAndWorkshopIdIncludeGroupSettings(command.WorkshopId, command.EmployeeId); + + var isActive = _rollCallEmployeeStatusApplication.IsActiveInPeriod(command.EmployeeId, command.WorkshopId, start, end); + var hasRollCall = isActive && employeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating; + if (hasRollCall) + { + + if ((end - start).TotalDays > 1 && employeeSettings.WorkshopShiftStatus != WorkshopShiftStatus.Regular) + { + return op.Failed("شما نمیتوانید بیشتر از یک روز مرخصی روزانه ثبت کنید"); + } + + if (employeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating && + command.SelectedShift == null) + { + return op.Failed("لطفا شیفت پرسنل را انتخاب کنید"); + } + + if (command.SelectedShift != null) + { + var validShiftStart = TimeOnly.TryParse(command.SelectedShift.StartTime, out var shiftStart); + var validShiftEnd = TimeOnly.TryParse(command.SelectedShift.EndTime, out var shiftEnd); + + if (validShiftStart == false && validShiftEnd == false) + { + return op.Failed("شیفت های انتخاب شده معتبر نمیباشد"); + } + + var shiftStartDateTime = new DateTime(new DateOnly(), shiftStart); + var shiftEndDateTime = new DateTime(new DateOnly(), shiftEnd); + if (shiftEndDateTime <= shiftStartDateTime) + shiftEndDateTime = shiftEndDateTime.AddDays(1); + shiftDuration = shiftEndDateTime - shiftStartDateTime; + hasShiftDuration = true; + } + else if (employeeSettings is { WorkshopShiftStatus: WorkshopShiftStatus.Irregular }) + { + if ((end - start).TotalDays > 1) + { + return op.Failed("شما نمیتوانید بیشتر از یک روز مرخصی روزانه ثبت کنید"); + } + + + if (isActive) + { + shiftDuration = employeeSettings.IrregularShift.WorkshopIrregularShifts switch + { + WorkshopIrregularShifts.TwelveThirtySix => TimeSpan.FromHours(12), + WorkshopIrregularShifts.TwelveTwentyFour => TimeSpan.FromHours(12), + WorkshopIrregularShifts.TwentyFourFortyEight => TimeSpan.FromHours(24), + WorkshopIrregularShifts.TwentyFourTwentyFour => TimeSpan.FromHours(24), + _ => new TimeSpan() + }; + hasShiftDuration = true; + } + + } + } + + + } + + if (command.LeaveType == LeaveType.SickLeave) + { + var totalLeavHourses = (end - start).TotalDays + 1; + totalhourses = $"{(int)totalLeavHourses}"; + command.PaidLeaveType = PaidLeaveType.Daily; + if (_leaveRepository.Exists(x => + x.StartLeave <= start && x.EndLeave >= start && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("برای تاریخ شروع سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave <= end && x.EndLeave >= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("برای تاریخ پایان سابقه مرخصی وجود دارد"); + if (_leaveRepository.Exists(x => + x.StartLeave >= start && x.EndLeave <= end && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "روزانه")) + return op.Failed("در بازه زمانی وارد شده مرخصی ثبت شده است"); + if (_leaveRepository.Exists(x => + x.StartLeave.Date >= start.Date && x.StartLeave.Date <= end.Date && x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId && x.PaidLeaveType == "ساعتی")) + return op.Failed("دربازه تاریخ وارد شده مرخصی ساعتی ثبت شده است"); + } + var year = Convert.ToInt32(command.StartLeave.Substring(0, 4)); + var month = Convert.ToInt32(command.StartLeave.Substring(5, 2)); + var paidLeaveType = command.PaidLeaveType == PaidLeaveType.Daily ? "روزانه" : "ساعتی"; + var leaveType = command.LeaveType == LeaveType.PaidLeave ? "استحقاقی" : "استعلاجی"; + var validation = ValidateNewLeaveWithExistingRollCalls(command.WorkshopId, command.EmployeeId, paidLeaveType, start, end); + if (validation.IsSuccedded == false) + return validation; + + var employeeFullName = _employeeRepository.GetDetails(command.EmployeeId).EmployeeFullName; + var workshopName = _workshopRepository.GetDetails(command.WorkshopId).WorkshopName; + var leave = new Company.Domain.LeaveAgg.Leave(start, end, totalhourses, command.WorkshopId, command.EmployeeId + , paidLeaveType, leaveType, employeeFullName, workshopName, command.IsAccepted, command.Decription, + year, month, shiftDuration, hasShiftDuration, command.IsInvallid); + await _leaveRepository.CreateAsync(leave); + await _leaveRepository.SaveChangesAsync(); + return op.Succcedded(); + } + + + public async Task> HasRotatingShift(long workshopId,long employeeId, string startLeaveDate) + { + var op = new OperationResult(); + var result = new RotatingShiftDto(); + if (startLeaveDate.TryToGeorgianDateTime(out var startDateTimeGr) == false) + { + return op.Failed("تاریخ شروع صحیح نیست"); + } + var employeeSettings = _employeeSettingsRepository.GetByEmployeeIdAndWorkshopIdIncludeGroupSettings(workshopId, employeeId); + //اگر گروه بندی نداشت + if (employeeSettings == null) + { + return op.Succcedded(result); + } + + var isActive = _rollCallEmployeeStatusApplication.IsActiveInPeriod(employeeId, workshopId, startDateTimeGr, startDateTimeGr); + + result.HasRollCall = isActive && employeeSettings.WorkshopShiftStatus == WorkshopShiftStatus.Rotating; + result.RotatingShifts = employeeSettings.CustomizeRotatingShifts.Select(x => + new CustomizeRotatingShiftsViewModel() + { + EndTime = x.EndTime.ToString("HH:mm"), + StartTime = x.StartTime.ToString("HH:mm") + }).ToList(); + return op.Succcedded(result); + } #endregion } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/LeaveController.cs b/ServiceHost/Areas/Client/Controllers/LeaveController.cs index 8e94d7e1..255d5b0e 100644 --- a/ServiceHost/Areas/Client/Controllers/LeaveController.cs +++ b/ServiceHost/Areas/Client/Controllers/LeaveController.cs @@ -1,5 +1,6 @@ using _0_Framework.Application; using Company.Domain.EmployeeAgg; +using CompanyManagment.App.Contracts.InstitutionPlan; using CompanyManagment.App.Contracts.InsuranceList; using CompanyManagment.App.Contracts.Leave; using Microsoft.AspNetCore.Mvc; @@ -47,14 +48,61 @@ public class LeaveController : ClientBaseController return Ok(result); } + /// + /// چک کردن تاریخ شروع مرخصی + /// + /// + /// + [HttpGet("CheckIsInvalidLeave")] + public async Task> CheckIsInvalidLeave(string startLeaveDate) + { + return await _leaveApplication.CheckIsInvalidLeave(startLeaveDate, _workshopId); + } + /// + /// ایجاد مرخصی + /// + /// + /// + [HttpPost("CreateLeave")] + public async Task> CreateLeave([FromBody] CreateLeaveDto command) + { + command.WorkshopId = _workshopId; + var result = await _leaveApplication.CreateLeave(command); + + return result; + } + + /// + /// دریافت شیفت گردشی اگر داشت + /// + /// + /// + [HttpGet("GetRotatingShift")] + public async Task> GetRotatingShift(long employeeId, string startLeaveDate) + { + + return await _leaveApplication.HasRotatingShift(_workshopId, employeeId, startLeaveDate); + } + + /// + /// پرینت تکی + /// + /// + /// [HttpGet("print/{id}")] public async Task> PrintOneAsync(long id) { var leavePrint = await _leaveApplication.PrintOneAsync(id, _workshopId); return leavePrint; } + + /// + /// پرینت گروهی + /// + /// + /// [HttpGet("print")] public async Task>> PrintAllAsync([FromQuery] List ids) { From 54e5904951be682f3edd9b30eeb43556477a633c Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 25 Dec 2025 15:11:27 +0330 Subject: [PATCH 19/22] add from form to verify gateway --- ServiceHost/Controllers/GeneralController.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ServiceHost/Controllers/GeneralController.cs b/ServiceHost/Controllers/GeneralController.cs index 455c60b4..4854bd4c 100644 --- a/ServiceHost/Controllers/GeneralController.cs +++ b/ServiceHost/Controllers/GeneralController.cs @@ -75,7 +75,7 @@ public class GeneralController : GeneralBaseController } [HttpGet("/api/callback"), HttpPost("/api/callback")] - public async Task Verify(SepehrGatewayPayResponse payResponse) + public async Task Verify([FromForm]SepehrGatewayPayResponse payResponse) { if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId)) { @@ -133,7 +133,12 @@ public class GeneralController : GeneralBaseController DigitalReceipt = payResponse.digitalreceipt }; + var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None); +#if DEBUG + verifyRes.IsSuccess = true; +#endif + _financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now); if (verifyRes.IsSuccess) @@ -158,14 +163,18 @@ public class GeneralController : GeneralBaseController payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(), payResponse.digitalreceipt); - if (financialInvoice.Items?.Any(x => x.Type is FinancialInvoiceItemType.BuyInstitutionContract or FinancialInvoiceItemType.BuyInstitutionContractInstallment) ?? false) + if (financialInvoice.Items?.Any(x => + x.Type is FinancialInvoiceItemType.BuyInstitutionContract + or FinancialInvoiceItemType.BuyInstitutionContractInstallment) ?? false) { var financialItems = financialInvoice.Items .Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContract); foreach (var editFinancialInvoiceItem in financialItems) { - await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId,InstitutionContractSigningType.OtpBased); + await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId, + InstitutionContractSigningType.OtpBased); } + var financialInstallmentItems = financialInvoice.Items .Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContractInstallment); @@ -174,7 +183,8 @@ public class GeneralController : GeneralBaseController var institutionContractId = await _institutionContractApplication.GetIdByInstallmentId( editFinancialInvoiceItem.EntityId); - await _institutionContractApplication.SetPendingWorkflow(institutionContractId,InstitutionContractSigningType.OtpBased); + await _institutionContractApplication.SetPendingWorkflow(institutionContractId, + InstitutionContractSigningType.OtpBased); } } From c488f61a098aa0d93ed5b5ba8ee39d2219aa41f8 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 27 Dec 2025 10:26:12 +0330 Subject: [PATCH 20/22] refactor: enhance error logging and add installment amount to institution contract view model --- .../Handler/CustomExceptionHandler.cs | 10 ++-- ...etInstitutionContractListItemsViewModel.cs | 5 ++ .../InstitutionContractRepository.cs | 46 +++++++++++++++---- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs b/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs index 3af1276d..0d57a94f 100644 --- a/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs +++ b/0_Framework/Exceptions/Handler/CustomExceptionHandler.cs @@ -24,9 +24,13 @@ public class CustomExceptionHandler : IExceptionHandler public async ValueTask TryHandleAsync(HttpContext context, Exception exception, CancellationToken cancellationToken) { - _logger.LogError( - "Error Message: {exceptionMessage}, Time of occurrence {time}", - exception.Message, DateTime.UtcNow); + _logger.LogError(exception, + "Error Message: {exceptionMessage}, Type: {exceptionType}, Time: {time}, Path: {path}, TraceId: {traceId}", + exception.Message, + exception.GetType().FullName, + DateTime.UtcNow, + context.Request.Path, + context.TraceIdentifier); (string Detail, string Title, int StatusCode, Dictionary? Extra) details = exception switch { diff --git a/CompanyManagment.App.Contracts/InstitutionContract/GetInstitutionContractListItemsViewModel.cs b/CompanyManagment.App.Contracts/InstitutionContract/GetInstitutionContractListItemsViewModel.cs index 123dc18a..7ba3aaa0 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/GetInstitutionContractListItemsViewModel.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/GetInstitutionContractListItemsViewModel.cs @@ -91,6 +91,11 @@ public class GetInstitutionContractListItemsViewModel public bool IsInPersonContract { get; set; } public bool IsOldContract { get; set; } + + /// + /// مبلغ قسط + /// + public double InstallmentAmount { get; set; } } public class InstitutionContractListWorkshop diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 96dcc2a3..6255ab29 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1108,14 +1108,15 @@ public class InstitutionContractRepository : RepositoryBase new { x.ContractingPartyId, x.ExtensionNo }) .ToListAsync(); - var contractsWithExtensionLookup = contractsWithExtension - .GroupBy(x => x.ContractingPartyId) - .ToDictionary( - g => g.Key, - g => g.Max(x => x.ExtensionNo) - ); + // var contractsWithExtensionLookup = contractsWithExtension + // .GroupBy(x => x.ContractingPartyId) + // .ToDictionary( + // g => g.Key, + // g => g.Max(x => x.ExtensionNo) + // ); - var joinedQuery = _context.InstitutionContractSet + var rawQuery = _context.InstitutionContractSet + .Include(x=>x.Installments) .AsNoTracking() .Join(_context.PersonalContractingParties .AsNoTracking() @@ -1124,8 +1125,14 @@ public class InstitutionContractRepository : RepositoryBase x.Workshop), contract => contract.ContractingPartyId, contractingParty => contractingParty.id, - (contract, contractingParty) => new { contract, contractingParty }) - .Select(x => new + (contract, contractingParty) => new { contract, contractingParty }); + + // var pendingForRenewalContracts = _context.InstitutionContractSet.AsNoTracking() + // .Where(c => c.IsActiveString == "true" && + // c.ContractEndGr >= now && + // c.ContractEndGr <= endThisMontGr); + + var joinedQuery = rawQuery.Select(x => new { x.contract, x.contractingParty, @@ -1384,9 +1391,28 @@ public class InstitutionContractRepository : RepositoryBase workshops.Select(w => w.id).Contains(l.WorkshopId)) .Count(l => l.StartWorkDate <= DateTime.Now && l.LeftWorkDate >= DateTime.Now); + + + var contractAmount = x.contract.SigningType is not InstitutionContractSigningType.Legacy + && !x.contract.IsInstallment? + x.contract.TotalAmount:0; + + var installmentAmount = 0d; + try + { + installmentAmount =x.contract.SigningType == InstitutionContractSigningType.Legacy + ?x.contract.ContractAmount : x.contract.IsInstallment ? x.contract.Installments.First().Amount :0; + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + return new GetInstitutionContractListItemsViewModel() { - ContractAmount = x.contract.ContractAmountWithTax, + ContractAmount = contractAmount, + InstallmentAmount = installmentAmount, Balance = statement?.FinancialTransactionList.Sum(ft => ft.Deptor - ft.Creditor) ?? 0, WorkshopsCount = workshops.Count(), ContractStartFa = x.contract.ContractStartGr.ToFarsi(), From 54c67fe8f71702bdfb189a94d5c993516554b4fb Mon Sep 17 00:00:00 2001 From: SamSys Date: Sat, 27 Dec 2025 12:06:02 +0330 Subject: [PATCH 21/22] add ListPrint --- .../Leave/LeavePrintListDto.cs | 71 +++++++++++++++++++ .../Client/Controllers/LeaveController.cs | 16 ++++- 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs diff --git a/CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs b/CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs new file mode 100644 index 00000000..7a614219 --- /dev/null +++ b/CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; + +namespace CompanyManagment.App.Contracts.Leave; + +public class LeavePrintListDto +{ + + /// + /// نام کامل پرسنل + /// + public string EmployeeFullName { get; set; } + + /// + /// لیست مرخصی + /// + public List LeavePrintListItemsDto { get; set; } + + /// + /// مجموع مرخصی پرسنل + /// + public string? SumOfEmployeeleaves { get; set; } +} + +public class LeavePrintListItemsDto +{ + /// + /// سال مرخصی + /// + public string YearStr { get; set; } + + /// + /// ماه مرخصی + /// + public string MonthStr { get; set; } + + + /// + /// نوع مرخصی، استحقاقی/استعلاجی + /// + public string LeaveType { get; set; } + + + /// + /// تاریخ شروع مرخصی + /// + public string StartLeave { get; set; } + + /// + /// تاریخ پایان مرخصی + /// + public string EndLeave { get; set; } + + + /// + /// زمان مرخصی + /// بازه مرخصی ساعتی + /// + public string HourlyInterval { get; set; } + + + /// + /// مدت مرخصی + /// + public string LeaveDuration { get; set; } + + /// + /// موافقت/عدم موافقت کارفرما + /// + public bool IsAccepted { get; set; } + +} diff --git a/ServiceHost/Areas/Client/Controllers/LeaveController.cs b/ServiceHost/Areas/Client/Controllers/LeaveController.cs index 255d5b0e..21d39aaa 100644 --- a/ServiceHost/Areas/Client/Controllers/LeaveController.cs +++ b/ServiceHost/Areas/Client/Controllers/LeaveController.cs @@ -104,10 +104,22 @@ public class LeaveController : ClientBaseController /// /// [HttpGet("print")] - public async Task>> PrintAllAsync([FromQuery] List ids) + public async Task>> PrintAllAsync([FromQuery] List ids, LeaveListSearchModel searchModel) { var leavePrints = await _leaveApplication.PrintAllAsync(ids, _workshopId); return Ok(leavePrints); } - + + /// + /// پرینت گروهی + /// + /// + /// + [HttpGet("ListPrint")] + public async Task> ListPrint([FromQuery] List ids,) + { + var leavePrints = await _leaveApplication.PrintAllAsync(ids, _workshopId); + return Ok(leavePrints); + } + } From ba778bb519921346eb9e1a6810a3102f89c96ac2 Mon Sep 17 00:00:00 2001 From: SamSys Date: Sat, 27 Dec 2025 14:06:10 +0330 Subject: [PATCH 22/22] LeaveListPrint --- Company.Domain/LeaveAgg/ILeaveRepository.cs | 7 +++ .../Leave/ILeaveApplication.cs | 7 +++ ...vePrintListDto.cs => LeaveListPrintDto.cs} | 16 ++++-- .../LeaveApplication.cs | 6 +++ .../Repository/LeaveRepository.cs | 53 ++++++++++++++++++- .../Client/Controllers/LeaveController.cs | 6 +-- 6 files changed, 85 insertions(+), 10 deletions(-) rename CompanyManagment.App.Contracts/Leave/{LeavePrintListDto.cs => LeaveListPrintDto.cs} (94%) diff --git a/Company.Domain/LeaveAgg/ILeaveRepository.cs b/Company.Domain/LeaveAgg/ILeaveRepository.cs index 93d5009b..293114ea 100644 --- a/Company.Domain/LeaveAgg/ILeaveRepository.cs +++ b/Company.Domain/LeaveAgg/ILeaveRepository.cs @@ -54,4 +54,11 @@ public interface ILeaveRepository : IRepository /// /// Task> GetGroupList(LeaveListSearchModel searchModel); + + /// + /// پرینت لیستی + /// + /// + /// + Task ListPrint(List ids); } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs index 3234526e..95548f1f 100644 --- a/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs +++ b/CompanyManagment.App.Contracts/Leave/ILeaveApplication.cs @@ -97,6 +97,13 @@ public interface ILeaveApplication /// Task> HasRotatingShift(long workshopId, long employeeId, string startLeaveDate); + /// + /// پرینت لیستی + /// + /// + /// + Task ListPrint(List ids); + } public class LeavePrintResponseViewModel diff --git a/CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs b/CompanyManagment.App.Contracts/Leave/LeaveListPrintDto.cs similarity index 94% rename from CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs rename to CompanyManagment.App.Contracts/Leave/LeaveListPrintDto.cs index 7a614219..caae96a3 100644 --- a/CompanyManagment.App.Contracts/Leave/LeavePrintListDto.cs +++ b/CompanyManagment.App.Contracts/Leave/LeaveListPrintDto.cs @@ -2,7 +2,11 @@ namespace CompanyManagment.App.Contracts.Leave; -public class LeavePrintListDto +/// +/// پرینت لیستی +/// api +/// +public class LeaveListPrintDto { /// @@ -10,15 +14,17 @@ public class LeavePrintListDto /// public string EmployeeFullName { get; set; } + /// + /// مجموع مرخصی پرسنل + /// + public string? SumOfEmployeeleaves { get; set; } + /// /// لیست مرخصی /// public List LeavePrintListItemsDto { get; set; } - /// - /// مجموع مرخصی پرسنل - /// - public string? SumOfEmployeeleaves { get; set; } + } public class LeavePrintListItemsDto diff --git a/CompanyManagment.Application/LeaveApplication.cs b/CompanyManagment.Application/LeaveApplication.cs index 1b3a998a..2bcffefe 100644 --- a/CompanyManagment.Application/LeaveApplication.cs +++ b/CompanyManagment.Application/LeaveApplication.cs @@ -960,4 +960,10 @@ public class LeaveApplication : ILeaveApplication return op.Succcedded(result); } #endregion + + + public async Task ListPrint(List ids) + { + return await _leaveRepository.ListPrint(ids); + } } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/LeaveRepository.cs b/CompanyManagment.EFCore/Repository/LeaveRepository.cs index b4a86ff3..de080e64 100644 --- a/CompanyManagment.EFCore/Repository/LeaveRepository.cs +++ b/CompanyManagment.EFCore/Repository/LeaveRepository.cs @@ -1,9 +1,7 @@ using _0_Framework.Application; using _0_Framework.InfraStructure; -using Azure.Core; using Company.Domain.LeaveAgg; using CompanyManagment.App.Contracts.Checkout; -using CompanyManagment.App.Contracts.InstitutionPlan; using CompanyManagment.App.Contracts.Leave; using Microsoft.EntityFrameworkCore; using System; @@ -11,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + namespace CompanyManagment.EFCore.Repository; public class LeaveRepository : RepositoryBase, ILeaveRepository @@ -678,6 +677,7 @@ public class LeaveRepository : RepositoryBase, ILeaveRepository query = query.OrderByDescending(x => x.CreationDate); var queryPaginationFilter = await query.ApplyPagination(searchModel.PageIndex, searchModel.PageSize).ToListAsync(); + var leaveResult = queryPaginationFilter.Select(item => new leaveListDto() { @@ -796,5 +796,54 @@ public class LeaveRepository : RepositoryBase, ILeaveRepository return leaveList; } + + + public async Task ListPrint(List ids) + { + var result = new LeaveListPrintDto(); + var timeSpanHourlyLeave = new TimeSpan(); + var dailyLeaveTime = new TimeSpan(); + if (ids.Any()) + { + var query = _context.LeaveList.Where(x => ids.Contains(x.id)).OrderByDescending(x=>x.StartLeave).AsQueryable(); + + #region sumOfLeaves + + var hourly = await query.Where(x => x.PaidLeaveType == "ساعتی").Select(x => x.LeaveHourses).ToListAsync(); + var daily = await query.Where(x => x.PaidLeaveType == "روزانه").Select(x => x.LeaveHourses).ToListAsync(); + + + if (hourly.Any()) + timeSpanHourlyLeave = new TimeSpan(hourly.Sum(x => TimeOnly.Parse(x).Ticks)); + if (daily.Any()) + dailyLeaveTime = daily.Sum(x => Convert.ToInt32(x)) * TimeSpan.FromDays(1); + + var sumOfLeaves = timeSpanHourlyLeave.Add(dailyLeaveTime); + + result.SumOfEmployeeleaves = sumOfLeaves.ToFarsiDaysAndHoursAndMinutes(); + + #endregion + + + result.LeavePrintListItemsDto = await query.Select(item => new LeavePrintListItemsDto + { + YearStr = $"{item.Year}", + MonthStr = item.Month.ToFarsiMonthByIntNumber(), + StartLeave = item.StartLeave.ToFarsi(), + EndLeave = item.EndLeave.ToFarsi(), + LeaveType = item.LeaveType, + HourlyInterval = item.PaidLeaveType == "ساعتی" ? $"{item.StartLeave.TimeOfDay:hh\\:mm} الی {item.EndLeave.TimeOfDay:hh\\:mm}" : "-", + LeaveDuration = Tools.CalculateLeaveHoursAndDays(item.PaidLeaveType, item.LeaveHourses), + IsAccepted = item.IsAccepted, + }).ToListAsync(); + + + result.EmployeeFullName = query.FirstOrDefault()!.EmployeeFullName; + } + + + return result; + } + #endregion } \ No newline at end of file diff --git a/ServiceHost/Areas/Client/Controllers/LeaveController.cs b/ServiceHost/Areas/Client/Controllers/LeaveController.cs index 21d39aaa..68962504 100644 --- a/ServiceHost/Areas/Client/Controllers/LeaveController.cs +++ b/ServiceHost/Areas/Client/Controllers/LeaveController.cs @@ -111,14 +111,14 @@ public class LeaveController : ClientBaseController } /// - /// پرینت گروهی + /// پرینت لیستی /// /// /// [HttpGet("ListPrint")] - public async Task> ListPrint([FromQuery] List ids,) + public async Task> ListPrint([FromQuery] List ids) { - var leavePrints = await _leaveApplication.PrintAllAsync(ids, _workshopId); + var leavePrints = await _leaveApplication.ListPrint(ids); return Ok(leavePrints); }