From d740c36dc683303cc2e241cbf1c7630b81e8280e Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 23 Dec 2025 17:33:09 +0330 Subject: [PATCH 01/23] add: update ProjectBoardDetailResponse to use TotalTimeMinute and SpentTimeMinute --- .../ProjectBoardDetailQueryHandler.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs index 60de81c1..58a48878 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardDetail/ProjectBoardDetailQueryHandler.cs @@ -8,14 +8,13 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.Project public record ProjectBoardDetailQuery(Guid SectionId) : IBaseQuery; -public record ProjectBoardDetailResponse(List Users, string TotalTime,string RemainingTime ); +public record ProjectBoardDetailResponse(List Users, string TotalTimeMinute,string RemainingTimeMinute ); public record ProjectBoardDetailUserResponse { public List Histories { get; init; } public string UserFullName { get; init; } - public string TotalTime { get; init; } - public string SpentTime { get; init; } + public string SpentTimeMinute { get; init; } public long UserId { get; init; } } @@ -24,7 +23,7 @@ public record ProjectBoardDetailUserHistoryResponse public string Date { get; init; } public string startTime { get; init; } public string EndTime { get; init; } - public string TotalTime { get; init; } + public string TotalTimeMinute { get; init; } } public class ProjectBoardDetailQueryHandler : IBaseQueryHandler @@ -68,18 +67,18 @@ public class ProjectBoardDetailQueryHandler : IBaseQueryHandlerh.GetTimeSpent().Ticks)).TotalHours.ToString(CultureInfo.InvariantCulture), + SpentTimeMinute = ((int)TimeSpan.FromTicks(x.Sum(h=>h.GetTimeSpent().Ticks)).TotalMinutes).ToString(CultureInfo.InvariantCulture), Histories = x.Select(h => new ProjectBoardDetailUserHistoryResponse() { Date = h.StartDate.ToFarsi(), startTime = h.StartDate.ToString("HH:mm"), EndTime = h.EndDate?.ToString("HH:mm") ?? "-", - TotalTime = h.GetTimeSpent().ToString(@"hh\:mm") + TotalTimeMinute = h.GetTimeSpent().TotalMinutes.ToString("F0",CultureInfo.InvariantCulture) }).ToList() }; }).ToList(); - var response = new ProjectBoardDetailResponse(users, $"{(int)totalActivityTimeSpan.TotalHours}:{totalActivityTimeSpan.Minutes:D2}", - $"{(int)remainingTimeSpan.TotalHours}:{remainingTimeSpan.Minutes:D2}"); + var response = new ProjectBoardDetailResponse(users, $"{(int)finalTime.TotalMinutes}", + $"{(int)remainingTimeSpan.TotalMinutes:D2}"); return OperationResult.Success(response); } } \ No newline at end of file From a191968c15f6136dd91ad8ded987e1d5a1153432 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 23 Dec 2025 18:16:50 +0330 Subject: [PATCH 02/23] add: include Installments in InstitutionContractRepository query --- .../Repository/InstitutionContractRepository.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index c0871074..51d434ef 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1754,6 +1754,7 @@ public class InstitutionContractRepository : RepositoryBase x.InitialWorkshops) .Include(x => x.WorkshopGroup) .ThenInclude(x => x.CurrentWorkshops) + .Include(x=>x.Installments) .FirstOrDefaultAsync(x => x.id == institutionContractId); } From 134466547e3149469b05bf767ad67e20b141181c Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 23 Dec 2025 18:54:10 +0330 Subject: [PATCH 03/23] add: enhance InstitutionContractRepository to include employer workshops and left work details --- .../InstitutionContractRepository.cs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 51d434ef..8e6e4c18 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -2155,6 +2155,10 @@ public class InstitutionContractRepository : RepositoryBase x.WorkshopGroup) .ThenInclude(institutionContractWorkshopGroup => institutionContractWorkshopGroup.CurrentWorkshops) .FirstOrDefaultAsync(x => x.id == extenstionTemp.PreviousId); + + var employerWorkshopIds = _context.Employers.Where(x=>x.ContractingPartyId == prevInstitutionContracts.ContractingPartyId).Include(x=>x.WorkshopEmployers) + .SelectMany(x=>x.WorkshopEmployers).Select(x=>x.WorkshopId).Distinct().ToList(); + if (prevInstitutionContracts == null) { throw new BadRequestException("قرارداد مالی قبلی یافت نشد"); @@ -2167,7 +2171,12 @@ public class InstitutionContractRepository : RepositoryBase x.WorkshopId.Value); - var workshops = await _context.Workshops.Where(x => workshopIds.Contains(x.id)).ToListAsync(); + + var workshopsNotInInstitution = employerWorkshopIds.Where(x=> !workshopIds.Contains(x)).ToList(); + + var workshops = await _context.Workshops.Where(x => workshopIds.Contains(x.id) || employerWorkshopIds.Contains(x.id)) + .ToListAsync(); + var workshopDetails = prevInstitutionContracts.WorkshopGroup.CurrentWorkshops .Select(x => { @@ -2209,6 +2218,32 @@ public class InstitutionContractRepository : RepositoryBase workshopsNotInInstitution.Contains(x.WorkshopId) && x.StartWorkDate <= DateTime.Now && + x.LeftWorkDate >= DateTime.Now) + .GroupBy(x => x.WorkshopId).ToListAsync(); + var notIncludeWorskhopsInContract = workshopsNotInInstitution.Select(x => + { + var workshop = workshops.FirstOrDefault(w => w.id == x); + var leftWorks = notIncludeWorskhopsLeftWork.FirstOrDefault(l=>l.Key ==x); + return new WorkshopTempViewModel() + { + WorkshopName = workshop?.WorkshopName ?? "فاقد کارگاه", + WorkshopServicesAmount = 0, + WorkshopServicesAmountStr = "0", + WorkshopId = x, + Id = 0, + ContractAndCheckout = false, + ContractAndCheckoutInPerson = false, + CustomizeCheckout = false, + CountPerson = leftWorks?.Count()??0, + Insurance = false, + InsuranceInPerson = false, + RollCall = false, + RollCallInPerson = false, + }; + }).ToList(); + workshopDetails = workshopDetails.Concat(notIncludeWorskhopsInContract).ToList(); var res = new InstitutionContractExtensionWorkshopsResponse() { TotalAmount = workshopDetails.Sum(x => x.WorkshopServicesAmount).ToMoney(), From 30b4f52896a98540ad1b39800e97e641d09d7eb4 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 23 Dec 2025 20:16:33 +0330 Subject: [PATCH 04/23] add: refactor RollCall application to support asynchronous operations and enhance transaction handling --- .../RollCall/IRollCallApplication.cs | 2 +- .../CustomizeWorkshopSettingsApplication.cs | 22 ++++++--- .../RollCallApplication.cs | 47 +++++++++++++------ .../Pages/Company/RollCall/Grouping.cshtml.cs | 4 +- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs index 6ada660b..6ce7bbfd 100644 --- a/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs +++ b/CompanyManagment.App.Contracts/RollCall/IRollCallApplication.cs @@ -124,7 +124,7 @@ namespace CompanyManagment.App.Contracts.RollCall /// /// /// - OperationResult RecalculateValues(long workshopId, List command); + Task RecalculateValues(long workshopId, List command); } public class ReCalculateRollCallValues { diff --git a/CompanyManagment.Application/CustomizeWorkshopSettingsApplication.cs b/CompanyManagment.Application/CustomizeWorkshopSettingsApplication.cs index b4f19256..5c3f7e2f 100644 --- a/CompanyManagment.Application/CustomizeWorkshopSettingsApplication.cs +++ b/CompanyManagment.Application/CustomizeWorkshopSettingsApplication.cs @@ -25,6 +25,7 @@ using Microsoft.EntityFrameworkCore.Query; using Company.Domain.CheckoutAgg; using Company.Domain.CustomizeCheckoutAgg; using Company.Domain.CustomizeCheckoutTempAgg; +using Company.Domain.RollCallAgg; using CompanyManagment.EFCore.Repository; @@ -38,7 +39,8 @@ public class CustomizeWorkshopSettingsApplication(ICustomizeWorkshopSettingsRepo IRollCallApplication rollCallAppllication, ICheckoutRepository checkoutRepository, ICustomizeCheckoutRepository customizeCheckoutRepository, - ICustomizeCheckoutTempRepository customizeCheckoutTempRepository) + ICustomizeCheckoutTempRepository customizeCheckoutTempRepository, + IRollCallRepository rollCallRepository) : ICustomizeWorkshopSettingsApplication { private readonly ICustomizeWorkshopSettingsRepository _customizeWorkshopSettingsRepository = customizeWorkshopSettingsRepository; @@ -53,6 +55,7 @@ public class CustomizeWorkshopSettingsApplication(ICustomizeWorkshopSettingsRepo private readonly ICheckoutRepository _checkoutRepository = checkoutRepository; private readonly ICustomizeCheckoutRepository _customizeCheckoutRepository = customizeCheckoutRepository; private readonly ICustomizeCheckoutTempRepository _customizeCheckoutTempRepository = customizeCheckoutTempRepository; + private readonly IRollCallRepository _rollCallRepository = rollCallRepository; #region RollCallShifts @@ -822,14 +825,19 @@ public class CustomizeWorkshopSettingsApplication(ICustomizeWorkshopSettingsRepo var notSelectedEmployeeSettings = employeeSettings.Where(x => !selectedEmployeesIds.Contains(x.EmployeeId)); - var weeklyOffDays = command.OffDayOfWeeks?.Select(x => new WeeklyOffDay(x)).ToList() ?? []; - using var transaction = new TransactionScope(); + var weeklyOffDays = command.OffDayOfWeeks? + .Select(x => new WeeklyOffDay(x)).ToList() ?? []; + + using var rollCallTransaction = _rollCallRepository.BeginTransactionAsync() + .GetAwaiter().GetResult(); entity.EditSimpleAndOverwriteOnEmployee(command.Name, selectedEmployeesIds, groupSettingsShifts, command.WorkshopShiftStatus, command.IrregularShift, breakTime, isChanged, command.HolidayWork, rotatingShift, weeklyOffDays); if (reCalculateCommand.Count > 0) { - var result = _rollCallApplication.RecalculateValues(workshopSettings.WorkshopId, reCalculateCommand); + var result = _rollCallApplication + .RecalculateValues(workshopSettings.WorkshopId, reCalculateCommand) + .GetAwaiter().GetResult(); if (result.IsSuccedded == false) { @@ -844,7 +852,7 @@ public class CustomizeWorkshopSettingsApplication(ICustomizeWorkshopSettingsRepo _customizeWorkshopGroupSettingsRepository.SaveChanges(); - transaction.Complete(); + rollCallTransaction.Commit(); return op.Succcedded(); } public OperationResult EditSimpleRollCallEmployeeSetting(EditCustomizeEmployeeSettings command, @@ -1043,7 +1051,9 @@ public class CustomizeWorkshopSettingsApplication(ICustomizeWorkshopSettingsRepo _customizeWorkshopGroupSettingsRepository.SaveChanges(); if (reCalculateCommand.Count > 0) { - var result = _rollCallApplication.RecalculateValues(command.WorkshopId, reCalculateCommand); + var result = _rollCallApplication + .RecalculateValues(command.WorkshopId, reCalculateCommand) + .GetAwaiter().GetResult(); if (result.IsSuccedded == false) { diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index 1730c70d..e73e4c3e 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -788,7 +788,7 @@ public class RollCallApplication : IRollCallApplication return _rollCallRepository.CheckRepeat(employeeId, workshopId); } - public OperationResult RecalculateValues(long workshopId, List commands) + public async Task RecalculateValues(long workshopId, List commands) { var operationResult = new OperationResult(); try @@ -812,24 +812,43 @@ public class RollCallApplication : IRollCallApplication var oldestDate = commands.MinBy(x => x.FromDate).FromDate.ToGeorgianDateTime(); - var allRollCalls = _rollCallRepository + var allRollCalls = await _rollCallRepository .GetRollCallsUntilNowWithWorkshopIdEmployeeIds(workshopId, commands.Select(x => x.EmployeeId).ToList(), - oldestDate).GetAwaiter().GetResult(); + oldestDate); + + var rollCalls = + commands.SelectMany(command => + allRollCalls.Where(x => + x.EmployeeId == command.EmployeeId && + x.ShiftDate >= command.FromDate.ToGeorgianDateTime() + ) + ); - - foreach (var command in commands) + foreach (var rollCall in rollCalls) { - var rollCalls = allRollCalls - .Where(x => x.EmployeeId == command.EmployeeId && x.ShiftDate >= command.FromDate.ToGeorgianDateTime()).ToList(); + rollCall.ClearTimeDiff(); - foreach (var rollCall in rollCalls) - { - rollCall.ClearTimeDiff(); - _rollCallRepository.SaveChanges(); - rollCall.SetEndDateTime(rollCall.EndDate!.Value, _rollCallDomainService); - } + await _rollCallRepository.SaveChangesAsync(); + + rollCall.SetEndDateTime( + rollCall.EndDate!.Value, + _rollCallDomainService + ); } - _rollCallRepository.SaveChanges(); + + // foreach (var command in commands) + // { + // var rollCalls = allRollCalls + // .Where(x => x.EmployeeId == command.EmployeeId && x.ShiftDate >= command.FromDate.ToGeorgianDateTime()).ToList(); + // + // foreach (var rollCall in rollCalls) + // { + // rollCall.ClearTimeDiff(); + // await _rollCallRepository.SaveChangesAsync(); + // rollCall.SetEndDateTime(rollCall.EndDate!.Value, _rollCallDomainService); + // } + // } + await _rollCallRepository.SaveChangesAsync(); return operationResult.Succcedded(); } diff --git a/ServiceHost/Areas/Client/Pages/Company/RollCall/Grouping.cshtml.cs b/ServiceHost/Areas/Client/Pages/Company/RollCall/Grouping.cshtml.cs index 781d76b8..7d41262c 100644 --- a/ServiceHost/Areas/Client/Pages/Company/RollCall/Grouping.cshtml.cs +++ b/ServiceHost/Areas/Client/Pages/Company/RollCall/Grouping.cshtml.cs @@ -293,9 +293,9 @@ namespace ServiceHost.Areas.Client.Pages.Company.RollCall }); } - public IActionResult OnPostReCalculateValues(List command) + public async Task OnPostReCalculateValues(List command) { - var result = _rollCallApplication.RecalculateValues(_workshopId, command); + var result =await _rollCallApplication.RecalculateValues(_workshopId, command); return new JsonResult(new { From 5faa2062b9c803969df19b48b2cb0f039a44567b Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 24 Dec 2025 13:54:51 +0330 Subject: [PATCH 05/23] 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 06/23] 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 07/23] 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 08/23] 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 09/23] 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 10/23] 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 11/23] 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 12/23] 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 13/23] 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 14/23] 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 18/23] 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 19/23] 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 20/23] 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 21/23] 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 54e5904951be682f3edd9b30eeb43556477a633c Mon Sep 17 00:00:00 2001 From: mahan Date: Thu, 25 Dec 2025 15:11:27 +0330 Subject: [PATCH 22/23] 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 23/23] 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(),