using _0_Framework.Application; using _0_Framework.Application.Enums; using _0_Framework.Application.Sms; using _0_Framework.Exceptions; using _0_Framework.InfraStructure; using Company.Domain.ContarctingPartyAgg; using Company.Domain.empolyerAgg; using Company.Domain.FinancialStatmentAgg; using Company.Domain.FinancialTransactionAgg; using Company.Domain.InstitutionContractAgg; using Company.Domain.InstitutionContractAmendmentTempAgg; using Company.Domain.InstitutionContractContactInfoAgg; using Company.Domain.InstitutionContractExtensionTempAgg; using Company.Domain.InstitutionPlanAgg; using Company.Domain.SmsResultAgg; using Company.Domain.WorkshopAgg; using CompanyManagment.App.Contracts.Employer; using CompanyManagment.App.Contracts.FinancialStatment; using CompanyManagment.App.Contracts.FinancilTransaction; using CompanyManagment.App.Contracts.Hubs; using CompanyManagment.App.Contracts.InstitutionContract; using CompanyManagment.App.Contracts.InstitutionContractContactinfo; using CompanyManagment.App.Contracts.Law; 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; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; using ContractingPartyAccount = Company.Domain.ContractingPartyAccountAgg.ContractingPartyAccount; using FinancialStatment = Company.Domain.FinancialStatmentAgg.FinancialStatment; using String = System.String; using Workshop = Company.Domain.WorkshopAgg.Workshop; namespace CompanyManagment.EFCore.Repository; public class InstitutionContractRepository : RepositoryBase, IInstitutionContractRepository { private readonly CompanyContext _context; private readonly IEmployerRepository _employerRepository; private readonly IWorkshopRepository _workshopRepository; private readonly IMongoCollection _institutionExtensionTemp; private readonly IMongoCollection _institutionAmendmentTemp; private readonly IPlanPercentageRepository _planPercentageRepository; private readonly ISmsService _smsService; private readonly ISmsResultRepository _smsResultRepository; private readonly IFinancialTransactionRepository _financialTransactionRepository; private readonly IFinancialStatmentRepository _financialStatmentRepository; private readonly IHubContext _hubContext; private readonly ILogger _logger; private readonly InstitutionContratVerificationParty _firstParty = new() { Address = "رشت - خیابان حاجی آیاد - کوچه سپهدار - ساختمان داماش - واحد 17", PhoneNumber = "09111485044", CeoName = "سید حسن مصباح", CompanyNameOrFullName = "نور داد مهر گستر کاسپین", NationalCodeOrNationalId = "14009970584", LegalType = LegalType.Legal }; public InstitutionContractRepository(CompanyContext context, IEmployerRepository employerRepository, IWorkshopRepository workshopRepository, IMongoDatabase database, IPlanPercentageRepository planPercentageRepository, ISmsService smsService, ISmsResultRepository smsResultRepository, IFinancialTransactionRepository financialTransactionRepository, IFinancialStatmentRepository financialStatmentRepository, IHubContext hubContext, ILogger logger) : base(context) { _context = context; _employerRepository = employerRepository; _workshopRepository = workshopRepository; _planPercentageRepository = planPercentageRepository; _smsService = smsService; _smsResultRepository = smsResultRepository; _financialTransactionRepository = financialTransactionRepository; _financialStatmentRepository = financialStatmentRepository; _hubContext = hubContext; _logger = logger; _institutionExtensionTemp = database.GetCollection("InstitutionContractExtensionTemp"); _institutionAmendmentTemp = database.GetCollection("InstitutionContractAmendmentTemp"); } public EditInstitutionContract GetDetails(long id) { return _context.InstitutionContractSet.Select(x => new EditInstitutionContract() { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, RepresentativeId = x.RepresentativeId, ContractingPartyId = x.ContractingPartyId, ContractDateFa = x.ContractDateFa, State = x.State, City = x.City, Address = x.Address, Description = x.Description, WorkshopManualCount = x.WorkshopManualCount, EmployeeManualCount = x.EmployeeManualCount, ContractAmountString = x.ContractAmount.ToMoney(), ContractAmount = x.ContractAmount, DailyCompenseationString = x.DailyCompenseation.ToMoney(), ObligationString = x.Obligation.ToMoney(), TotalAmountString = x.TotalAmount.ToMoney(), ExtensionNo = x.ExtensionNo, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature, HasValueAddedTax = x.HasValueAddedTax, ValueAddedTax = x.ValueAddedTax, }) .FirstOrDefault(x => x.Id == id); } public EditInstitutionContract GetFirstContract(long contractingPartyId, string typeOfContract) { return _context.InstitutionContractSet.Select(x => new EditInstitutionContract() { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, RepresentativeId = x.RepresentativeId, ContractingPartyId = x.ContractingPartyId, ContractDateFa = x.ContractDateFa, State = x.State, City = x.City, Address = x.Address, Description = x.Description, WorkshopManualCount = x.WorkshopManualCount, EmployeeManualCount = x.EmployeeManualCount, ContractAmountString = x.ContractAmount.ToMoney(), DailyCompenseationString = x.DailyCompenseation.ToMoney(), ObligationString = x.Obligation.ToMoney(), TotalAmountString = x.TotalAmount.ToMoney(), ExtensionNo = x.ExtensionNo, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature }) .Where(x => x.ContractingPartyId == contractingPartyId && x.TypeOfContract == typeOfContract) .OrderBy(x => x.ExtensionNo).FirstOrDefault(); } public List InstitutionContractsWithoutAccount() { var now = DateTime.Now; var contractHasClientAccountList = _context.InstitutionContractSet.AsSplitQuery().Where(x => x.IsActiveString == "true" && x.ContractStartGr <= now && x.ContractEndGr >= now) .Join(_context.ContractingPartyAccounts, contract => contract.ContractingPartyId, acc => acc.PersonalContractingPartyId, ((contract, account) => new { contract, account })).Select(x => x.contract); var allActiveContracts = _context.InstitutionContractSet.Where(x => x.IsActiveString == "true" && x.ContractStartGr <= now && x.ContractEndGr >= now); var contractWithoutAccountList = allActiveContracts.Except(contractHasClientAccountList); return contractWithoutAccountList.Select(x => new InstitutionContractViewModel { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount.ToMoney(), TotalAmount = x.TotalAmount.ToMoney(), SearchAmount = x.ContractAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, }).ToList(); } public List ContractWithoutValidContactInfo() { var now = DateTime.Now; var contractHasContactInfo = _context.InstitutionContractSet.AsSplitQuery().Where(x => x.IsActiveString == "true" && x.ContractStartGr <= now && x.ContractEndGr >= now) .Join(_context.InstitutionContractContactInfos, contract => contract.id, contactInfo => contactInfo.InstitutionContractId, ((contract, contactInfo) => new { contract, contactInfo })) .Where(x => x.contactInfo.SendSms && x.contactInfo.Position == "طرف قرارداد" && x.contactInfo.PhoneType == "شماره همراه") .Select(x => x.contract); var allvalidCcntactInfoContracts = _context.InstitutionContractSet.Where(x => x.IsActiveString == "true" && x.ContractStartGr <= now && x.ContractEndGr >= now); var contractWithoutAccountList = allvalidCcntactInfoContracts.Except(contractHasContactInfo); return contractWithoutAccountList.Select(x => new InstitutionContractViewModel { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount.ToMoney(), TotalAmount = x.TotalAmount.ToMoney(), SearchAmount = x.ContractAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, }).ToList(); } public List Search(InstitutionContractSearchModel searchModel) { //var stored = _context.InstitutionContractSet.FromSqlInterpolated($"SelectQuery_InstitutionContract").AsNoTracking() // .ToList(); var query = _context.InstitutionContractSet.Select(x => new InstitutionContractViewModel() { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount.ToMoney(), TotalAmount = x.TotalAmount.ToMoney(), SearchAmount = x.ContractAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature }); if (searchModel.Id != 0) query = query.Where(x => x.Id == searchModel.Id); if (searchModel.RepresentativeId != 0) query = query.Where(x => x.RepresentativeId == searchModel.RepresentativeId); if (searchModel.ContractingPartyId != 0) query = query.Where(x => x.ContractingPartyId == searchModel.ContractingPartyId); if (!string.IsNullOrWhiteSpace(searchModel.StartAmount) && !string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start && x.SearchAmount <= end); } if (!string.IsNullOrWhiteSpace(searchModel.StartAmount) && string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start); } if (string.IsNullOrWhiteSpace(searchModel.StartAmount) && !string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start); query = query.Where(x => x.SearchAmount <= end); } if (searchModel.IsActiveString == null) { query = query.Where(x => x.IsActiveString == "true" || x.IsActiveString == "blue"); } if (searchModel.IsActiveString == "false") { query = query.Where(x => x.IsActiveString == "false"); } else if (searchModel.IsActiveString == "both") { query = query.Where(x => x.IsActiveString == "false" || x.IsActiveString == "true" || x.IsActiveString == "blue"); } if (searchModel.OfficialCompany == "Official") query = query.Where(x => x.OfficialCompany == "Official"); if (searchModel.OfficialCompany == "NotOfficial") query = query.Where(x => x.OfficialCompany == "NotOfficial"); if (searchModel.TypeOfContract == "both") { query = query.Where(x => x.TypeOfContract == "JobRelation" || x.TypeOfContract == "JobRelation"); } else if (searchModel.TypeOfContract == "JobRelation" || string.IsNullOrWhiteSpace(searchModel.TypeOfContract)) { query = query.Where(x => x.TypeOfContract == "JobRelation"); } else if (searchModel.TypeOfContract == "taxAndFinancial") { query = query.Where(x => x.TypeOfContract == "taxAndFinancial"); } if (searchModel.Signature == "2") { query = query.Where(x => x.Signature == "0" || x.Signature == "1"); } if (searchModel.Signature == "1") { query = query.Where(x => x.Signature == "1"); } else if (searchModel.Signature == "0") { query = query.Where(x => x.Signature == "0"); } //var sumList = query.Select(x => x.SearchAmount).ToList(); //double sum = 0; //foreach (var amount in sumList) //{ // sum += amount; //} //Console.WriteLine(sum); return query.OrderByDescending(x => x.Id).ToList(); } public List NewSearch(InstitutionContractSearchModel searchModel) { var timer = Stopwatch.StartNew(); var query = _context.InstitutionContractSet.AsSplitQuery() .Select(x => new InstitutionContractViewModel() { Id = x.id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount.ToMoney(), TotalAmount = x.TotalAmount.ToMoney(), SearchAmount = x.ContractAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature, WorkshopCount = "", //WorkshopViewModels = _context.Workshops.Include(w=>w.WorkshopEmployers).Include(w => w.LeftWorks).Include(w => w.LeftWorkInsurances).Select(w => new WorkshopViewModel() //{ // Id = w.id, // WorkshopName = w.WorkshopName, // WorkshopFullName = w.WorkshopFullName, // ArchiveCode = w.ArchiveCode, // ContractingPartId = w.WorkshopEmployers.Select(e => e.Employer.ContractingPartyId).FirstOrDefault(), // LeftWorkIds = w.LeftWorks.Where(l => l.StartWorkDate <= DateTime.Now && l.LeftWorkDate > DateTime.Now).Select(l => l.EmployeeId).ToList(), // InsuranceLeftWorkIds = w.LeftWorkInsurances.Where(l => (l.StartWorkDate <= DateTime.Now && l.LeftWorkDate > DateTime.Now) || (l.StartWorkDate <= DateTime.Now && l.LeftWorkDate == null)).Select(l => l.EmployeeId).ToList(), //}).Where(w=>w.ContractingPartId == x.ContractingPartyId).ToList(), WorkshopIds = _context.Workshops .Include(w => w.WorkshopEmployers).Select(w => new WorkshopViewModel() { Id = w.id, ContractingPartId = w.WorkshopEmployers.Select(e => e.Employer.ContractingPartyId) .FirstOrDefault(), }).Where(c => c.ContractingPartId == x.ContractingPartyId).Select(w => w.Id).ToList(), EmployerViewModels = _context.Employers.Where(e => e.ContractingPartyId == x.ContractingPartyId) .Select(e => new EmployerViewModel() { Id = e.id, FullName = e.FName + " " + e.LName, }).GroupBy(e => e.Id).Select(e => e.First()).ToList(), EmployerIds = _context.Employers.AsSplitQuery().Where(e => e.ContractingPartyId == x.ContractingPartyId) .Select(e => e.id).ToList(), EmployerNo = "", EmployerName = "", IsContractingPartyBlock = _context.PersonalContractingParties.AsSplitQuery() .Any(p => p.id == x.ContractingPartyId && p.IsBlock == "true") ? "true" : "false", BlockTimes = _context.PersonalContractingParties.AsSplitQuery().Any(p => p.id == x.ContractingPartyId) ? _context.PersonalContractingParties.FirstOrDefault(p => p.id == x.ContractingPartyId).BlockTimes : 0, }); if (searchModel.Id != 0) query = query.Where(x => x.Id == searchModel.Id); if (searchModel.RepresentativeId != 0) query = query.Where(x => x.RepresentativeId == searchModel.RepresentativeId); if (searchModel.ContractingPartyId != 0) query = query.Where(x => x.ContractingPartyId == searchModel.ContractingPartyId); if (!string.IsNullOrWhiteSpace(searchModel.StartAmount) && !string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start && x.SearchAmount <= end); } if (!string.IsNullOrWhiteSpace(searchModel.StartAmount) && string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start); } if (string.IsNullOrWhiteSpace(searchModel.StartAmount) && !string.IsNullOrWhiteSpace(searchModel.EndAmount)) { var start = Convert.ToDouble(searchModel.StartAmount); var end = Convert.ToDouble(searchModel.EndAmount); query = query.Where(x => x.SearchAmount >= start); query = query.Where(x => x.SearchAmount <= end); } if (searchModel.IsActiveString == null) { query = query.Where(x => x.IsActiveString == "true" || x.IsActiveString == "blue"); } if (searchModel.IsActiveString == "false") { query = query.Where(x => x.IsActiveString == "false"); } else if (searchModel.IsActiveString == "both") { query = query.Where(x => x.IsActiveString == "false" || x.IsActiveString == "true" || x.IsActiveString == "blue"); } if (searchModel.OfficialCompany == "Official") query = query.Where(x => x.OfficialCompany == "Official"); if (searchModel.OfficialCompany == "NotOfficial") query = query.Where(x => x.OfficialCompany == "NotOfficial"); if (searchModel.TypeOfContract == "both") { query = query.Where(x => x.TypeOfContract == "JobRelation" || x.TypeOfContract == "taxAndFinancial"); } else if (searchModel.TypeOfContract == "JobRelation" || string.IsNullOrWhiteSpace(searchModel.TypeOfContract)) { query = query.Where(x => x.TypeOfContract == "JobRelation"); } else if (searchModel.TypeOfContract == "taxAndFinancial") { query = query.Where(x => x.TypeOfContract == "taxAndFinancial"); } if (searchModel.WorkshopId != 0) { query = query.Where(x => x.WorkshopIds.Count > 0 && x.WorkshopIds.Any(e => e == searchModel.WorkshopId)); } if (searchModel.EmployerId != 0) { query = query.Where(x => x.EmployerIds.Count > 0 && x.EmployerIds.Any(e => e == searchModel.EmployerId)); } if (searchModel.Signature == "2") { query = query.Where(x => x.Signature == "0" || x.Signature == "1"); } if (searchModel.Signature == "1") { query = query.Where(x => x.Signature == "1"); } else if (searchModel.Signature == "0") { query = query.Where(x => x.Signature == "0"); } var listQuery = query.ToList(); listQuery = listQuery.Select(x => new InstitutionContractViewModel() { Id = x.Id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount, TotalAmount = x.TotalAmount, SearchAmount = x.SearchAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature, ExpireColor = ExpColor(x.ContractEndGr, x.SearchAmount, x.IsActiveString).result, IsExpier = ExpColor(x.ContractEndGr, x.SearchAmount, x.IsActiveString).isExpier, BalanceDouble = TotalBalance(x.ContractingPartyId).TotalBalanceDbl, BalanceStr = TotalBalance(x.ContractingPartyId).TotalBalanceStr, EmployerViewModels = x.EmployerViewModels, EmployerNo = x.EmployerNo, // EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), // WorkshopViewModels = x.WorkshopViewModels, WorkshopCount = Convert.ToString(x.WorkshopIds.Count), IsContractingPartyBlock = x.IsContractingPartyBlock, BlockTimes = x.BlockTimes, // EmployeeCount = ((x.WorkshopViewModels.Sum(w => w.LeftWorkIds.Count)) + (x.WorkshopViewModels.Sum(w => w.InsuranceLeftWorkIds.Count(c => !w.LeftWorkIds.Contains(c))))).ToString(), // ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, WorkshopViewModels = _context.Workshops.AsSplitQuery().Where(w => x.WorkshopIds.Contains(w.id)) .Include(w => w.LeftWorks).Include(w => w.LeftWorkInsurances).Select(w => new WorkshopViewModel() { Id = w.id, WorkshopName = w.WorkshopName, WorkshopFullName = w.WorkshopFullName, ArchiveCode = w.ArchiveCode, ContractingPartId = w.WorkshopEmployers.Select(e => e.Employer.ContractingPartyId).FirstOrDefault(), LeftWorkIds = w.LeftWorks .Where(l => l.StartWorkDate <= DateTime.Now && l.LeftWorkDate > DateTime.Now) .Select(l => l.EmployeeId).ToList(), InsuranceLeftWorkIds = w.LeftWorkInsurances .Where(l => (l.StartWorkDate <= DateTime.Now && l.LeftWorkDate > DateTime.Now) || (l.StartWorkDate <= DateTime.Now && l.LeftWorkDate == null)) .Select(l => l.EmployeeId).ToList(), }).ToList(), }).ToList(); listQuery = listQuery.Select(x => new InstitutionContractViewModel() { Id = x.Id, ContractNo = x.ContractNo, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, RepresentativeId = x.RepresentativeId, RepresentativeName = x.RepresentativeName, ContractingPartyName = x.ContractingPartyName, ContractingPartyId = x.ContractingPartyId, ContractAmount = x.ContractAmount, TotalAmount = x.TotalAmount, SearchAmount = x.SearchAmount, IsActiveString = x.IsActiveString, OfficialCompany = x.OfficialCompany, TypeOfContract = x.TypeOfContract, Signature = x.Signature, ExpireColor = x.ExpireColor, IsExpier = x.IsExpier, BalanceDouble = x.BalanceDouble, BalanceStr = x.BalanceStr, EmployerViewModels = x.EmployerViewModels, EmployerNo = x.EmployerNo, EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), WorkshopViewModels = x.WorkshopViewModels, WorkshopCount = x.WorkshopCount, IsContractingPartyBlock = x.IsContractingPartyBlock, BlockTimes = x.BlockTimes, EmployeeCount = ((x.WorkshopViewModels.Sum(w => w.LeftWorkIds.Count)) + (x.WorkshopViewModels.Sum(w => w.InsuranceLeftWorkIds.Count(c => !w.LeftWorkIds.Contains(c))))).ToString(), ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, }).OrderBy(x => x.WorkshopCount != "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.WorkshopCount == "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.IsExpier == "true") .ThenBy(x => x.ExpireColor == "purple") .ThenBy(x => x.ExpireColor == "black").ToList(); Console.WriteLine("test >>> " + timer.Elapsed); return listQuery; } public List PrintAll(List id) { throw new NotImplementedException(); } public InstitutionContractViewModel PrintOne(long id) { throw new NotImplementedException(); } public void RemoveContract(long id) { var op = new OperationResult(); var institutionContarct = _context.InstitutionContractSet .FirstOrDefault(x => x.id == id); var prevInstitutionContracts = _context.InstitutionContractSet .Where(x => x.ContractingPartyId == institutionContarct.ContractingPartyId) .OrderByDescending(x => x.ContractEndGr).Skip(1).FirstOrDefault(); var transaction = _context.Database.BeginTransaction(); var contactInfo = _context.InstitutionContractContactInfos .Where(x => x.InstitutionContractId == id) .ToList(); if (contactInfo.Count > 0) { foreach (var item in contactInfo) { _context.InstitutionContractContactInfos.Remove(item); _context.SaveChanges(); } } if (institutionContarct != null) { _context.InstitutionContractSet.Remove(institutionContarct); _context.SaveChanges(); } if (prevInstitutionContracts != null) { var now = DateTime.Now; var financialStatement = _context.FinancialStatments .Include(x => x.FinancialTransactionList) .FirstOrDefault(x => x.ContractingPartyId == institutionContarct.ContractingPartyId); if (financialStatement != null) { var sumDebtor = financialStatement.FinancialTransactionList .Sum(x => x.Deptor); var sumCreditor = financialStatement.FinancialTransactionList .Sum(x => x.Creditor); var balance = sumDebtor - sumCreditor; if (balance > 0 && prevInstitutionContracts.ContractEndGr < now) { prevInstitutionContracts.DeActiveBlue(); _context.SaveChanges(); } } } transaction.Commit(); } public void CreateContractingPartyAccount(long contractingPartyid, long accountId) { var create = new ContractingPartyAccount(contractingPartyid, accountId); _context.ContractingPartyAccounts.Add(create); _context.SaveChanges(); } public double GetcontractAmount(int countPerson) { var planPercentage = _context.PlanPercentages.FirstOrDefault(); int contarctAndCheckoutPercent = 100; int insurancePercent = 50; int rollCallPercent = 100; int customizeCkeckoutPercen = 50; int contarctAndCheckoutInPersonPercent = 900; int insuranceInPersonPercent = 500; if (planPercentage != null) { contarctAndCheckoutPercent = planPercentage.ContractAndCheckoutPercent; insurancePercent = planPercentage.InsurancePercent; rollCallPercent = planPercentage.RollCallPercent; customizeCkeckoutPercen = planPercentage.CustomizeCheckoutPercent; contarctAndCheckoutInPersonPercent = planPercentage.ContractAndCheckoutInPersonPercent; insuranceInPersonPercent = planPercentage.InsuranceInPersonPercent; } var dailyWageYearlySalery = _context.YearlySalaries.Include(i => i.YearlySalaryItemsList).FirstOrDefault(x => x.StartDate.Date <= DateTime.Now.Date && x.EndDate >= DateTime.Now.Date); double res = 0; if (countPerson > 0 && dailyWageYearlySalery != null) { var dailyWage = dailyWageYearlySalery.YearlySalaryItemsList.Where(x => x.ItemName == "مزد روزانه") .Select(x => x.ItemValue).FirstOrDefault(); var plan = _context.InstitutionPlans.FirstOrDefault(x => x.CountPerson == countPerson); if (plan != null) { //مبلغ قرارداد و تصفیه var contarctAndCheckout = ((dailyWage * contarctAndCheckoutPercent) / 100) * countPerson * plan.IncreasePercentage; //خدمات بیمه var insurance = ((dailyWage * insurancePercent) / 100) * countPerson * plan.IncreasePercentage; ////خدمات حضور غیاب //var rollCall = ((dailyWage * rollCallPercent) / 100) * countPerson * // plan.IncreasePercentage; ////خدمات فیش حقوقی غیر رسمی //var customizeCkeckout = ((dailyWage * customizeCkeckoutPercen) / 100) * countPerson * // plan.IncreasePercentage; //خدمات حضوری قرارداد و تصفیه var contarctAndCheckoutInPerson = ((dailyWage * contarctAndCheckoutInPersonPercent) / 100) * countPerson * plan.IncreasePercentage; //خدمات حضوری بیمه var insuranceInPerson = ((dailyWage * insuranceInPersonPercent) / 100) * countPerson * plan.IncreasePercentage; //جمع کل res = contarctAndCheckout + insurance + contarctAndCheckoutInPerson + insuranceInPerson; } } return res; } public (string result, string isExpier) ExpColor(DateTime contractEndGr, double contractAmount, string isActiveString) { var now = DateTime.Now; var nowFa = now.ToFarsi(); var endFa = nowFa.FindeEndOfMonth(); var endThisMontGr = endFa.ToGeorgianDateTime(); string result = ""; string isExpier = "false"; if (contractEndGr < now) { result = "black"; isExpier = "true"; } if (contractEndGr >= now && contractEndGr <= endThisMontGr) { result = "red"; isExpier = "true"; } if (contractAmount == 0) { result = "purple"; if ((contractEndGr >= now && contractEndGr <= endThisMontGr) || (contractEndGr < now)) { isExpier = "true"; } } if (isActiveString == "blue") { result = "blue"; isExpier = "false"; } return (result, isExpier); } #region ExteraMetods public TotalbalancViewModel TotalBalance(long contractingPartyId) { var result = new TotalbalancViewModel(); var firstGetStatement = _context.FinancialStatments.Include(x => x.FinancialTransactionList) .FirstOrDefault(x => x.ContractingPartyId == contractingPartyId); if (firstGetStatement != null) { if (firstGetStatement.FinancialTransactionList != null) { var allTransactions = firstGetStatement.FinancialTransactionList; allTransactions = allTransactions.OrderBy(x => x.TdateGr).ToList(); var debt = allTransactions.Sum(x => x.Deptor); var credit = allTransactions.Sum(x => x.Creditor); result.TotalBalanceDbl = debt - credit; result.TotalBalanceStr = result.TotalBalanceDbl.ToMoney(); } } return result; } public int ArchiveCodeFinder(List workshopViewModels) { var workshop = workshopViewModels.OrderBy(x => x.Id)?.ToList(); var arc = workshop.Select(x => new ArchiveCodConvertoint { ArchiveCodeInt = x.ArchiveCode.Substring(0, 1) == "b" ? 10000000 : x.ArchiveCode.ConvertToInt(), }).OrderBy(x => x.ArchiveCodeInt).ToList(); var minArchiveCode = arc.Min(x => x.ArchiveCodeInt); return minArchiveCode == 10000000 ? 0 : minArchiveCode; } #endregion public InstitutionContract InstitutionContractByEmployerId(long employerId) { long contractingPryId = _context.Employers.FirstOrDefault(x => x.id == employerId)!.ContractingPartyId; if (_context.PersonalContractingParties.Any(x => x.id == contractingPryId && x.IsBlock == "true")) return new(); var contracts = _context.InstitutionContractSet.Where(x => x.ContractingPartyId == contractingPryId).ToList(); var contract = contracts.FirstOrDefault(x => x.IsActiveString != "false" && x.ContractStartGr.Date <= DateTime.Now.Date && x.ContractEndGr >= DateTime.Now.Date); if (contract != null) { return contract; } else { var future = contracts.FirstOrDefault(x => x.IsActiveString != "false" && x.ContractStartGr.Date >= DateTime.Now.Date && x.ContractEndGr >= DateTime.Now.Date); if (future != null) return future; return new(); } } /// /// ایجاد سند مالی حضور غیاب /// /// /// /// /// #region RollcallServicCreateTransaction public async Task RollCallServiceCreateTransaction() { DateTime now = DateTime.Now; var nowFa = now.ToFarsi(); var endOfMonth = nowFa.FindeEndOfMonth(); DateTime endOfMonthGr = endOfMonth.ToGeorgianDateTime(); #region FindeNextMonth 1th var year = Convert.ToInt32(endOfMonth.Substring(0, 4)); var month = Convert.ToInt32(endOfMonth.Substring(5, 2)); var nextM = new PersianDateTime(year, month, 1).AddMonths(1); var nextMonthGr = ($"{nextM}").ToGeorgianDateTime(); var endOfCurrentMonth = (($"{endOfMonth.Substring(0, 8)}/01").FindeEndOfMonth()).ToGeorgianDateTime(); #endregion #region GetAvtiveContracts var institutionContracts = _context.InstitutionContractSet.Where(x => x.IsActiveString == "true").Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, SearchAmount = x.ContractAmount, TypeOfContract = x.TypeOfContract }).Where(x => x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.SearchAmount > 0) .ToList(); #endregion #region GetFutureContracts List futureContracts = _context.InstitutionContractSet .Where(x => x.IsActiveString == "true" && x.ContractStartGr == nextMonthGr && x.ContractAmount > 0) .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, TypeOfContract = x.TypeOfContract, ExtensionNo = x.ExtensionNo, }).ToList(); #endregion #region GetDectivedContractOnCurrentMonth if (futureContracts.Any()) { List futureContractIds = futureContracts.Select(x => x.ContractingPartyId).ToList(); List deatcivedContract = _context.InstitutionContractSet .Where(x => x.IsActiveString == "false" && futureContractIds.Contains(x.ContractingPartyId) && x.ContractEndGr == endOfCurrentMonth && x.ContractAmount > 0) .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, SearchAmount = x.ContractAmount, TypeOfContract = x.TypeOfContract }).ToList(); if (deatcivedContract.Any()) institutionContracts.AddRange(deatcivedContract); } List exceptionContractingPartyIds = [30520, 30739]; institutionContracts = institutionContracts .Where(x => !exceptionContractingPartyIds.Contains(x.ContractingPartyId)).ToList(); int counter = 0; var rollcallServiceList = _context.RollCallServices.Where(x => x.IsActiveString == "true").ToList(); var activeStatusDate = new DateTime(2121, 03, 21); foreach (var item in institutionContracts) { //var isblock = contractingParty.IsBlock == "true" ? true : false; var employers = _context.Employers.Where(x => x.ContractingPartyId == item.ContractingPartyId) .Select(x => x.id); var workshops = _context.WorkshopEmployers.Where(x => employers.Contains(x.EmployerId)) .Select(x => x.WorkshopId).Distinct().ToList(); var srvices = rollcallServiceList.Where(x => workshops.Contains(x.WorkshopId)).ToList(); if (rollcallServiceList.Count > 0) { foreach (var rollCallService in srvices) { //var spaning = (int)(endOfMonthGr - rollCallService.StartService).TotalDays + 1; int monthCounter = 0; var currentMonthStart = ($"{(endOfMonthGr.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); var prevMonthEnd = currentMonthStart.AddDays(-1); var prevMonthStart = ($"{(prevMonthEnd.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); var monthCurrent = endOfMonth.Substring(5, 2); var yearCurrent = endOfMonth.Substring(0, 4); var currentMonthName = monthCurrent.ToFarsiMonthByNumber(); var workshop = _context.Workshops.FirstOrDefault(x => x.id == rollCallService.WorkshopId); string description = ""; //if (rollCallService.StartService <= prevMonthStart) //{ // var monthPrev = prevMonthEnd.ToFarsi().Substring(5, 2); // var yearPrev = prevMonthEnd.ToFarsi().Substring(0, 4); // var prevMonthName = monthPrev.ToFarsiMonthByNumber(); // description = // $"{prevMonthName} و {currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; // monthCounter = 2; //} //else if (rollCallService.StartService <= currentMonthStart && // rollCallService.StartService > prevMonthStart) //{ // monthCounter = 1; // description = $"{currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; //} if (rollCallService.StartService <= currentMonthStart) { monthCounter = 1; description = $"{currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; } var employees = _context.RollCallEmployees.Where(x => x.WorkshopId == rollCallService.WorkshopId) .Select(x => x.id); var employeeCount = _context.RollCallEmployeesStatus .Where(x => employees.Contains(x.RollCallEmployeeId)) .Count(x => x.EndDate.Date == activeStatusDate.Date); if (employeeCount > 0 && monthCounter > 0) { counter++; var dailyWageYearlySalery = _context.YearlySalaries.Include(i => i.YearlySalaryItemsList) .FirstOrDefault(x => x.StartDate.Date <= DateTime.Now.Date && x.EndDate >= DateTime.Now.Date); var dailyWage = dailyWageYearlySalery.YearlySalaryItemsList .Where(x => x.ItemName == "مزد روزانه") .Select(x => x.ItemValue).FirstOrDefault(); var planPercentage = _context.PlanPercentages.FirstOrDefault(); var countPersonnel = employeeCount; var planByCountPerson = _context.InstitutionPlans .FirstOrDefault(x => x.CountPerson == countPersonnel); var amountForOneMonth = (((dailyWage * planPercentage.RollCallPercent) / 100) * planByCountPerson.CountPerson * planByCountPerson.IncreasePercentage); var amountWithoutTax = amountForOneMonth * monthCounter; var tenPercent = amountWithoutTax * 10 / 100; var totalAmonut = amountWithoutTax + tenPercent; double roundFloor = Math.Floor(totalAmonut); double result = Math.Ceiling(roundFloor / 10000.0) * 10000; Console.WriteLine(counter + " - " + rollCallService.StartService.ToFarsi() + " - " + rollCallService.WorkshopId + " - " + employeeCount + $" - {totalAmonut} - round {result}"); var financialStatment = _context.FinancialStatments.FirstOrDefault(x => x.ContractingPartyId == item.ContractingPartyId); long financialStatementId = 0; if (financialStatment != null) { financialStatementId = financialStatment.id; } else { var statement = new FinancialStatment(item.ContractingPartyId, item.ContractingPartyName); _context.FinancialStatments.Add(statement); _context.SaveChanges(); financialStatementId = statement.id; } var transaction = new FinancialTransaction(financialStatementId, endOfMonthGr, endOfMonth, description, "debt", "بابت سرویس حضور غیاب", result, 0, 0); _context.FinancialTransactions.Add(transaction); _context.SaveChanges(); //Console.WriteLine(" number : " + counter + " - " + rollCallService.StartService.ToFarsi() + " - WorkshopId : " + rollCallService.WorkshopId + " - monthCount : " + monthCounter + " - employeeCount : " + employeeCount + $" - Amount : {amountWithoutTax.ToMoney()}" + $" - ten : {tenPercent.ToMoney()} total : {totalAmonut.ToMoney()}"); } } } } #endregion } public async Task> GetList( InstitutionContractListSearchModel searchModel) { var now = DateTime.Today; var nowFa = now.ToFarsi(); var endFa = nowFa.FindeEndOfMonth(); var endThisMontGr = endFa.ToGeorgianDateTime(); 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), contract => contract.ContractingPartyId, contractingParty => contractingParty.id, (contract, contractingParty) => new { contract, contractingParty }) .Select(x => new { x.contract, x.contractingParty, StatusPriority = x.contract.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify ? (int)InstitutionContractListStatus.PendingForVerify : x.contract.IsActiveString == "blue" ? (int)InstitutionContractListStatus.DeactiveWithDebt : x.contract.ContractEndGr < now ? (int)InstitutionContractListStatus.Deactive : (x.contract.ContractEndGr >= now && x.contract.ContractEndGr <= endThisMontGr && !_context.InstitutionContractSet.Any(i => i.ContractingPartyId == x.contract.ContractingPartyId && x.contract.ExtensionNo + 1 <= i.ExtensionNo && i.IsActiveString == "true")) ? (int)InstitutionContractListStatus.PendingForRenewal : x.contractingParty.IsBlock == "true" ? (int)InstitutionContractListStatus.Block : x.contract.ContractAmount == 0 ? (int)InstitutionContractListStatus.Free : !x.contractingParty.Employers .SelectMany(e => e.WorkshopEmployers .Select(we => we.Workshop)).Any() ? (int)InstitutionContractListStatus.WithoutWorkshop : (int)InstitutionContractListStatus.Active }); #region Search if (!string.IsNullOrWhiteSpace(searchModel.EmployerOrWorkshopOrContractingPartyOrRepresentativeName)) { var keyword = searchModel.EmployerOrWorkshopOrContractingPartyOrRepresentativeName; joinedQuery = joinedQuery.Where(x => x.contractingParty.RepresentativeFullName.Contains(keyword) || (x.contractingParty.FName + " " + x.contractingParty.LName).Contains(keyword) || (x.contractingParty.IsLegal == "حقیقی" ? x.contractingParty.SureName == null ? x.contractingParty.FName + " " + x.contractingParty.LName : x.contractingParty.FName + " " + x.contractingParty.LName + " " + x.contractingParty.SureName : x.contractingParty.SureName == null ? x.contractingParty.LName : x.contractingParty.LName + " " + x.contractingParty.SureName).Contains(keyword) || x.contractingParty.Employers.Any(e => e.FullName.Contains(keyword) || e.WorkshopEmployers.Any(we => we.Workshop.WorkshopFullName.Contains(keyword))) ); } if (!string.IsNullOrWhiteSpace(searchModel.City)) { joinedQuery = joinedQuery.Where(x => x.contract.City == searchModel.City); } if (!string.IsNullOrWhiteSpace(searchModel.Province)) { joinedQuery = joinedQuery.Where(x => x.contract.State == searchModel.Province); } if (searchModel.AmountFrom > 0) { joinedQuery = joinedQuery.Where(x => x.contract.ContractAmount >= searchModel.AmountFrom); } if (searchModel.AmountTo > 0) { joinedQuery = joinedQuery.Where(x => x.contract.ContractAmount <= searchModel.AmountTo); } if (!string.IsNullOrWhiteSpace(searchModel.ContractDateFrom) && !string.IsNullOrWhiteSpace(searchModel.ContractDateTo)) { if (!searchModel.ContractDateFrom.TryToGeorgianDateTime(out var dateFrom)) throw new BadRequestException("تاریخ وارد شده نامعتبر است"); if (!searchModel.ContractDateTo.TryToGeorgianDateTime(out var dateTo)) { throw new BadRequestException("تاریخ وارد شده نامعتبر است"); } if (dateFrom > dateTo) { throw new BadRequestException("تاریخ شروع نمیتواند بزرگ تر از تاریخ پایان باشد"); } joinedQuery = joinedQuery.Where(x => x.contract.ContractStartGr <= dateTo && x.contract.ContractEndGr <= dateFrom); } if (searchModel.HasSignature != null) { var hasSignature = searchModel.HasSignature == true ? "1" : "0"; joinedQuery = joinedQuery.Where(x => x.contract.Signature == hasSignature); } if (searchModel.IsActive != null) { var isActiveStr = searchModel.IsActive == true ? "true" : "false"; joinedQuery = joinedQuery.Where(x => x.contract.IsActiveString == isActiveStr || x.contract.IsActiveString == "blue"); } if (searchModel.Type != null) { var typeStr = searchModel.Type switch { InstitutionContractType.JobRelation => "JobRelation", InstitutionContractType.TaxAndFinancial => "taxAndFinancial", _ => throw new ArgumentOutOfRangeException() }; joinedQuery = joinedQuery.Where(x => x.contract.TypeOfContract == typeStr); } if (searchModel.IsOfficial != null) { var isOfficialStr = searchModel.IsOfficial == true ? "Official" : "NotOfficial"; joinedQuery = joinedQuery.Where(x => x.contract.OfficialCompany == isOfficialStr); } if (searchModel.Status != null) { switch (searchModel.Status) { case InstitutionContractListStatus.DeactiveWithDebt: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.DeactiveWithDebt); break; case InstitutionContractListStatus.PendingForRenewal: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.PendingForRenewal); break; case InstitutionContractListStatus.Block: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Block); break; case InstitutionContractListStatus.Free: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Free); break; case InstitutionContractListStatus.WithoutWorkshop: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.WithoutWorkshop); break; case InstitutionContractListStatus.Active: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Active); break; case InstitutionContractListStatus.Deactive: joinedQuery = joinedQuery.Where(x => x.contract.ContractEndGr < now); break; case InstitutionContractListStatus.PendingForVerify: joinedQuery = joinedQuery.Where(x => x.contract.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify); break; } } else { joinedQuery = joinedQuery.Where(x => x.contract.IsActiveString != "blue"); } #endregion var endOfMonth = new DateTime(now.Year, now.Month, DateTime.DaysInMonth(now.Year, now.Month)); var orderedQuery = joinedQuery .OrderBy(x => x.StatusPriority == (int)InstitutionContractListStatus.DeactiveWithDebt ? 0 : // DeactiveWithoutDebt (x.StatusPriority == (int)InstitutionContractListStatus.PendingForRenewal) ? 1 : // PendingToRenewal x.StatusPriority == (int)InstitutionContractListStatus.Block ? 2 : // Block x.StatusPriority == (int)InstitutionContractListStatus.Free ? 3 : // Free x.StatusPriority == (int)InstitutionContractListStatus.WithoutWorkshop ? 4 : // WithoutWorkshop 5 // Active ); var list = await orderedQuery.ApplyPagination(searchModel.PageIndex, searchModel.PageSize).ToListAsync(); var contractingPartyIds = list.Select(x => 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(); var res = new PagedResult() { TotalCount = await joinedQuery.CountAsync(), List = list.Select(x => { var workshops = x.contractingParty.Employers .SelectMany(e => e.WorkshopEmployers.Select(we => we.Workshop)).DistinctBy(w => w.id).ToList(); var employers = x.contractingParty.Employers.ToList(); var arc = workshops.Select(w => w.ArchiveCode.Substring(0, 1) == "b" ? 10000000 : w.ArchiveCode.ConvertToInt() ).OrderBy(w => w).ToList(); var minArchiveCode = arc.Count > 0 ? arc.Min(a => a) : 0; var archiveCode = minArchiveCode == 10000000 ? 0 : minArchiveCode; var status = Enum.Parse(x.StatusPriority.ToString()); // دریافت 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); if (currentStateWorkshops != null && workshopGroup != null) { currentStateWorkshops.AddRange(workshopGroup.InitialWorkshops.Where(w => !w.WorkshopCreated)); } var workshopDetails = currentStateWorkshops?.Select(w => { Workshop workshopSelected = null; if (w.WorkshopId != null && workshops.Select(ww => ww.id).Contains(w.WorkshopId.Value)) { workshopSelected = workshops.First(ww => ww.id == w.WorkshopId.Value); } return new InstitutionContractListWorkshop() { EmployeeCount = w.PersonnelCount, WorkshopName = workshopSelected?.WorkshopName ?? w.WorkshopName, WorkshopServices = new WorkshopServicesViewModel() { Contract = w.Services.Contract, ContractInPerson = w.Services.ContractInPerson, CustomizeCheckout = w.Services.CustomizeCheckout, Insurance = w.Services.Insurance, InsuranceInPerson = w.Services.InsuranceInPerson, RollCall = w.Services.RollCall, RollCallInPerson = w.Services.RollCallInPerson } }; }).ToList() ?? []; var employeesCount = _context.LeftWorkList .Where(l => workshops.Select(w => w.id).Contains(l.WorkshopId)) .Count(l => l.StartWorkDate <= DateTime.Now && l.LeftWorkDate >= DateTime.Now); return new GetInstitutionContractListItemsViewModel() { ContractAmount = x.contract.ContractAmountWithTax, Balance = statement?.FinancialTransactionList.Sum(ft => ft.Deptor - ft.Creditor) ?? 0, WorkshopsCount = workshops.Count(), ContractStartFa = x.contract.ContractStartGr.ToFarsi(), ContractEndFa = x.contract.ContractEndGr.ToFarsi(), ContractingPartyName = x.contract.ContractingPartyName, WorkshopNames = workshops.Select(w => w.WorkshopFullName).ToList(), RepresentativeName = x.contractingParty.RepresentativeFullName, HasSigniture = x.contract.Signature == "1", Id = x.contract.id, ContractNo = x.contract.ContractNo, ArchiveNo = archiveCode.ToString(), EmployeesCount = employeesCount, EmployerNames = employers.Select(e => e.FullName).ToList(), ListStatus = status, IsExpired = x.contract.ContractEndGr <= endThisMontGr, ContractingPartyId = x.contractingParty.id, Workshops = workshopDetails, IsInPersonContract = workshopGroup?.CurrentWorkshops .Any(y => y.Services.ContractInPerson) ?? true, IsOldContract = x.contract.SigningType == InstitutionContractSigningType.Legacy }; }).ToList() }; return res; } public async Task GetListStats( InstitutionContractListSearchModel searchModel) { var query = _context.InstitutionContractSet .Include(x => x.ContactInfoList); var now = DateTime.Today; var nowFa = now.ToFarsi(); var endFa = nowFa.FindeEndOfMonth(); var endThisMontGr = endFa.ToGeorgianDateTime(); var joinedQuery = query.Join(_context.PersonalContractingParties .Include(x => x.Employers) .ThenInclude(x => x.WorkshopEmployers) .ThenInclude(x => x.Workshop), contract => contract.ContractingPartyId, contractingParty => contractingParty.id, (contract, contractingParty) => new { contract, contractingParty }) .Join(_context.FinancialStatments.Include(x => x.FinancialTransactionList), x => x.contractingParty.id, statement => statement.ContractingPartyId, (x, statement) => new { x.contractingParty, x.contract, statement }) .Select(x => new { x.contract, x.contractingParty, x.statement, StatusPriority = x.contract.IsActiveString == "blue" ? (int)InstitutionContractListStatus.DeactiveWithDebt : x.contract.ContractEndGr < now ? (int)InstitutionContractListStatus.Deactive : (x.contract.ContractEndGr >= now && x.contract.ContractEndGr <= endThisMontGr) ? (int)InstitutionContractListStatus.PendingForRenewal : x.contractingParty.IsBlock == "true" ? (int)InstitutionContractListStatus.Block : x.contract.ContractAmount == 0 ? (int)InstitutionContractListStatus.Free : !x.contractingParty.Employers .SelectMany(e => e.WorkshopEmployers.Select(we => we.Workshop)).Any() ? (int)InstitutionContractListStatus.WithoutWorkshop : (int)InstitutionContractListStatus.Active }); #region Search if (!string.IsNullOrWhiteSpace(searchModel.EmployerOrWorkshopOrContractingPartyOrRepresentativeName)) { var keyword = searchModel.EmployerOrWorkshopOrContractingPartyOrRepresentativeName; joinedQuery = joinedQuery.Where(x => x.contractingParty.RepresentativeFullName.Contains(keyword) || (x.contractingParty.FName + " " + x.contractingParty.LName).Contains(keyword) || x.contractingParty.Employers.Any(e => e.FullName.Contains(keyword) || e.WorkshopEmployers.Any(we => we.Workshop.WorkshopFullName.Contains(keyword))) ); } if (!string.IsNullOrWhiteSpace(searchModel.City)) { joinedQuery = joinedQuery.Where(x => x.contract.City == searchModel.City); } if (!string.IsNullOrWhiteSpace(searchModel.Province)) { joinedQuery = joinedQuery.Where(x => x.contract.State == searchModel.Province); } if (searchModel.AmountFrom > 0) { joinedQuery = joinedQuery.Where(x => x.contract.ContractAmount >= searchModel.AmountFrom); } if (searchModel.AmountTo > 0) { joinedQuery = joinedQuery.Where(x => x.contract.ContractAmount <= searchModel.AmountTo); } if (!string.IsNullOrWhiteSpace(searchModel.ContractDateFrom) && !string.IsNullOrWhiteSpace(searchModel.ContractDateTo)) { if (!searchModel.ContractDateFrom.TryToGeorgianDateTime(out var dateFrom)) throw new BadRequestException("تاریخ وارد شده نامعتبر است"); if (!searchModel.ContractDateTo.TryToGeorgianDateTime(out var dateTo)) { throw new BadRequestException("تاریخ وارد شده نامعتبر است"); } if (dateFrom > dateTo) { throw new BadRequestException("تاریخ شروع نمیتواند بزرگ تر از تاریخ پایان باشد"); } joinedQuery = joinedQuery.Where(x => x.contract.ContractStartGr <= dateTo && x.contract.ContractEndGr <= dateFrom); } if (searchModel.HasSignature != null) { var hasSignature = searchModel.HasSignature == true ? "1" : "0"; joinedQuery = joinedQuery.Where(x => x.contract.Signature == hasSignature); } if (searchModel.IsActive != null) { var isActiveStr = searchModel.IsActive == true ? "true" : "false"; joinedQuery = joinedQuery.Where(x => x.contract.IsActiveString == isActiveStr || x.contract.IsActiveString == "blue"); } if (searchModel.Type != null) { var typeStr = searchModel.Type switch { InstitutionContractType.JobRelation => "JobRelation", InstitutionContractType.TaxAndFinancial => "taxAndFinancial", _ => throw new ArgumentOutOfRangeException() }; joinedQuery = joinedQuery.Where(x => x.contract.TypeOfContract == typeStr); } if (searchModel.IsOfficial != null) { var isOfficialStr = searchModel.IsOfficial == true ? "Official" : "NotOfficial"; joinedQuery = joinedQuery.Where(x => x.contract.OfficialCompany == isOfficialStr); } if (searchModel.Status != null) { switch (searchModel.Status) { case InstitutionContractListStatus.DeactiveWithDebt: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.DeactiveWithDebt); break; case InstitutionContractListStatus.PendingForRenewal: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.PendingForRenewal); break; case InstitutionContractListStatus.Block: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Block); break; case InstitutionContractListStatus.Free: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Free); break; case InstitutionContractListStatus.WithoutWorkshop: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.WithoutWorkshop); break; case InstitutionContractListStatus.Active: joinedQuery = joinedQuery.Where(x => x.StatusPriority == (int)InstitutionContractListStatus.Active); break; case InstitutionContractListStatus.Deactive: joinedQuery = joinedQuery.Where(x => x.contract.ContractEndGr < now); break; case InstitutionContractListStatus.PendingForVerify: joinedQuery = joinedQuery.Where(x => x.contract.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify); break; } } else { joinedQuery = joinedQuery.Where(x => x.contract.IsActiveString != "blue"); } #endregion var totalAmount = await joinedQuery.SumAsync(x => x.contract.ContractAmount); var totalDebt = await _context.FinancialStatments.Include(x => x.FinancialTransactionList) .Where(x => joinedQuery.Select(i => i.contract.ContractingPartyId).Contains(x.ContractingPartyId)) .SelectMany(x => x.FinancialTransactionList) .SumAsync(x => x.Deptor - x.Creditor); var counts = new List(); foreach (var name in typeof(InstitutionContractListStatus).GetEnumNames()) { var @enum = Enum.Parse(name); searchModel.Status = @enum; searchModel.PageSize = 1; var count = (await GetList(searchModel)).TotalCount; counts.Add(new() { ListStatus = @enum, Count = count }); } var res = new GetInstitutionContractListStatsViewModel() { TotalDebt = totalDebt, TotalAmount = totalAmount, Counts = counts }; return res; } public async Task> RegistrationWorkflowMainList() { return await _context.InstitutionContractSet .Where(x => x.VerificationStatus == InstitutionContractVerificationStatus.PendingWorkflow) .Include(x => x.WorkshopGroup) .ThenInclude(x => x.InitialWorkshops) .Join(_context.PersonalContractingParties, institutionContract => institutionContract.ContractingPartyId, contractingParty => contractingParty.id, (institutionContract, contractingParty) => new { institutionContract, contractingParty }).Select(x => new RegistrationWorkflowMainListViewModel { InstitutionContractId = x.institutionContract.id, ContractingPartyFullName = $"{x.contractingParty.FName} {x.contractingParty.LName}", Phone = x.contractingParty.Phone, Amount = x.institutionContract.TotalAmount, DoneWorkshops = x.institutionContract.WorkshopGroup.InitialWorkshops.Count(w => w.WorkshopCreated), TotalWorkshops = x.institutionContract.WorkshopGroup.InitialWorkshops.Count, UnDoneWorkshops = x.institutionContract.WorkshopGroup.InitialWorkshops.Count(w => !w.WorkshopCreated), ContractingPartyId = x.contractingParty.id }).ToListAsync(); } /// /// دریافت لیست اقلام گردش کار ثبت نام /// /// شناسه قرارداد نهاد /// لیست اقلام گردش کار ثبت نام public async Task> RegistrationWorkflowItems(long institutionContractId) { // دریافت قرارداد نهاد همراه با جزئیات کارگاه‌ها var institutionContract = await _context.InstitutionContractSet .Include(x => x.WorkshopGroup).ThenInclude(institutionContractWorkshopGroup => institutionContractWorkshopGroup.InitialWorkshops).ThenInclude(institutionContractWorkshopDetail => institutionContractWorkshopDetail.Employers) .FirstOrDefaultAsync(x => x.id == institutionContractId); if (institutionContract == null) throw new NotFoundException("قرارداد مؤسسه یافت نشد"); // استخراج شناسه‌های کارگاه‌هایی که ایجاد شده‌اند var workshopIds = institutionContract.WorkshopGroup.InitialWorkshops .Where(x => x.WorkshopId != null) .Select(x => x.WorkshopId.Value) .ToList(); // دریافت کارگاه‌ها همراه با کارفرمایان در یک کوئری var workshops = await _context.Workshops .Where(x => workshopIds.Contains(x.id)) .ToListAsync(); // استخراج تمامی شناسه‌های کارفرمایان از جزئیات کارگاه‌ها var allEmployerIds = institutionContract.WorkshopGroup.InitialWorkshops .SelectMany(x => x.Employers.Select(e => e.EmployerId)) .Distinct() .ToList(); // دریافت اطلاعات کارفرمایان در یک کوئری واحد var employersDict = (await _context.Employers .Where(e => allEmployerIds.Contains(e.id)) .Select(e => new { e.id, e.FullName }) .ToListAsync()) .ToDictionary(e => e.id, e => e); // ساخت نتیجه نهایی با استفاده از داده‌های از پیش بارگذاری شده var items = institutionContract.WorkshopGroup .InitialWorkshops.Select(workshopDetail => { // پیدا کردن کارگاه مرتبط var workshop = workshops.FirstOrDefault(w => w.id == workshopDetail.WorkshopId); // ساخت لیست کارفرمایان این جزئیات کارگاه var employers = workshopDetail.Employers .Where(e => employersDict.ContainsKey(e.EmployerId)) .Select(e => new RegistrationWorkflowItemsEmployerViewModel { Id = e.EmployerId, FullName = employersDict[e.EmployerId].FullName }) .ToList(); return new RegistrationWorkflowItemsViewModel { Price = workshopDetail.Price, IsDone = workshop != null, PersonnelCount = workshopDetail.PersonnelCount, WorkshopName = workshopDetail.WorkshopName, Employers = employers, WorkshopDetailsId = workshopDetail.id }; }).ToList(); return items; } private (InstitutionContractListStatus status, bool isExpiered) SetContractStatus(InstitutionContract contract, PersonalContractingParty contractingParty, FinancialStatment financialStatment) { //if (contract.ContractEndGr <= endThisMontGr) var now = DateTime.Now; var nowFa = now.ToFarsi(); var endFa = nowFa.FindeEndOfMonth(); var endThisMontGr = endFa.ToGeorgianDateTime(); InstitutionContractListStatus listStatus = InstitutionContractListStatus.Active; bool isExpier = false; if (contract.ContractEndGr < now) { listStatus = InstitutionContractListStatus.Deactive; isExpier = true; } if (contract.ContractEndGr >= now && contract.ContractEndGr <= endThisMontGr) { listStatus = InstitutionContractListStatus.PendingForRenewal; isExpier = true; } if (contract.ContractAmount == 0) { listStatus = InstitutionContractListStatus.Free; if ((contract.ContractEndGr >= now && contract.ContractEndGr <= endThisMontGr) || (contract.ContractEndGr < now)) { isExpier = true; } } if (contract.IsActiveString == "blue") { listStatus = InstitutionContractListStatus.DeactiveWithDebt; isExpier = true; } var workshops = contractingParty.Employers .SelectMany(e => e.WorkshopEmployers.Select(we => we.Workshop)).DistinctBy(w => w.id).ToList(); if (workshops.Count == 0) { listStatus = InstitutionContractListStatus.Free; } if (contractingParty.IsBlock == "true") { listStatus = InstitutionContractListStatus.Block; } return (listStatus, isExpier); } public async Task GetInstitutionWorkshopInitialDetails( long institutionWorkshopInitialId) { var result = await _context.InstitutionContractWorkshopInitials.Include(x => x.WorkshopGroup) .Include(x => x.Employers) .FirstOrDefaultAsync(x => x.id == institutionWorkshopInitialId); return result; } public async Task GetIncludeWorkshopDetailsAsync(long institutionContractId) { return await _context.InstitutionContractSet .Include(x => x.WorkshopGroup) .ThenInclude(x => x.InitialWorkshops) .Include(x => x.WorkshopGroup) .ThenInclude(x => x.CurrentWorkshops) .Include(x=>x.Installments) .FirstOrDefaultAsync(x => x.id == institutionContractId); } public void UpdateStatusIfNeeded(long institutionContractId) { var institutionContract = _context.InstitutionContractSet .Include(x => x.WorkshopGroup).ThenInclude(institutionContractWorkshopGroup => institutionContractWorkshopGroup.InitialWorkshops) .FirstOrDefault(x => x.id == institutionContractId); if (institutionContract == null) throw new NotFoundException("قرارداد مؤسسه یافت نشد"); if (institutionContract.VerificationStatus == InstitutionContractVerificationStatus.Verified) return; if (institutionContract.WorkshopGroup.InitialWorkshops .All(x => x.WorkshopCreated)) institutionContract.Verified(); _context.SaveChanges(); } public async Task GetVerificationDetails(Guid id) { var query = await _context.InstitutionContractSet.Where(x => x.PublicId == id) .Include(x => x.WorkshopGroup).ThenInclude(institutionContractWorkshopGroup => institutionContractWorkshopGroup.InitialWorkshops) .Include(institutionContract => institutionContract.Installments) .Join(_context.PersonalContractingParties, institutionContract => institutionContract.ContractingPartyId, contractingParty => contractingParty.id, (contract, party) => new { contract, party }).FirstOrDefaultAsync(); if (query == null) { throw new NotFoundException("قرارداد مؤسسه یافت نشد"); } if (query.contract.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify) { throw new BadRequestException( "قرارداد وارد شده تایید شده میباشد", new Dictionary { { "isVerified", true } } ); } int installmentNumber = 1; var res = new GetInstitutionVerificationDetailsViewModel() { ContractStart = query.contract.ContractStartFa, ContractEnd = query.contract.ContractEndFa, ContractNo = query.contract.ContractNo, CreationDate = query.contract.CreationDate.ToFarsi(), TaxPrice = query.contract.ValueAddedTax.ToMoney(), TotalPrice = (query.contract.TotalAmount - query.contract.ValueAddedTax).ToMoney(), PaymentPrice = query.contract.TotalAmount.ToMoney(), IsInstallment = query.contract.IsInstallment, Installments = query.contract.Installments.OrderBy(x => x.InstallmentDateGr) .Select(x => { var res = new InstitutionContractInstallmentViewModel() { Amount = x.Amount.ToMoney(), InstallmentIndex = GetInstallmentPersianNumber(installmentNumber), Id = x.Id, InstallmentDateFa = x.InstallmentDateFa, InstallmentDateGr = x.InstallmentDateGr, InstitutionContractId = x.InstitutionContractId, }; installmentNumber++; return res; }).ToList(), Workshops = query.contract.WorkshopGroup.InitialWorkshops .Select(x => new GetInstitutionVerificationDetailsWorkshopsViewModel { Services = new WorkshopServicesViewModel() { Contract = x.Services.Contract, ContractInPerson = x.Services.ContractInPerson, CustomizeCheckout = x.Services.CustomizeCheckout, Insurance = x.Services.Insurance, InsuranceInPerson = x.Services.InsuranceInPerson, RollCall = x.Services.RollCall, RollCallInPerson = x.Services.RollCallInPerson }, Name = x.WorkshopName, PersonnelCount = x.PersonnelCount, Price = x.Price.ToMoney() }).ToList(), SecondParty = new InstitutionContratVerificationParty() { Address = query.contract.Address, PhoneNumber = query.party.Phone, CeoName = query.party.IsLegal == "حقیقی" ? $"{query.party.FName} {query.party.LName}" : $"{query.party.CeoFName} {query.party.CeoLName}", CompanyNameOrFullName = query.party.IsLegal == "حقیقی" ? $"{query.party.FName} {query.party.LName}" : query.party.LName, NationalCodeOrNationalId = query.party.IsLegal == "حقیقی" ? query.party.Nationalcode : query.party.NationalId, LegalType = query.party.IsLegal == "حقیقی" ? LegalType.Real : LegalType.Legal, }, FirstParty = _firstParty }; return res; } private string GetInstallmentPersianNumber(int number) { return number switch { 1 => "اول", 2 => "دوم", 3 => "سوم", 4 => "چهارم", 5 => "پنجم", 6 => "ششم", 7 => "هفتم", 8 => "هشتم", 9 => "نهم", 10 => "دهم", 11 => "یازدهم", 12 => "دوازدهم", _ => number.ToString() }; } public async Task GetByPublicIdAsync(Guid id) { return await _context.InstitutionContractSet .Include(x => x.ContactInfoList) .Include(x => x.Installments) .FirstOrDefaultAsync(x => x.PublicId == id); } public InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request,string contractStart=null) { var baseAmount = request.TotalAmount; var discountAmount = (baseAmount * request.DiscountPercentage) / 100; var discountOneMonthAmount = (request.OneMonthAmount * request.DiscountPercentage) / 100; var discountedOneMonthAmount = request.OneMonthAmount - discountOneMonthAmount; var totalAmount = baseAmount - discountAmount; var taxAmount = totalAmount * 0.10; var paymentAmount = totalAmount + taxAmount; InstitutionContractDiscountMonthlyViewModel monthlyPayment = null; InstitutionContractDiscountOneTimeViewModel oneTimePayment = null; if (request.IsInstallment) { monthlyPayment = new InstitutionContractDiscountMonthlyViewModel() { TotalAmount = totalAmount.ToMoney(), PaymentAmount = paymentAmount.ToMoney(), Tax = taxAmount.ToMoney(), DiscountedAmount = discountAmount.ToMoney(), DiscountPercetage = request.DiscountPercentage, Installments = InstitutionMonthlyInstallmentCaculation((int)request.Duration, totalAmount, DateTime.Now.ToFarsi()), OneMonthAmount = discountedOneMonthAmount.ToMoney(), Obligation = totalAmount.ToMoney() }; } else { oneTimePayment = new InstitutionContractDiscountOneTimeViewModel() { TotalAmount = totalAmount.ToMoney(), PaymentAmount = paymentAmount.ToMoney(), Tax = taxAmount.ToMoney(), DiscountedAmount = discountAmount.ToMoney(), DiscountPercetage = request.DiscountPercentage, OneMonthAmount = discountedOneMonthAmount.ToMoney(), Obligation = totalAmount.ToMoney() }; } if (discountAmount > baseAmount) throw new BadRequestException("مقدار تخفیف نمی‌تواند بیشتر از مبلغ کل باشد"); return new InstitutionContractDiscountResponse() { Monthly = monthlyPayment, OneTime = oneTimePayment }; } public InstitutionContractDiscountResponse ResetDiscountCreate( InstitutionContractResetDiscountForCreateRequest request) { InstitutionContractDiscountMonthlyViewModel monthlyPayment = null; InstitutionContractDiscountOneTimeViewModel oneTimePayment = null; if (request.IsInstallment) { var newTotalAmount = request.TotalAmount / (1 - (request.DiscountPercentage / 100.0)); var taxAmount = (newTotalAmount * 0.10); var paymentAmount = (newTotalAmount + taxAmount); var newOneMonthAmount = request.OneMonthAmount / (1 - (request.DiscountPercentage / 100.0)); monthlyPayment = new InstitutionContractDiscountMonthlyViewModel() { TotalAmount = newTotalAmount.ToMoney(), Tax = taxAmount.ToMoney(), DiscountedAmount = "0", DiscountPercetage = 0, PaymentAmount = paymentAmount.ToMoney(), Installments = InstitutionMonthlyInstallmentCaculation((int)request.Duration, paymentAmount, DateTime.Now.ToFarsi()), Obligation = newTotalAmount.ToMoney(), OneMonthAmount = newOneMonthAmount.ToMoney() }; } else { var newTotalAmount = request.TotalAmount / (1 - ((double)request.DiscountPercentage / 100)); var taxAmount = (newTotalAmount * 0.10); var paymentAmount = (newTotalAmount + taxAmount); var newOneMonthAmount = request.OneMonthAmount / (1 - ((double)request.DiscountPercentage / 100)); oneTimePayment = new InstitutionContractDiscountOneTimeViewModel() { TotalAmount = newTotalAmount.ToMoney(), Tax = taxAmount.ToMoney(), PaymentAmount = paymentAmount.ToMoney(), DiscountedAmount = "0", DiscountPercetage = 0, Obligation = newTotalAmount.ToMoney(), OneMonthAmount = newOneMonthAmount.ToMoney() }; } return new InstitutionContractDiscountResponse() { Monthly = monthlyPayment, OneTime = oneTimePayment }; } #region Extension public async Task GetExtensionInquiry(long previousContractId) { var institutionContracts = await _context.InstitutionContractSet .Include(institutionContract => institutionContract.ContactInfoList) .FirstOrDefaultAsync(x => x.id == previousContractId); var contractingParty = await _context.PersonalContractingParties.FirstOrDefaultAsync(x => x.id == institutionContracts.ContractingPartyId); var legalType = contractingParty.IsLegal == "حقیقی" ? LegalType.Real : LegalType.Legal; CreateInstitutionContractLegalPartyRequest legalPartyRequest = null; CreateInstitutionContractRealPartyRequest realPartyRequest = null; if (legalType == LegalType.Legal) { legalPartyRequest = new CreateInstitutionContractLegalPartyRequest() { NationalCode = contractingParty.Nationalcode == "*" ? string.Empty : contractingParty.Nationalcode, BirthDateFa = contractingParty.DateOfBirth.ToFarsi(), PhoneNumber = contractingParty.Phone, FatherName = contractingParty.FatherName, FName = contractingParty.CeoFName, LName = contractingParty.CeoLName, CompanyName = contractingParty.LName, Gender = contractingParty.Gender, IdNumber = contractingParty.IdNumber, RegisterId = contractingParty.RegisterId, IsAuth = contractingParty.IsAuthenticated, NationalId = contractingParty.NationalId, Position = contractingParty.LegalPosition, ContractingPartyTempId = 0 }; } else { realPartyRequest = new CreateInstitutionContractRealPartyRequest() { NationalCode = contractingParty.Nationalcode, BirthDateFa = contractingParty.DateOfBirth.ToFarsi(), PhoneNumber = contractingParty.Phone, FatherName = contractingParty.FatherName, FName = contractingParty.FName, Gender = contractingParty.Gender, IdNumber = contractingParty.IdNumber, IsAuth = contractingParty.IsAuthenticated, LName = contractingParty.LName, ContractingPartyTempId = 0 }; } var previousContractTemp = await _institutionExtensionTemp .Find(x => x.PreviousId == previousContractId) .FirstOrDefaultAsync(); if (previousContractTemp != null) { await _institutionExtensionTemp.DeleteOneAsync(x => x.Id == previousContractTemp.Id); } var institutionContractTemp = new InstitutionContractExtensionTemp(previousContractId); await _institutionExtensionTemp.InsertOneAsync(institutionContractTemp); var res = new InstitutionContractExtensionInquiryResult() { LegalType = legalType, Address = contractingParty.Address, City = contractingParty.City, ContactInfoViewModels = institutionContracts.ContactInfoList.Select(x => new EditContactInfo() { Id = x.id, FnameLname = x.FnameLname, InstitutionContractId = x.InstitutionContractId, PhoneNumber = x.PhoneNumber, PhoneType = x.PhoneType, Position = x.Position, SendSms = x.SendSms }).ToList(), Province = contractingParty.State, LegalParty = legalPartyRequest, RealParty = realPartyRequest, TemporaryId = institutionContractTemp.Id, RepresentativeId = institutionContracts.RepresentativeId }; return res; } public async Task GetExtensionWorkshops( InstitutionContractExtensionWorkshopsRequest request) { var transaction = await _context.Database.BeginTransactionAsync(); switch (request.LegalType) { case LegalType.Legal: var legalCommand = request.LegalParty; var legalPersonalContractingParty = _context.PersonalContractingParties .FirstOrDefault(x => x.NationalId == legalCommand.NationalId); if (!request.LegalParty.IsAuth) { if (legalPersonalContractingParty is { IsAuthenticated: false }) { legalPersonalContractingParty.UnAuthenticateLegalEdit(legalCommand.FName, legalCommand.LName, legalCommand.FatherName, legalCommand.IdNumber, legalPersonalContractingParty.IdNumberSeri, legalPersonalContractingParty.IdNumberSerial, legalCommand.BirthDateFa, legalCommand.Gender, legalCommand.PhoneNumber); } } else { legalPersonalContractingParty?.LegalAuthentication(legalCommand.FName, legalCommand.LName, legalCommand.FatherName, legalCommand.IdNumber, legalPersonalContractingParty.IdNumberSeri, legalPersonalContractingParty.IdNumberSerial, legalCommand.BirthDateFa, legalCommand.Gender, legalCommand.PhoneNumber); } legalPersonalContractingParty?.EditLegalPartyFromInstitution(legalCommand.Position, legalCommand.CompanyName, legalCommand.RegisterId, legalCommand.NationalId); break; case LegalType.Real: if (!request.RealParty.IsAuth) { var realCommand = request.RealParty; var personalContractingParty = _context.PersonalContractingParties .FirstOrDefault(x => x.Nationalcode == realCommand.NationalCode); if (personalContractingParty is { IsAuthenticated: false }) { personalContractingParty.UnAuthenticateRealEdit(realCommand.FName, realCommand.LName, realCommand.FatherName, realCommand.IdNumber, personalContractingParty.IdNumberSeri, personalContractingParty.IdNumberSerial, realCommand.BirthDateFa, realCommand.Gender, realCommand.PhoneNumber); } } break; } await SaveChangesAsync(); await transaction.CommitAsync(); var extenstionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId) .FirstOrDefaultAsync(); if (extenstionTemp == null) { throw new BadRequestException("دیتای درخواست شده نامعتبر است"); } var prevInstitutionContracts = await _context.InstitutionContractSet .Include(x => 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("قرارداد مالی قبلی یافت نشد"); } extenstionTemp.SetContractingPartyInfos(request.Address, request.City, request.Province, request.ContactInfos); await _institutionExtensionTemp.ReplaceOneAsync( x => x.Id == extenstionTemp.Id, extenstionTemp ); var workshopIds = prevInstitutionContracts.WorkshopGroup.CurrentWorkshops.Select(x => x.WorkshopId.Value); 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 => { var workshop = workshops.FirstOrDefault(w => w.id == x.WorkshopId); var service = x.Services; var price = x.Price; if (x.Price == 0) { var command = new WorkshopTempViewModel() { ContractAndCheckout = service.Contract, ContractAndCheckoutInPerson = service.ContractInPerson, CountPerson = x.PersonnelCount, CustomizeCheckout = service.CustomizeCheckout, Insurance = service.Insurance, InsuranceInPerson = service.InsuranceInPerson, RollCall = service.RollCall, WorkshopName = x.WorkshopName, RollCallInPerson = service.RollCallInPerson, }; var institutionPlanForWorkshop = _planPercentageRepository.GetInstitutionPlanForWorkshop(command); price = institutionPlanForWorkshop.OnlineAndInPersonSumAmountDouble; } return new WorkshopTempViewModel() { Id = x.id, ContractAndCheckout = service.Contract, ContractAndCheckoutInPerson = service.ContractInPerson, CustomizeCheckout = service.CustomizeCheckout, CountPerson = x.PersonnelCount, Insurance = service.Insurance, InsuranceInPerson = service.InsuranceInPerson, RollCall = service.RollCall, WorkshopName = workshop?.WorkshopName ?? "فاقد کارگاه", WorkshopServicesAmount = price, WorkshopServicesAmountStr = price.ToMoney(), WorkshopId = workshop?.id ?? 0, RollCallInPerson = service.RollCallInPerson }; }).ToList(); var notIncludeWorskhopsLeftWork =await _context.LeftWorkList .Where(x => 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(), WorkshopTemps = workshopDetails }; return res; } public async Task GetExtensionInstitutionPlan( InstitutionContractExtensionPlanRequest request) { if (request.WorkshopTemps.Count == 0) throw new BadRequestException("هیچ کارگاهی یافت نشد"); bool hasInPerson = request.WorkshopTemps.Any(x => x.ContractAndCheckoutInPerson); double amount = request.TotalAmount.MoneyToDouble(); var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId).FirstOrDefaultAsync(); var previousInstitution = await _context.InstitutionContractSet.FirstOrDefaultAsync(x => x.id == institutionTemp.PreviousId); var res = new InstitutionContractExtensionPlanResponse(); DateTime newContractStart; if (previousInstitution.ContractEndGr <= DateTime.Now) { newContractStart = DateTime.Now; } else { newContractStart = previousInstitution.ContractEndGr.AddDays(1); } if (hasInPerson) { res.OneMonth = null; res.ThreeMonths = null; res.SixMonths = null; res.TwelveMonths = CalculateInstitutionPlan(InstitutionContractDuration.TwelveMonths, amount, true, newContractStart); } else { res.OneMonth = CalculateInstitutionPlan(InstitutionContractDuration.OneMonth, amount, false, newContractStart); res.ThreeMonths = CalculateInstitutionPlan(InstitutionContractDuration.ThreeMonths, amount, false, newContractStart); res.SixMonths = CalculateInstitutionPlan(InstitutionContractDuration.SixMonths, amount, false, newContractStart); res.TwelveMonths = CalculateInstitutionPlan(InstitutionContractDuration.TwelveMonths, amount, false, newContractStart); } var workshops = request.WorkshopTemps .Select(x => new InstitutionContractExtensionTempWorkshop(x.WorkshopName, x.CountPerson, x.ContractAndCheckout, x.ContractAndCheckoutInPerson, x.Insurance, x.InsuranceInPerson, x.RollCall, x.RollCall, x.RollCallInPerson, x.WorkshopServicesAmount, x.WorkshopId)).ToList(); institutionTemp.SetWorkshopsAndPlanAmounts(workshops, res.OneMonth, res.ThreeMonths, res.SixMonths, res.TwelveMonths, hasInPerson); await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, institutionTemp); return res; } public async Task GetExtensionPaymentMethod( InstitutionContractExtensionPaymentRequest request) { var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId).FirstOrDefaultAsync(); if (institutionTemp == null) throw new BadRequestException("اطلاعات وارد شده نامعتبر است"); var duration = request.Duration; var selectedPlan = duration switch { InstitutionContractDuration.OneMonth => institutionTemp.OneMonth, InstitutionContractDuration.ThreeMonths => institutionTemp.ThreeMonths, InstitutionContractDuration.SixMonths => institutionTemp.SixMonths, InstitutionContractDuration.TwelveMonths => institutionTemp.TwelveMonths, _ => throw new ArgumentOutOfRangeException() }; var baseAmount = selectedPlan.TotalPayment.MoneyToDouble(); var vatOrDiscount = baseAmount * 0.10; var res = institutionTemp.HasContractInPerson ? CalculateInPersonPayment(selectedPlan, baseAmount, vatOrDiscount, request.Duration) : CalculateOnlinePayment(baseAmount, vatOrDiscount); institutionTemp.SetAmountAndDuration(duration, res.Monthly, res.OneTime); await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, institutionTemp); return res; } public async Task SetDiscountForExtension( InstitutionContractSetDiscountForExtensionRequest request) { if (request.DiscountPercentage <= 0) throw new BadRequestException("مقدار تخفیف نمی‌تواند برابر یا کمتر از صفر باشد"); if (request.DiscountPercentage>=100) { throw new BadRequestException("مقدار تخفیف نمی‌تواند برابر یا بیشتر از صد باشد"); } var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId) .FirstOrDefaultAsync(); if (institutionTemp == null) { throw new BadRequestException("اطلاعات وارد شده نامعتبر است"); } if (request.IsInstallment) { if (institutionTemp.MonthlyPayment.DiscountPercetage > 0) throw new BadRequestException("تخفیف قبلا برای این قرارداد اعمال شده است"); } else { if (institutionTemp.OneTimePayment.DiscountPercetage > 0) throw new BadRequestException("تخفیف قبلا برای این قرارداد اعمال شده است"); } var selectedPlan = institutionTemp.Duration switch { InstitutionContractDuration.OneMonth => institutionTemp.OneMonth, InstitutionContractDuration.ThreeMonths => institutionTemp.ThreeMonths, InstitutionContractDuration.SixMonths => institutionTemp.SixMonths, InstitutionContractDuration.TwelveMonths => institutionTemp.TwelveMonths, _ => throw new ArgumentOutOfRangeException() }; var calculateRequest = new InstitutionContractSetDiscountRequest() { Duration = institutionTemp.Duration.Value, TotalAmount = request.TotalAmount, DiscountPercentage = request.DiscountPercentage, IsInstallment = request.IsInstallment, OneMonthAmount = selectedPlan.OneMonthPaymentDiscounted.MoneyToDouble() }; var res = CalculateDiscount(calculateRequest,selectedPlan.ContractStart); //این به این دلیل هست که متد caclulate discount یکی از مقادیر رو پر میکنه و ما نیاز داریم هر دو مقدار رو داشته باشیم if (request.IsInstallment) { var onetime = institutionTemp.OneTimePayment; onetime.TotalAmountWithoutDiscount = onetime.TotalAmount; onetime.OneMonthPaymentWithoutDiscount = selectedPlan.OneMonthPaymentDiscounted; institutionTemp.OneTimePayment.TotalAmountWithoutDiscount = onetime.TotalAmount; institutionTemp.OneTimePayment.OneMonthPaymentWithoutDiscount = selectedPlan.OneMonthPaymentDiscounted; res.OneTime = new() { PaymentAmount = onetime.PaymentAmount, Tax = onetime.Tax, TotalAmount = onetime.TotalAmount, DiscountedAmount = onetime.DiscountedAmount, DiscountPercetage = onetime.DiscountPercetage, }; institutionTemp.MonthlyPayment = new() { Installments = res.Monthly.Installments, PaymentAmount = res.Monthly.PaymentAmount, Tax = res.Monthly.Tax, TotalAmount = res.Monthly.TotalAmount, DiscountedAmount = res.Monthly.DiscountedAmount, DiscountPercetage = res.Monthly.DiscountPercetage, TotalAmountWithoutDiscount = institutionTemp.MonthlyPayment.TotalAmount, OneMonthPaymentWithoutDiscount = selectedPlan.OneMonthPaymentDiscounted, }; selectedPlan.TotalPayment = res.Monthly.TotalAmount; selectedPlan.Obligation = res.Monthly.Obligation; selectedPlan.OneMonthPaymentDiscounted = res.Monthly.OneMonthAmount; selectedPlan.DailyCompenseation = (res.Monthly.OneMonthAmount.MoneyToDouble() * 0.10).ToMoney(); } else { var monthly = institutionTemp.MonthlyPayment; institutionTemp.MonthlyPayment.TotalAmountWithoutDiscount = monthly.TotalAmount; res.Monthly = new() { PaymentAmount = monthly.PaymentAmount, Tax = monthly.Tax, TotalAmount = monthly.TotalAmount, DiscountedAmount = monthly.DiscountedAmount, DiscountPercetage = monthly.DiscountPercetage, Installments = monthly.Installments, }; institutionTemp.OneTimePayment = new() { PaymentAmount = res.OneTime.PaymentAmount, Tax = res.OneTime.Tax, TotalAmount = res.OneTime.TotalAmount, DiscountedAmount = res.OneTime.DiscountedAmount, DiscountPercetage = res.OneTime.DiscountPercetage, TotalAmountWithoutDiscount = institutionTemp.OneTimePayment.TotalAmount, OneMonthPaymentWithoutDiscount = selectedPlan.OneMonthPaymentDiscounted, }; selectedPlan.TotalPayment = res.OneTime.TotalAmount; selectedPlan.Obligation = res.OneTime.Obligation; selectedPlan.OneMonthPaymentDiscounted = res.OneTime.OneMonthAmount; selectedPlan.DailyCompenseation = (res.OneTime.OneMonthAmount.MoneyToDouble() * 0.10).ToMoney(); } switch (institutionTemp.Duration) { case InstitutionContractDuration.OneMonth: institutionTemp.OneMonth = selectedPlan; break; case InstitutionContractDuration.ThreeMonths: institutionTemp.ThreeMonths = selectedPlan; break; case InstitutionContractDuration.SixMonths: institutionTemp.SixMonths = selectedPlan; break; case InstitutionContractDuration.TwelveMonths: institutionTemp.TwelveMonths = selectedPlan; break; default: throw new ArgumentOutOfRangeException(); } await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, institutionTemp); return new() { OneTime = res.OneTime, Monthly = res.Monthly }; } public async Task ResetDiscountForExtension (InstitutionContractResetDiscountForExtensionRequest request) { var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId) .FirstOrDefaultAsync(); if (institutionTemp == null) { throw new BadRequestException("اطلاعات وارد شده نامعتبر است"); } InstitutionContractDiscountMonthlyViewModel monthlyPayment = null; InstitutionContractDiscountOneTimeViewModel oneTimePayment = null; var selectedPlan = institutionTemp.Duration switch { InstitutionContractDuration.OneMonth => institutionTemp.OneMonth, InstitutionContractDuration.ThreeMonths => institutionTemp.ThreeMonths, InstitutionContractDuration.SixMonths => institutionTemp.SixMonths, InstitutionContractDuration.TwelveMonths => institutionTemp.TwelveMonths, _ => throw new ArgumentOutOfRangeException() }; if (request.IsInstallment) { var prevMonthlyPayment = institutionTemp.MonthlyPayment; var resetTotalAmount = prevMonthlyPayment.TotalAmountWithoutDiscount.MoneyToDouble(); var resetTax = (resetTotalAmount * 0.10); var paymentAmount = (resetTotalAmount + resetTax); var newOneMonthAmount = prevMonthlyPayment.OneMonthPaymentWithoutDiscount.MoneyToDouble(); monthlyPayment = new InstitutionContractDiscountMonthlyViewModel() { DiscountPercetage = 0, DiscountedAmount = "0", PaymentAmount = paymentAmount.ToMoney(), Tax = resetTax.ToMoney(), TotalAmount = resetTotalAmount.ToMoney(), Installments = InstitutionMonthlyInstallmentCaculation((int)institutionTemp.Duration.Value, paymentAmount,selectedPlan.ContractStart), OneMonthAmount = newOneMonthAmount.ToMoney(), Obligation = resetTotalAmount.ToMoney() }; institutionTemp.MonthlyPayment = new InstitutionContractPaymentMonthlyViewModel() { Installments = monthlyPayment.Installments, PaymentAmount = monthlyPayment.PaymentAmount, Tax = monthlyPayment.Tax, TotalAmount = monthlyPayment.TotalAmount, DiscountedAmount = monthlyPayment.DiscountedAmount, DiscountPercetage = monthlyPayment.DiscountPercetage, }; selectedPlan.TotalPayment = monthlyPayment.TotalAmount; selectedPlan.Obligation = monthlyPayment.Obligation; selectedPlan.OneMonthPaymentDiscounted = monthlyPayment.OneMonthAmount; selectedPlan.DailyCompenseation = (monthlyPayment.OneMonthAmount.MoneyToDouble() * 0.10).ToMoney(); switch (institutionTemp.Duration) { case InstitutionContractDuration.OneMonth: institutionTemp.OneMonth = selectedPlan; break; case InstitutionContractDuration.ThreeMonths: institutionTemp.ThreeMonths = selectedPlan; break; case InstitutionContractDuration.SixMonths: institutionTemp.SixMonths = selectedPlan; break; case InstitutionContractDuration.TwelveMonths: institutionTemp.TwelveMonths = selectedPlan; break; default: throw new ArgumentOutOfRangeException(); } await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, institutionTemp); } else { var prevOneTimePayment = institutionTemp.OneTimePayment; var resetTotalAmount = prevOneTimePayment.TotalAmountWithoutDiscount.MoneyToDouble(); var resetTax = (resetTotalAmount * 0.10); var newOneMonthAmount = prevOneTimePayment.OneMonthPaymentWithoutDiscount.MoneyToDouble(); oneTimePayment = new InstitutionContractDiscountOneTimeViewModel() { DiscountPercetage = 0, DiscountedAmount = "0", TotalAmount = resetTotalAmount.ToMoney(), Tax = resetTax.ToMoney(), PaymentAmount = (resetTotalAmount + resetTax).ToMoney(), OneMonthAmount = newOneMonthAmount.ToMoney(), Obligation = resetTotalAmount.ToMoney() }; institutionTemp.OneTimePayment = new InstitutionContractPaymentOneTimeViewModel() { PaymentAmount = oneTimePayment.PaymentAmount, Tax = oneTimePayment.Tax, TotalAmount = oneTimePayment.TotalAmount, DiscountedAmount = oneTimePayment.DiscountedAmount, DiscountPercetage = oneTimePayment.DiscountPercetage, TotalAmountWithoutDiscount = institutionTemp.OneTimePayment.TotalAmount, OneMonthPaymentWithoutDiscount = institutionTemp.OneTimePayment.OneMonthPaymentWithoutDiscount }; selectedPlan.TotalPayment = institutionTemp.HasContractInPerson? (oneTimePayment.TotalAmount.MoneyToDouble()/(0.9)).ToMoney() :oneTimePayment.TotalAmount; selectedPlan.Obligation = oneTimePayment.Obligation; selectedPlan.OneMonthPaymentDiscounted = oneTimePayment.OneMonthAmount; selectedPlan.DailyCompenseation = (oneTimePayment.OneMonthAmount.MoneyToDouble() * 0.10).ToMoney(); switch (institutionTemp.Duration) { case InstitutionContractDuration.OneMonth: institutionTemp.OneMonth = selectedPlan; break; case InstitutionContractDuration.ThreeMonths: institutionTemp.ThreeMonths = selectedPlan; break; case InstitutionContractDuration.SixMonths: institutionTemp.SixMonths = selectedPlan; break; case InstitutionContractDuration.TwelveMonths: institutionTemp.TwelveMonths = selectedPlan; break; default: throw new ArgumentOutOfRangeException(); } await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, institutionTemp); } return new InstitutionContractDiscountResponse() { OneTime = oneTimePayment, Monthly = monthlyPayment }; } public async Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request) { var institutionContractTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TemporaryId) .FirstOrDefaultAsync(); if (institutionContractTemp == null) throw new BadRequestException("اطلاعات وارد شده نامعتبر است"); var selectedDuration = institutionContractTemp.Duration switch { InstitutionContractDuration.OneMonth => institutionContractTemp.OneMonth, InstitutionContractDuration.ThreeMonths => institutionContractTemp.ThreeMonths, InstitutionContractDuration.SixMonths => institutionContractTemp.SixMonths, InstitutionContractDuration.TwelveMonths => institutionContractTemp.TwelveMonths, _ => throw new ArgumentOutOfRangeException() }; var previousInstitutionContract = await _context.InstitutionContractSet .FirstOrDefaultAsync(x => x.id == institutionContractTemp.PreviousId); if (previousInstitutionContract == null) throw new NotFoundException("قرارداد مالی مورد نظر یافت نشد"); var contractingParty = await _context.PersonalContractingParties .FirstOrDefaultAsync(x => x.id == previousInstitutionContract.ContractingPartyId); var payment = request.IsInstallment ? institutionContractTemp.MonthlyPayment : institutionContractTemp.OneTimePayment; bool dateMessages = false; string dateMaessageResult = String.Empty; var opration = new OperationResult(); var extensionNo = previousInstitutionContract.ExtensionNo + 1; if (_context.InstitutionContractSet.Any(x => x.ExtensionNo == extensionNo && x.ContractingPartyId == previousInstitutionContract.ContractingPartyId && x.TypeOfContract == previousInstitutionContract.TypeOfContract)) return opration.Failed("برای این قرارداد قبلا تمدید ایجاد شده است"); var contractStart = selectedDuration.ContractStart; if (string.IsNullOrWhiteSpace(contractStart)) { dateMaessageResult = "تاریخ قراراداد اجباری است. "; dateMessages = true; } if (string.IsNullOrWhiteSpace(contractStart)) { dateMaessageResult += "تاریخ شروع قراراداد اجباری است. "; dateMessages = true; } if (string.IsNullOrWhiteSpace(selectedDuration.ContractEnd)) { dateMaessageResult += "تاریخ پایان قراراداد اجباری است. "; dateMessages = true; } if (dateMessages) return opration.Failed(dateMaessageResult); var firstContract = GetFirstContract(previousInstitutionContract.ContractingPartyId, previousInstitutionContract.TypeOfContract); var syear = firstContract.ContractStartFa.Substring(0, 4); var smonth = firstContract.ContractStartFa.Substring(5, 2); var sday = firstContract.ContractStartFa.Substring(8, 2); //شماره قرارداد var contractNo = $"{syear}{smonth}{sday}/{contractingParty.ArchiveCode}/{extensionNo}"; var contractStartGr = contractStart.ToGeorgianDateTime(); var contractEndGr = selectedDuration.ContractEnd.ToGeorgianDateTime(); var contractDateGr = contractStart.ToGeorgianDateTime(); if (Exists(x => ((contractStartGr >= x.ContractStartGr && contractStartGr <= x.ContractEndGr) || (contractEndGr >= x.ContractStartGr && contractEndGr <= x.ContractEndGr)) && x.TypeOfContract == previousInstitutionContract.TypeOfContract && x.ContractingPartyId == previousInstitutionContract.ContractingPartyId)) return opration.Failed("تاریخ شروع و پایان وارد شده با قرارداد دیگری تداخل دارد"); if (institutionContractTemp.Address != null && institutionContractTemp.Province == null) { return opration.Failed("لطفا استان و شهر را انتخاب کنید"); } if ((institutionContractTemp.Address != null && institutionContractTemp.Province != null) && institutionContractTemp.City == "شهرستان") { return opration.Failed("لطفا شهر را انتخاب کنید"); } if (institutionContractTemp.Address == null && institutionContractTemp.Province != null) { return opration.Failed("لطفا آدرس را وارد کنید"); } var hasValueAddedTax = payment.Tax.MoneyToDouble() > 0 ? "true" : "false"; var workshopsCount = institutionContractTemp.Workshops.Count.ToString(); var workshopDetails = institutionContractTemp .Workshops.Select(x => { var res = new InstitutionContractWorkshopInitial(x.WorkshopName, x.RollCall, x.RollCallInPerson, x.CustomizeCheckout, x.ContractAndCheckout, x.ContractAndCheckoutInPerson, x.Insurance, x.InsuranceInPerson, x.CountPerson, x.Price); if (x.WorkshopId != 0) { res.SetWorkshopId(x.WorkshopId); } return res; }).ToList(); var employeeCount = institutionContractTemp.Workshops.Sum(x => x.CountPerson).ToString(); var oneMonthPayment = selectedDuration.OneMonthPaymentDiscounted.MoneyToDouble(); var contractingPartyFullName = previousInstitutionContract.ContractingPartyName; var totalAmount = payment.PaymentAmount.MoneyToDouble(); var transaction = await _context.Database.BeginTransactionAsync(); var entity = new InstitutionContract(contractNo, previousInstitutionContract.RepresentativeId, previousInstitutionContract.RepresentativeName, previousInstitutionContract.ContractingPartyId, contractingPartyFullName, contractDateGr, contractStart, institutionContractTemp.Province, institutionContractTemp.City, institutionContractTemp.Address, contractStartGr, contractStart, contractEndGr, selectedDuration.ContractEnd, oneMonthPayment, selectedDuration.DailyCompenseation.MoneyToDouble(), selectedDuration.Obligation.MoneyToDouble(), totalAmount, extensionNo, workshopsCount, employeeCount, previousInstitutionContract.Description, "NotOfficial", "JobRelation", hasValueAddedTax, payment.Tax.MoneyToDouble(), [], request.LawId, payment.DiscountPercetage, payment.DiscountedAmount.MoneyToDouble()); await CreateAsync(entity); await SaveChangesAsync(); foreach (var workshop in institutionContractTemp.Workshops) { var workshopDetail = new InstitutionContractWorkshopInitial( workshop.WorkshopName, workshop.RollCall, workshop.RollCallInPerson, workshop.CustomizeCheckout, workshop.ContractAndCheckout, workshop.ContractAndCheckoutInPerson, workshop.Insurance, workshop.InsuranceInPerson, workshop.CountPerson, workshop.Price); workshopDetail.SetWorkshopGroup(entity.WorkshopGroup); if (workshop.WorkshopId != 0) { workshopDetail.SetWorkshopId(workshop.WorkshopId); } // Set parent reference // Add to the parent's collection entity.WorkshopGroup.InitialWorkshops.Add(workshopDetail); } // Save the changes again await SaveChangesAsync(); FinancialStatment financialStatement; if (_context.FinancialStatments.Any(x => x.ContractingPartyId == contractingParty.id)) { financialStatement = await _context.FinancialStatments.FirstOrDefaultAsync(x => x.ContractingPartyId == contractingParty.id); } else { financialStatement = new FinancialStatment(contractingParty.id, contractingPartyFullName); await _context.AddAsync(financialStatement); } if (request.IsInstallment && payment is InstitutionContractPaymentMonthlyViewModel monthly) { var installments = monthly.Installments.Select(x => new InstitutionContractInstallment(x.InstalmentDate.ToGeorgianDateTime(), x.InstallmentAmountStr.MoneyToDouble(), "")).ToList(); // دریافت مبلغ اولین قسط //این کار برای این هست که اولین قسط باید با تاریخ امروز باشد و باید به وضعیت مالی بدهی ایجاد شود که یوزر اولین بدهی را وارد کند var firstInstallmentAmount = installments.First().Amount; // حذف اولین قسط installments.RemoveAt(0); // ایجاد قسط جدید با تاریخ امروز var todayInstallment = new InstitutionContractInstallment(DateTime.Today, firstInstallmentAmount, ""); // اضافه کردن قسط جدید به ابتدای لیست installments.Insert(0, todayInstallment); entity.SetInstallments(installments); await SaveChangesAsync(); } foreach (var contactInfo in institutionContractTemp.ContactInfos) { if (contactInfo.PhoneNumber != null) { var contactinfo = new InstitutionContractContactInfo(contactInfo.PhoneType, contactInfo.Position, contactInfo.PhoneNumber, contactInfo.FnameLname, entity.id, contactInfo.SendSmsString == "true"); _context.InstitutionContractContactInfos.Add(contactinfo); } } await SaveChangesAsync(); await _smsService.SendInstitutionCreationVerificationLink(contractingParty.Phone, contractingPartyFullName, entity.PublicId, contractingParty.id, entity.id); await SaveChangesAsync(); await transaction.CommitAsync(); return opration.Succcedded(); } #endregion public async Task GetAmendmentWorkshops(long institutionContractId) { var institutionContract = await _context.InstitutionContractSet .Include(x => x.WorkshopGroup) .ThenInclude(x => x.CurrentWorkshops) .FirstOrDefaultAsync(x => x.id == institutionContractId); if (institutionContract.WorkshopGroup.CurrentWorkshops.Any(x => x.Price == 0)) { throw new BadRequestException( "این قرارداد قابل ارتقا به صورت ظاهری نیست لطفا به صورت دیتابیسی اقدام به ویرایش کنید"); } var workshops = institutionContract.WorkshopGroup.CurrentWorkshops .Select(x => new InstitutionContractAmendmentTempPrevWorkshop(x.WorkshopName, x.PersonnelCount, x.Services.Contract, x.Services.ContractInPerson, x.Services.Insurance, x.Services.InsuranceInPerson, x.Services.RollCall, x.Services.RollCallInPerson, x.Services.CustomizeCheckout, x.Price, x.WorkshopId ?? 0, x.id)).ToList(); var temp = new InstitutionContractAmendmentTemp(workshops, institutionContractId); await _institutionAmendmentTemp.InsertOneAsync(temp); var prevWorkshops = workshops.Select(x => new InstitutionContractAmendmentTempWorkshopViewModel() { WorkshopName = x.WorkshopName, CountPerson = x.CountPerson, ContractAndCheckout = x.ContractAndCheckout, ContractAndCheckoutInPerson = x.ContractAndCheckoutInPerson, Insurance = x.Insurance, InsuranceInPerson = x.InsuranceInPerson, RollCall = x.RollCall, RollCallInPerson = x.RollCallInPerson, CustomizeCheckout = x.CustomizeCheckout, PriceStr = x.Price.ToMoney(), Price = x.Price, WorkshopId = x.WorkshopId, WorkshopTempId = x.Id, CurrentWorkshopId = x.CurrentWorkshopId, TempId = temp.Id }) .ToList(); var res = new InstitutionContractAmendmentWorkshopsResponse() { Workshops = prevWorkshops, TempId = temp.Id }; return res; } public async Task GetAmendmentPaymentDetails( InsitutionContractAmendmentPaymentRequest request) { var institutionContractAmendmentTemp = await _institutionAmendmentTemp .Find(x => x.Id == request.TempId) .FirstOrDefaultAsync(); if (institutionContractAmendmentTemp == null) throw new NotFoundException("دیتای وارد شده نامعتبر است"); var amendmentStart = DateTime.Now; var institutionContract = await _context.InstitutionContractSet .Include(x => x.WorkshopGroup) .ThenInclude(x => x.CurrentWorkshops) .FirstOrDefaultAsync(x => x.id == institutionContractAmendmentTemp.InstitutionContractId); if (institutionContract == null) throw new NotFoundException("قرارداد مؤسسه یافت نشد"); var amendmentEnd = institutionContract.ContractEndGr; var haContractInPerson = institutionContract.WorkshopGroup.CurrentWorkshops .Any(x => x.Services.ContractInPerson); if (!haContractInPerson) { if (institutionContractAmendmentTemp.NewWorkshops.Any(x => x.ContractAndCheckoutInPerson)) { throw new BadRequestException("برای قرارداد آنلاین نمیتوان سرویس حضوری انتخاب کرد"); } } var pc = new PersianCalendar(); int startYear = pc.GetYear(amendmentStart); int startMonth = pc.GetMonth(amendmentStart); int startDay = pc.GetDayOfMonth(amendmentStart); int endYear = pc.GetYear(amendmentEnd); int endMonth = pc.GetMonth(amendmentEnd); int endDay = pc.GetDayOfMonth(amendmentEnd); // اختلاف خام ماه‌ها int monthDiff = (endYear - startYear) * 12 + (endMonth - startMonth); // اگر حتی چند روز از ماه بعدی هم گذشته بود → رند به بالا if (endDay > startDay) monthDiff++; var sumOneMonth = institutionContractAmendmentTemp.NewWorkshops.Sum(x => x.PriceDifference); var baseAmount = monthDiff * sumOneMonth; var tax = baseAmount * 0.10; var totalPayment = tax + baseAmount; var res = new InsitutionContractAmendmentPaymentResponse() { ContractStart = amendmentStart.ToFarsi(), ContractEnd = amendmentEnd.ToFarsi(), OneMonthAmount = sumOneMonth.ToMoney(), TotalAmount = baseAmount.ToMoney(), }; res.OneTime = new InstitutionContractPaymentOneTimeViewModel() { TotalAmount = baseAmount.ToMoney(), PaymentAmount = totalPayment.ToMoney(), Tax = tax.ToMoney() }; if (haContractInPerson) { var installment = InstitutionMonthlyInstallmentCaculation(monthDiff, totalPayment, amendmentStart.ToFarsi()); var firstPrevInstallment = installment.First(); var lastPrevInstallment = installment.Last(); var firstInstallment = new MonthlyInstallment() { InstallmentAmountStr = firstPrevInstallment.InstallmentAmountStr, InstallmentCounter = firstPrevInstallment.InstallmentCounter, InstalmentDate = amendmentStart.ToFarsi() }; var lastInstallment = new MonthlyInstallment() { InstallmentAmountStr = lastPrevInstallment.InstallmentAmountStr, InstallmentCounter = lastPrevInstallment.InstallmentCounter, InstalmentDate = lastPrevInstallment.InstalmentDate }; installment.Remove(firstPrevInstallment); installment.Remove(lastPrevInstallment); installment.Insert(0, firstInstallment); installment.Add(lastInstallment); res.Monthly = new InstitutionContractPaymentMonthlyViewModel() { Installments = installment, TotalAmount = baseAmount.ToMoney(), PaymentAmount = totalPayment.ToMoney(), Tax = tax.ToMoney() }; } return res; } public async Task InsertAmendmentTempWorkshops( InstitutionContractAmendmentTempWorkshopViewModel request) { var amendmentTemp = await _institutionAmendmentTemp .Find(x => x.Id == request.TempId).FirstOrDefaultAsync(); if (amendmentTemp == null) throw new BadRequestException("دیتای وارد شده نامعتبر است"); var workshopTemp = amendmentTemp.NewWorkshops .FirstOrDefault(x => x.Id == request.WorkshopTempId); var planForWorkshop = new WorkshopTempViewModel() { WorkshopName = request.WorkshopName, CountPerson = request.CountPerson, ContractAndCheckout = request.ContractAndCheckout, ContractAndCheckoutInPerson = request.ContractAndCheckoutInPerson, Insurance = request.Insurance, InsuranceInPerson = request.InsuranceInPerson, RollCall = request.RollCall, RollCallInPerson = request.RollCallInPerson, CustomizeCheckout = request.CustomizeCheckout }; var price = _planPercentageRepository.GetInstitutionPlanForWorkshop(planForWorkshop) .OnlineAndInPersonSumAmountDouble; if (workshopTemp == null) { var newWorkshopTemp = new InstitutionContractAmendmentTempNewWorkshop(request.WorkshopName, request.CountPerson, request.ContractAndCheckout, request.ContractAndCheckoutInPerson, request.Insurance, request.InsuranceInPerson, request.RollCall, request.RollCallInPerson, request.CustomizeCheckout, price, request.WorkshopId, 0, price); workshopTemp = newWorkshopTemp; amendmentTemp.NewWorkshops.Add(newWorkshopTemp); await _institutionAmendmentTemp .ReplaceOneAsync(x => x.Id == amendmentTemp.Id, amendmentTemp); } else { amendmentTemp.NewWorkshops.Remove(workshopTemp); var differencePrice = price - workshopTemp.Price; workshopTemp.Edit(request.WorkshopName, request.CountPerson, request.ContractAndCheckout, request.ContractAndCheckoutInPerson, request.Insurance, request.InsuranceInPerson, request.RollCall, request.CustomizeCheckout, price, differencePrice); amendmentTemp.NewWorkshops.Add(workshopTemp); await _institutionAmendmentTemp .ReplaceOneAsync(x => x.Id == amendmentTemp.Id, amendmentTemp); } return new InsertAmendmentTempWorkshopResponse() { WorkshopTempId = workshopTemp.Id, Amount = workshopTemp.PriceDifference.ToMoney() }; } public async Task RemoveAmendmentWorkshops(Guid workshopTempId) { var amendmentTemp = await _institutionAmendmentTemp.Find(x => x.NewWorkshops.Any(w => w.Id == workshopTempId)) .FirstOrDefaultAsync(); if (amendmentTemp == null) throw new BadRequestException("دیتای وارد شده نامعتبر است"); var workshopTemp = amendmentTemp.NewWorkshops.FirstOrDefault(x => x.Id == workshopTempId); if (workshopTemp == null) throw new BadRequestException("دیتای وارد شده نامعتبر است"); if (workshopTemp.CurrentWorkshopId != 0) throw new BadRequestException("شما نمی توانید این کارگاه را حذف کنید زیرا در قرارداد اصلی وجود دارد"); amendmentTemp.NewWorkshops.Remove(workshopTemp); await _institutionAmendmentTemp.ReplaceOneAsync(x => x.Id == amendmentTemp.Id, amendmentTemp); } public async Task> GetInstitutionContractSelectList(string search, string selected) { var contractingParties = _context.PersonalContractingParties.Select(x => new InstitutionContractSelectListViewModel() { Id = x.id, Text = x.IsLegal == "حقیقی" ? x.SureName == null ? x.FName + " " + x.LName : x.FName + " " + x.LName + " " + x.SureName : x.SureName == null ? x.LName : x.LName + " " + x.SureName }); var workshops = _context.Workshops.Select(x => new InstitutionContractSelectListViewModel() { Id = x.id, Text = x.WorkshopFullName }); //کارفرما ها به غیر از آن هایی که به طرف حساب ---- وصل هستند var employers = _context.Employers.Where(x => x.ContractingPartyId != 30428) .Select(x => new InstitutionContractSelectListViewModel() { Id = x.id, Text = x.FullName }); var representatives = _context.RepresentativeSet.Select(x => new InstitutionContractSelectListViewModel() { Id = x.id, Text = x.FName + " " + x.LName }); var res = contractingParties .Union(workshops) .Union(employers) .Union(representatives); InstitutionContractSelectListViewModel idSelected = null; if (!string.IsNullOrWhiteSpace(selected)) { idSelected = await res.FirstOrDefaultAsync(x => x.Text == selected); } if (!string.IsNullOrWhiteSpace(search)) { res = res.Where(x => x.Text.Contains(search)); } var list = await res.Take(100).ToListAsync(); if (idSelected != null) list.Add(idSelected); return list.DistinctBy(x => x.Id).ToList(); } public async Task> PrintAllAsync(List ids) { var query = _context.InstitutionContractSet .Include(x => x.WorkshopGroup) .ThenInclude(x => x.InitialWorkshops) .Include(x => x.WorkshopGroup) .ThenInclude(x => x.CurrentWorkshops) .Where(x => ids.Contains(x.id)); var contractingPartyIds = query.Select(x => x.ContractingPartyId).ToList(); var contractingParties = await _context.PersonalContractingParties .Where(x => contractingPartyIds.Contains(x.id)) .ToListAsync(); var list = query.ToList(); if (list.Count == 0) throw new NotFoundException("قرارداد مؤسسه یافت نشد"); var res = new List(); foreach (var institution in list) { var contractingParty = contractingParties.FirstOrDefault(x => x.id == institution.ContractingPartyId); if (contractingParty == null) { throw new NotFoundException("طرف حساب یافت نشد"); } var law = await _context.Laws .FirstOrDefaultAsync(x => x.id == institution.LawId); var secondParty = new InstitutionContratVerificationParty() { Address = contractingParty.Address, PhoneNumber = contractingParty.Phone, CeoName = contractingParty.IsLegal == "حقیقی" ? $"{contractingParty.FName} {contractingParty.LName}" : $"{contractingParty.CeoFName} {contractingParty.CeoLName}", CompanyNameOrFullName = contractingParty.IsLegal == "حقیقی" ? $"{contractingParty.FName} {contractingParty.LName}" : contractingParty.LName, NationalCodeOrNationalId = contractingParty.IsLegal == "حقیقی" ? contractingParty.Nationalcode : contractingParty.NationalId, LegalType = contractingParty.IsLegal == "حقیقی" ? LegalType.Real : LegalType.Legal, }; var lawViewModel = new LawViewModel() { Id = law.id, CreatedAt = law.CreationDate, HeadTitle = law.HeadTitle, IsActive = law.IsActive, Items = law.Items.Select(x => new LawItemViewModel() { Details = x.Details, Header = x.Header }).ToList(), Notifications = law.Notifications, Title = law.Title, Type = law.Type, Version = law.Version }; var item = new InstitutionContractPrintViewModel() { ContractStart = institution.ContractStartFa, ContractEnd = institution.ContractEndFa, ContractNo = institution.ContractNo, CreationDate = institution.CreationDate.ToFarsi(), FirstParty = _firstParty, SecondParty = secondParty, LawViewModel = lawViewModel, Obligation = institution.Obligation.ToMoney(), PaymentPrice = institution.TotalAmount.ToMoney(), TotalPrice = (institution.TotalAmount - institution.ValueAddedTax).ToMoney(), TaxPrice = institution.ValueAddedTax.ToMoney(), OneMonthPrice = institution.ContractAmountWithTax.ToMoney(), OneMonthWithoutTax = institution.ContractAmount.ToMoney(), OneMonthTax = institution.ContractAmountTax.ToMoney(), VerifierFullName = institution.VerifierFullName, VerifierPhoneNumber = institution.VerifierPhoneNumber, VerifyCode = institution.VerifyCode, VerifyDate = institution.VerifyCodeCreation.ToFarsi(), VerifyTime = institution.VerifyCodeCreation.ToString("HH:mm:ss"), Workshops = institution.WorkshopGroup.CurrentWorkshops .Select(x => new GetInstitutionVerificationDetailsWorkshopsViewModel() { Name = x.WorkshopName, PersonnelCount = x.PersonnelCount, Services = new WorkshopServicesViewModel() { Contract = x.Services.Contract, ContractInPerson = x.Services.ContractInPerson, CustomizeCheckout = x.Services.CustomizeCheckout, Insurance = x.Services.Insurance, InsuranceInPerson = x.Services.InsuranceInPerson, RollCall = x.Services.RollCall, RollCallInPerson = x.Services.RollCallInPerson }, Price = x.Price.ToMoney() }).ToList() }; res.Add(item); } return res; } private InstitutionContractExtensionPaymentResponse CalculateInPersonPayment( InstitutionContractExtensionPlanDetail selectedPlan, double baseAmount, double tenPercent, InstitutionContractDuration duration) { // حالت پرداخت یکجا var oneTimeBase = baseAmount - tenPercent; var oneTimeTax = oneTimeBase * 0.10; var oneTimeTotal = oneTimeBase + oneTimeTax; var res = new InstitutionContractExtensionPaymentResponse { OneTime = new() { TotalAmount = oneTimeBase.ToMoney(), Tax = oneTimeTax.ToMoney(), PaymentAmount = oneTimeTotal.ToMoney() } }; // حالت پرداخت اقساطی var monthlyTax = baseAmount * 0.10; var monthlyTotal = baseAmount + monthlyTax; var installments = InstitutionMonthlyInstallmentCaculation((int)duration, monthlyTotal, selectedPlan.ContractStart); res.Monthly = new() { TotalAmount = baseAmount.ToMoney(), Tax = monthlyTax.ToMoney(), PaymentAmount = monthlyTotal.ToMoney(), Installments = installments }; return res; } private InstitutionContractExtensionPaymentResponse CalculateOnlinePayment(double baseAmount, double tenPercent) { var tax = tenPercent; var total = baseAmount + tax; return new InstitutionContractExtensionPaymentResponse { OneTime = new() { TotalAmount = baseAmount.ToMoney(), Tax = tax.ToMoney(), PaymentAmount = total.ToMoney() } }; } private InstitutionContractExtensionPlanDetail CalculateInstitutionPlan(InstitutionContractDuration duration, double amount, bool hasInPersonContract, DateTime contractStart) { var result = new InstitutionContractExtensionPlanDetail(); var months = (int)duration; //بدست آوردن جمع کل مبالغ کارگاه بر اساس مدت قراداد var totalPrice = months * amount; var contractStartFa = contractStart.ToFarsi(); var findeEnd = Tools.FindEndOfContract(contractStartFa, ((int)duration).ToString()); var contractEndDate = findeEnd.endDateGr; result.ContractEnd = contractEndDate.ToFarsi(); result.ContractStart = contractStartFa; result.Obligation = totalPrice.ToMoney(); result.DailyCompenseation = ((amount * 10) / 100).ToMoney(); if (hasInPersonContract) { result.OneMonthDiscount = "0"; result.OneMonthOriginalPayment = amount.ToMoney(); result.OneMonthPaymentDiscounted = amount.ToMoney(); result.TotalPayment = totalPrice.ToMoney(); } else { var discount = duration switch { InstitutionContractDuration.OneMonth => 0, InstitutionContractDuration.ThreeMonths => 5, InstitutionContractDuration.SixMonths => 10, InstitutionContractDuration.TwelveMonths => 15, _ => throw new ArgumentOutOfRangeException(nameof(duration), duration, null) }; var oneMonthDiscountAmount = (amount * discount) / 100; var oneMonthDiscountedPayment = amount - oneMonthDiscountAmount; var totalDiscount = oneMonthDiscountAmount * months; var discountedPayment = totalPrice - totalDiscount; result.OneMonthDiscount = oneMonthDiscountAmount.ToMoney(); result.OneMonthPaymentDiscounted = oneMonthDiscountedPayment.ToMoney(); result.OneMonthOriginalPayment = totalPrice.ToMoney(); result.TotalPayment = discountedPayment.ToMoney(); } return result; } public static List InstitutionMonthlyInstallmentCaculation(int duration, double monthlyTotalPaymentDouble, string installmentstart) { var originalDay = int.Parse(installmentstart.Substring(8, 2)); var installmentList = new List(); int instalmentCount = duration; var instalmentAmount = monthlyTotalPaymentDouble / instalmentCount; int currentInstallmentStartDay = int.Parse(installmentstart.Substring(8, 2)); bool endOfMonth = currentInstallmentStartDay == 31; // Loop through each installment period for (int i = 1; i <= instalmentCount; i++) { string installmentDate; // For first installment, use the initial date if (i == 1) { installmentDate = installmentstart; } else { var currentDay = int.Parse(installmentstart.Substring(8, 2)); var currentMonth = int.Parse(installmentstart.Substring(5, 2)); var currentYear = int.Parse(installmentstart.Substring(0, 4)); // Get next month's date var nextMonthFa = installmentstart.ToGeorgianDateTime().AddMonthsFa(1, out var nextMonth); var maxDayInNextMonth = int.Parse(nextMonthFa.FindeEndOfMonth().Substring(8, 2)); // Use original day if possible, otherwise use last day of month var dayToUse = Math.Min(originalDay, maxDayInNextMonth); installmentDate = nextMonthFa.Substring(0, 8) + dayToUse.ToString("D2"); // Update installmentstart for next iteration installmentstart = installmentDate; } installmentList.Add(new MonthlyInstallment() { InstallmentAmountStr = instalmentAmount.ToMoney(), InstallmentCounter = i switch { 1 => "اول", 2 => "دوم", 3 => "سوم", 4 => "چهارم", 5 => "پنجم", 6 => "ششم", 7 => "هفتم", 8 => "هشتم", 9 => "نهم", 10 => "دهم", 11 => "یازدهم", 12 => "دوازدهم", _ => "دوازدهم", }, InstalmentDate = installmentDate }); } return installmentList; } #endregion #region DebtReminderSms /// /// دریافت لیست - ارسال پیامک /// فراخوانی از سمت بک گراند سرویس /// /// public async Task SendReminderSmsForBackgroundTask() { var now = DateTime.Now; // تبدیل تاریخ میلادی به شمسی var persianNow = now.ToFarsi(); var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2)); var dayOfMonth = int.Parse(persianNow.Substring(8, 2)); var hour = now.Hour; var minute = now.Minute; var checkAnyToExecute = false; //اگر آخرین روز ماه باشد //اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود if (dayOfMonth == persianEndOfMonth) { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth >= dayOfMonth && x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractDebtReminder && x.IsActive ); } else { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth == dayOfMonth && x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractDebtReminder && x.IsActive ); } if (checkAnyToExecute) { //اجرای تسک _logger.LogInformation("اجرای تسک پیامک های یاد آور SendReminderSmsForBackgroundTask" + persianNow + " - " + hour + ":" + minute); //دریافت لیست بدهکاران var smsListData = await GetSmsListData(now, TypeOfSmsSetting.InstitutionContractDebtReminder); string typeOfSms = "یادآور بدهی ماهانه"; string sendMessStart = "شروع پیامک یادآور"; string sendMessEnd = "پایان پیامک یادآور"; //ارسال پیامک await SendReminderSmsToContractingParties(smsListData, typeOfSms, sendMessStart, sendMessEnd); Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute); return true; } return false; } #region MonthlySms /// /// ارسال پیامک صورت حساب ماهانه /// /// /// public async Task SendMonthlySms(DateTime now) { //دریافت لیست بدهکاران var smsListData = await GetSmsListData(now, TypeOfSmsSetting.MonthlyInstitutionContract); string typeOfSms = "صورت حساب ماهانه"; string sendMessStart = "شروع پیامک ماهانه"; string sendMessEnd = "پایان پیامک ماهانه"; //ارسال پیامک await SendReminderSmsToContractingParties(smsListData, typeOfSms, sendMessStart, sendMessEnd); } #endregion #region BlockSms /// /// پیامک بلاک /// /// public async Task SendBlockSmsForBackgroundTask() { var now = DateTime.Now; // تبدیل تاریخ میلادی به شمسی var persianNow = now.ToFarsi(); var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2)); var dayOfMonth = int.Parse(persianNow.Substring(8, 2)); var hour = now.Hour; var minute = now.Minute; var checkAnyToExecute = false; //اگر آخرین روز ماه باشد //اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود if (dayOfMonth == persianEndOfMonth) { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth >= dayOfMonth && x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.BlockContractingParty && x.IsActive ); } else { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth == dayOfMonth && x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.BlockContractingParty && x.IsActive ); } if (checkAnyToExecute) { //اجرای تسک //دریافت لیست بدهکاران var smsListData = await GetBlockListData(now); string typeOfSms = "اعلام مسدودی طرف حساب"; string sendMessStart = "شروع پیامک مسدودی"; string sendMessEnd = "پایان پیامک مسدودی"; //ارسال پیامک await SendBlockSmsToContractingParties(smsListData, typeOfSms, sendMessStart, sendMessEnd); Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute); } } public async Task> GetBlockListData(DateTime checkDate) { var smsList = new List(); var institutionContracts = await _context.InstitutionContractSet.Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, ContractAmountDouble = x.ContractAmount, OfficialCompany = x.OfficialCompany }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) .ToListAsync(); var contractingPartyList = await _context.PersonalContractingParties .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); var financialStatmentList = await _context.FinancialStatments.AsSplitQuery() .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.ContractingPartyId)) .Include(x => x.FinancialTransactionList).Where(x => x.FinancialTransactionList.Count > 0).ToListAsync(); var phoneNumberList = await _context.InstitutionContractContactInfos .Where(x => institutionContracts.Select(ins => ins.Id).Contains(x.InstitutionContractId)) .Where(x => x.SendSms && x.PhoneType == "شماره همراه" && !string.IsNullOrWhiteSpace(x.PhoneNumber) && x.PhoneNumber.Length == 11).ToListAsync(); foreach (var item in institutionContracts) { try { var contractingParty = contractingPartyList.FirstOrDefault(x => x.id == item.ContractingPartyId); if (contractingParty != null && contractingParty.IsBlock == "true") { var partyName = contractingParty.IsLegal == "حقیقی" ? $"{contractingParty.FName} {contractingParty.LName}" : $"{contractingParty.LName}"; if (!string.IsNullOrWhiteSpace(contractingParty.SureName)) partyName = $"{partyName} ({contractingParty.SureName})"; if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; var isLegal = contractingParty.IsLegal == "حقوقی" ? true : false; var hasFinancialStatment = financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId & x.FinancialTransactionList.Count > 0); var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); if (hasFinancialStatment && hasPhonNumber) { var transactions = financialStatmentList.FirstOrDefault(x => x.ContractingPartyId == item.ContractingPartyId); var debtor = transactions.FinancialTransactionList.Sum(x => x.Deptor); var creditor = transactions.FinancialTransactionList.Sum(x => x.Creditor); var id = $"{item.ContractingPartyId}"; var aprove = $"{transactions.id}"; var balance = debtor - creditor; if (balance > 0) { var jobRelation = "بابت قرارداد مابین (روابط کار)"; var taxAndFinancial = "بابت قرارداد مابین (حسابداری و مالیات)"; var jobRelationContract = transactions.FinancialTransactionList .OrderByDescending(x => x.TdateGr).FirstOrDefault(x => x.TypeOfTransaction == "debt" && x.DescriptionOption == jobRelation); var taxAndFinancialContract = transactions.FinancialTransactionList .OrderByDescending(x => x.TdateGr).FirstOrDefault(x => x.TypeOfTransaction == "debt" && x.DescriptionOption == taxAndFinancial); var jobRelationContractAmounts = jobRelationContract != null ? jobRelationContract.Deptor : 0; var taxAndFinancialContractAmounts = taxAndFinancialContract != null ? taxAndFinancialContract.Deptor : 0; var sumOfAmounts = jobRelationContractAmounts * 2 + taxAndFinancialContractAmounts * 2; if (balance >= sumOfAmounts) { var phoneNumbers = new List(); phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) .Select(x => new CreateContactInfo { PhoneType = x.PhoneType, PhoneNumber = x.PhoneNumber, InstitutionContractId = x.InstitutionContractId, SendSms = x.SendSms }).Where(x => x.PhoneNumber.Length == 11).ToList(); var accountType = item.OfficialCompany == "Official" ? "ol" : "nol"; var balanceToMoney = balance.ToMoney(); var amount = balanceToMoney + " " + "ریال" + " "; foreach (var number in phoneNumbers) { smsList.Add(new BlockSmsListData() { PhoneNumber = number.PhoneNumber, PartyName = partyName, AccountType = accountType, Amount = amount, ContractingPartyId = contractingParty.id, InstitutionContractId = item.Id, AproveId = aprove }); } } } } } } catch (Exception e) { string name = item.ContractingPartyName.Length > 18 ? item.ContractingPartyName.Substring(0, 18) : item.ContractingPartyName; string errMess = $"{name}-خطا"; await _smsService.Alarm("09114221321", errMess); } } return smsList; } #endregion /// ///دریافت لیست بدهکارن /// جهت ارسال پیامک /// /// public async Task> GetSmsListData(DateTime checkDate, TypeOfSmsSetting typeOfSmsSetting) { var watch = new Stopwatch(); var smsList = new List(); var currentMonthStart = ($"{(checkDate.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); var previusMonthEnd = currentMonthStart.AddDays(-1); var previusMonthStart = ($"{(previusMonthEnd.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); watch.Start(); //دریافت اطلاعات بدهکارن و ساخت لیست پیامک #region GetSmsListData //var rollcallServiceList = _context.RollCallServices.Where(x => x.StartService.Date <= previusMonthStart.Date && x.EndService.Date >= previusMonthEnd.Date).ToList(); var institutionContracts = await _context.InstitutionContractSet.AsSplitQuery().Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, ContractAmountDouble = x.ContractAmount, OfficialCompany = x.OfficialCompany }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) .ToListAsync(); var contractingPartyList = await _context.PersonalContractingParties .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); var financialStatmentList = await _context.FinancialStatments.AsSplitQuery() .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.ContractingPartyId)) .Include(x => x.FinancialTransactionList).Where(x => x.FinancialTransactionList.Count > 0).ToListAsync(); var phoneNumberList = await _context.InstitutionContractContactInfos .Where(x => institutionContracts.Select(ins => ins.Id).Contains(x.InstitutionContractId)) .Where(x => x.SendSms && x.PhoneType == "شماره همراه" && !string.IsNullOrWhiteSpace(x.PhoneNumber) && x.PhoneNumber.Length == 11).ToListAsync(); Console.WriteLine("database query: " + watch.Elapsed); watch.Stop(); watch.Start(); foreach (var item in institutionContracts) { try { var contractingParty = contractingPartyList.FirstOrDefault(x => x.id == item.ContractingPartyId); //var isSend = sendedSms.Any(x => x.ContractingPatyId == contractingParty.Id); if (!string.IsNullOrWhiteSpace(contractingParty.LName)) { //Thread.Sleep(500); var partyName = contractingParty.IsLegal == "حقیقی" ? $"{contractingParty.FName} {contractingParty.LName}" : $"{contractingParty.LName}"; if (!string.IsNullOrWhiteSpace(contractingParty.SureName)) partyName = $"{partyName} ({contractingParty.SureName})"; if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; var isLegal = contractingParty.IsLegal == "حقوقی" ? true : false; var isBlock = contractingParty.IsBlock == "true" ? true : false; var isActive = contractingParty.IsActiveString == "true" ? true : false; if (!string.IsNullOrWhiteSpace(contractingParty.IsActiveString) && isActive) { var hasFinancialStatement = financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId); var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); if (hasFinancialStatement && hasPhonNumber) { var phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) .Select(x => new CreateContactInfo { PhoneType = x.PhoneType, PhoneNumber = x.PhoneNumber, InstitutionContractId = x.InstitutionContractId, SendSms = x.SendSms }).Where(x => x.PhoneNumber.Length == 11).ToList(); var transactions = financialStatmentList.FirstOrDefault(x => x.ContractingPartyId == item.ContractingPartyId); var debtor = transactions.FinancialTransactionList.Sum(x => x.Deptor); var creditor = transactions.FinancialTransactionList.Sum(x => x.Creditor); var id = $"{item.ContractingPartyId}"; var aprove = $"{transactions.id}"; var balance = debtor - creditor; if (balance > 0) // اگر بدهکار بود { //var employers = _context.Employers.Where(x => x.ContractingPartyId == item.ContractingPartyId) // .Select(x => x.id); //var workshops = _context.WorkshopEmployers.Where(x => employers.Contains(x.EmployerId)) // .Select(x => x.WorkshopId).Distinct().ToList(); //var services = // rollcallServiceList.Where(x => workshops.Contains(x.WorkshopId)).ToList(); //var hasRollCallService = services.Count > 0; //موقت var hasRollCallService = false; //if (hasRollCallService) //{ // var employees = // _context.RollCallEmployees.Where(x => workshops.Contains(x.WorkshopId)) // .Select(x => x.id); // var employeeCount = _context.RollCallEmployeesStatus // .Where(x => employees.Contains(x.RollCallEmployeeId)) // .Count(x => x.EndDate.Date == activeStatusDate.Date); // if (employeeCount == 0) // hasRollCallService = false; //} if (isLegal) { if (item.OfficialCompany == "Official") // حقوقی بدهکار رسمی { var balanceToMoney = balance.ToMoney(); foreach (var number in phoneNumbers) { if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && number.PhoneNumber.Length == 11) { int messageId = 0; string message = ""; bool isSuccessSend = false; if (hasRollCallService) { string publicId = transactions.PublicIdStr; string code1 = publicId.Substring(0, 25); string code2 = publicId.Substring(25); var templateId = 789638; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 983035; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1, Code2 = code2, InstitutionContractId = item.Id }); } else { var templateId = 161233; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 394006; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "", InstitutionContractId = item.Id }); } } } } else if (item.OfficialCompany == "NotOfficial") // حقوقی بدهکار غیر رسمی { var balanceToMoney = balance.ToMoney(); foreach (var number in phoneNumbers) { if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && number.PhoneNumber.Length == 11) { int messageId = 0; string message = ""; bool isSuccessSend = false; if (hasRollCallService) { string publicId = transactions.PublicIdStr; string code1 = publicId.Substring(0, 25); string code2 = publicId.Substring(25); var templateId = 789638; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 983035; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1, Code2 = code2, InstitutionContractId = item.Id }); } else { var templateId = 347415; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 679068; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "", InstitutionContractId = item.Id }); } } } } } else { if (item.OfficialCompany == "Official") // حقیقی بدهکار رسمی { var balanceToMoney = balance.ToMoney(); foreach (var number in phoneNumbers) { if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && number.PhoneNumber.Length == 11) { int messageId = 0; string message = ""; bool isSuccessSend = false; if (hasRollCallService) { string publicId = transactions.PublicIdStr; string code1 = publicId.Substring(0, 25); string code2 = publicId.Substring(25); var templateId = 768277; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 479624; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1, Code2 = code2, InstitutionContractId = item.Id }); } else { var templateId = 998180; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 646040; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "", InstitutionContractId = item.Id }); } } } } else if (item.OfficialCompany == "NotOfficial") // حقیقی بدهکار غیر رسمی { var balanceToMoney = balance.ToMoney(); foreach (var number in phoneNumbers) { if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && number.PhoneNumber.Length == 11) { int messageId = 0; string message = ""; bool isSuccessSend = false; if (hasRollCallService) { var templateId = 768277; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 479624; } string publicId = transactions.PublicIdStr; string code1 = publicId.Substring(0, 25); string code2 = publicId.Substring(25); smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1, Code2 = code2, InstitutionContractId = item.Id }); } else { var templateId = 810539; if (typeOfSmsSetting == TypeOfSmsSetting.MonthlyInstitutionContract) { templateId = 566537; } smsList.Add(new SmsListData() { PhoneNumber = number.PhoneNumber, TemplateId = templateId, PartyName = partyName, Amount = balanceToMoney, ContractingPartyId = contractingParty.id, AproveId = aprove, TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "", InstitutionContractId = item.Id }); } } } } } } phoneNumbers = new List(); } } } } catch (Exception e) { string name = item.ContractingPartyName.Length > 18 ? item.ContractingPartyName.Substring(0, 18) : item.ContractingPartyName; string errMess = $"{name}-خطا"; // _smsService.Alarm("09114221321", errMess); } } #endregion Console.WriteLine("SmsListData: " + watch.Elapsed); return smsList; } public async Task SendBlockSmsToContractingParties(List smsListData, string typeOfSms, string sendMessStart, string sendMessEnd) { if (smsListData.Any()) { await _smsService.Alarm("09114221321", sendMessStart); Thread.Sleep(1000); await _smsService.Alarm("09111485044", sendMessStart); Thread.Sleep(1000); int successProcess = 1; int countList = smsListData.Count; foreach (var item in smsListData) { try { var smsResult = await _smsService.BlockMessage(item.PhoneNumber, item.PartyName, item.Amount, item.AccountType, $"{item.ContractingPartyId}", item.AproveId); Thread.Sleep(1000); var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(smsResult.messaeId, smsResult.message, typeOfSms, item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); await _smsResultRepository.CreateAsync(createSmsResult); await _smsResultRepository.SaveChangesAsync(); } catch (Exception e) { string name = item.PartyName.Length > 18 ? item.PartyName.Substring(0, 18) : item.PartyName; string errMess = $"{name}-خطا"; await _smsService.Alarm("09114221321", errMess); } Thread.Sleep(600); var percent = (successProcess / (double)countList) * 100; await _hubContext.Clients.Group(SendSmsHub.GetGroupName(10)) .SendAsync("showStatus", (int)percent); successProcess += 1; } await _smsService.Alarm("09114221321", sendMessEnd); Thread.Sleep(1000); await _smsService.Alarm("09111485044", sendMessEnd); } } /// /// ارسال پیامک های یاد آور بدهی /// /// public async Task SendReminderSmsToContractingParties(List smsListData, string typeOfSms, string sendMessStart, string sendMessEnd) { //ارسال پیامک با اساس لیست #region SendSMSFromList if (smsListData.Any()) { //await _smsService.Alarm("09114221321", sendMessStart); //Thread.Sleep(1000); //await _smsService.Alarm("09111485044", sendMessStart); //Thread.Sleep(1000); int successProcess = 1; int countList = smsListData.Count; foreach (var item in smsListData) { try { if (item.TypeOfSmsMethod == "MonthlyBill") { var res = await _smsService.MonthlyBill(item.PhoneNumber, item.TemplateId, item.PartyName, item.Amount, $"{item.ContractingPartyId}", item.AproveId); if (res.isSucceded) { var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(res.messaeId, res.message, typeOfSms, item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); await _smsResultRepository.CreateAsync(createSmsResult); await _smsResultRepository.SaveChangesAsync(); } } else { var res = await _smsService.MonthlyBillNew(item.PhoneNumber, item.TemplateId, item.PartyName, item.Amount, item.Code1, item.Code2); if (res.isSucceded) { var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(res.messaeId, res.message, typeOfSms, item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); await _smsResultRepository.CreateAsync(createSmsResult); await _smsResultRepository.SaveChangesAsync(); } } Thread.Sleep(600); } catch (Exception e) { string name = item.PartyName.Length > 18 ? item.PartyName.Substring(0, 18) : item.PartyName; string errMess = $"{name}-خطا"; _logger.LogError(errMess); await _smsService.Alarm("09114221321", errMess); } var percent = (successProcess / (double)countList) * 100; await _hubContext.Clients.Group(SendSmsHub.GetGroupName(7)) .SendAsync("showStatus", (int)percent); successProcess += 1; } //await _smsService.Alarm("09114221321", sendMessEnd); //Thread.Sleep(1000); //await _smsService.Alarm("09111485044", sendMessEnd); } #endregion } #region PrivateMetods /// /// دریافت صورت حساب مالی با آی دی طرف حساب /// /// /// private async Task GetFinancialByContractingPartyId(long contractingPartyId) { return await _context.FinancialStatments.Include(x => x.FinancialTransactionList) .Select(x => new FinancialStatmentViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, PublicId = x.PublicIdStr, FinancialTransactionViewModels = x.FinancialTransactionList.Select(t => new FinancialTransactionViewModel { Id = t.id, TdateFa = t.TdateFa, TdateGr = t.TdateGr, Description = t.TypeOfTransaction == "debt" ? "ایجاد درآمد" + " " + t.DescriptionOption + " " + t.Description : "دریافت درآمد" + " " + t.DescriptionOption + " " + t.Description, Deptor = t.Deptor, DeptorString = t.Deptor != 0 ? t.Deptor.ToMoney() : "", Creditor = t.Creditor, CreditorString = t.Creditor != 0 ? t.Creditor.ToMoney() : "", Balance = t.Balance, MessageText = t.MessageText, SentSms = t.SentSms, SentSmsDateFa = t.SentSmsDateFa, FinancialStatementId = t.FinancialStatementId, TypeOfTransaction = t.TypeOfTransaction, DescriptionOption = t.DescriptionOption }).OrderBy(t => t.TdateGr).ToList() }) .FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId); } #endregion #region InstitutionContractConfirm /// /// ارسال پیامک یادآور تایید قراداد مالی /// /// public async Task SendInstitutionContractConfirmSmsTask() { var now = DateTime.Now; // تبدیل تاریخ میلادی به شمسی var persianNow = now.ToFarsi(); var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2)); var dayOfMonth = int.Parse(persianNow.Substring(8, 2)); var hour = now.Hour; var minute = now.Minute; var checkAnyToExecute = false; //اگر آخرین روز ماه باشد //اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود if (dayOfMonth == persianEndOfMonth) { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth >= dayOfMonth && /// اگر بزرگتر یا مساوی رو جاری بود x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm && x.IsActive ); } else { checkAnyToExecute = await _context.SmsSettings .AnyAsync(x => x.DayOfMonth == dayOfMonth && x.TimeOfDay.Hours == hour && x.TimeOfDay.Minutes == minute && x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm && x.IsActive ); } if (checkAnyToExecute) { //اجرای تسک _logger.LogInformation("اجرای تسک ارسال یاد آور تایید قراداد مالی SendInstitutionContractConfirmSms" + persianNow + " - " + hour + ":" + minute); //دریافت لیست قراداد های تایید نشده var fromAmonthAgo = now.AddDays(-30); var pendingContracts = await _context.InstitutionContractSet .Where(x => x.CreationDate >= fromAmonthAgo && x.CreationDate.Date != now.Date && x.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify) .Join(_context.PersonalContractingParties, contract => contract.ContractingPartyId, contractingParty => contractingParty.id, (contract, contractingParty) => new { contract, contractingParty }).Select(x => new InstitutionCreationVerificationSmsDto { Number = x.contractingParty.Phone, FullName = x.contractingParty.IsLegal == "حقیقی" ? $"{x.contractingParty.FName} {x.contractingParty.LName}" : $"{x.contractingParty.LName}", ContractingPartyId = x.contract.ContractingPartyId, InstitutionContractId = x.contract.id, InstitutionId = x.contract.PublicId, }).ToListAsync(); string typeOfSms = "یادآور تایید قرارداد مالی"; foreach (var item in pendingContracts) { var sendResult = await _smsService.SendInstitutionCreationVerificationLink(item.Number, item.FullName, item.InstitutionId, item.ContractingPartyId, item.InstitutionContractId, typeOfSms); Thread.Sleep(1000); } Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute); } } #endregion #endregion #region CreateMontlyTransaction /// /// ایجاد سند مالی برای قرارداد ها /// /// public async Task CreateTransactionForInstitutionContracts(DateTime endOfMonthGr, string endOfMonthFa, string description) { #region FindeNextMonth 1th var firstDayOfMonthGr = ($"{endOfMonthFa.Substring(0, 8)}01").ToGeorgianDateTime(); var nextMonthGr = endOfMonthGr.AddDays(1); var endOfCurrentMonth = (($"{endOfMonthFa.Substring(0, 8)}/01").FindeEndOfMonth()).ToGeorgianDateTime(); #endregion #region GetAvtiveContracts var institutionContracts = await _context.InstitutionContractSet.Where(x => x.IsActiveString == "true") .Include(x => x.Installments) .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, ContractAmountDouble = x.ContractAmount, TypeOfContract = x.TypeOfContract, IsInstallment = x.IsInstallment, VerificationStatus = x.VerificationStatus, SigningType = x.SigningType, InstallmentList = x.Installments .Select(ins => new InstitutionContractInstallmentViewModel { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).Where(x => x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.ContractAmountDouble > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify) .ToListAsync(); #endregion #region GetFutureContracts List futureContracts = await _context.InstitutionContractSet .Where(x => x.IsActiveString == "true" && x.ContractStartGr.Date == nextMonthGr.Date && x.ContractAmount > 0) .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, }).ToListAsync(); #region GetDectivedContractOnCurrentMonth if (futureContracts.Any()) { List futureContractIds = futureContracts.Select(x => x.ContractingPartyId).ToList(); List deatcivedContract = await _context.InstitutionContractSet .Where(x => x.IsActiveString == "false" && futureContractIds.Contains(x.ContractingPartyId) && x.ContractEndGr.Date == endOfCurrentMonth.Date && x.ContractAmount > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify) .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, ContractingPartyName = x.ContractingPartyName, ContractStartGr = x.ContractStartGr, ContractStartFa = x.ContractStartFa, ContractEndGr = x.ContractEndGr, ContractEndFa = x.ContractEndFa, IsActiveString = x.IsActiveString, ContractAmountDouble = x.ContractAmount, TypeOfContract = x.TypeOfContract, IsInstallment = x.IsInstallment, VerificationStatus = x.VerificationStatus, SigningType = x.SigningType, InstallmentList = x.Installments .Select(ins => new InstitutionContractInstallmentViewModel { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).ToListAsync(); if (deatcivedContract.Any()) institutionContracts.AddRange(deatcivedContract); } // قرارداد هایی که پطور یکجا پرداخت شده اند var paidInFull = institutionContracts.Where(x => x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه institutionContracts = institutionContracts.Except(paidInFull).ToList(); #region RollCallServicCompute var rollcallServiceList = await _context.RollCallServices.Where(x => x.IsActiveString == "true").ToListAsync(); var activeStatusDate = new DateTime(2121, 03, 21); #endregion int count = 0; int serviceCounter = 0; foreach (var item in institutionContracts) { var jobRelation = "بابت قرارداد مابین (روابط کار)"; var taxAndFinancial = "بابت قرارداد مابین (حسابداری و مالیات)"; var contractingParty = await _context.PersonalContractingParties.FirstOrDefaultAsync(x => x.id == item.ContractingPartyId); string partyName = item.ContractingPartyName; if (partyName.Length > 18) partyName = $"{partyName.Substring(0, 18)}"; var isblock = contractingParty.IsBlock == "true" ? true : false; if (contractingParty != null && contractingParty.IsActiveString == "true" && endOfMonthGr <= item.ContractEndGr) { try { var hasFinancialStatment = await _context.FinancialStatments.AnyAsync(x => x.ContractingPartyId == item.ContractingPartyId); var computeOption = item.TypeOfContract == "JobRelation" ? jobRelation : taxAndFinancial; if (hasFinancialStatment) { var financialStatmentData = await _context.FinancialStatments.FirstOrDefaultAsync(x => x.ContractingPartyId == item.ContractingPartyId); var financialStatmentId = financialStatmentData.id; var alreadyCreated = await _context.FinancialTransactions.AnyAsync(x => x.DescriptionOption == computeOption && x.TypeOfTransaction == "debt" && x.TdateGr.Date == endOfMonthGr.Date && x.FinancialStatementId == financialStatmentId); if (!alreadyCreated) { if (item.IsInstallment) { var instalment = item.InstallmentList .FirstOrDefault(x => x.InstallmentDateGr >= firstDayOfMonthGr && x.InstallmentDateGr <= endOfMonthGr); if (instalment != null) { var transaction = new FinancialTransaction(financialStatmentId, endOfMonthGr, endOfMonthFa, description, "debt", computeOption, instalment.AmountDouble, 0, 0, isblock); await _financialTransactionRepository.CreateAsync(transaction); await _financialTransactionRepository.SaveChangesAsync(); } } else { var transaction = new FinancialTransaction(financialStatmentId, endOfMonthGr, endOfMonthFa, description, "debt", computeOption, item.ContractAmountDouble, 0, 0, isblock); await _financialTransactionRepository.CreateAsync(transaction); await _financialTransactionRepository.SaveChangesAsync(); } } } else { var statement = new FinancialStatment(item.ContractingPartyId, item.ContractingPartyName); await _financialStatmentRepository.CreateAsync(statement); await _financialStatmentRepository.SaveChangesAsync(); if (item.IsInstallment) { var instalment = item.InstallmentList .FirstOrDefault(x => x.InstallmentDateGr >= firstDayOfMonthGr && x.InstallmentDateGr <= endOfMonthGr); if (instalment != null) { var transaction = new FinancialTransaction(statement.id, endOfMonthGr, endOfMonthFa, description, "debt", computeOption, instalment.AmountDouble, 0, 0, isblock); await _financialTransactionRepository.CreateAsync(transaction); await _financialTransactionRepository.SaveChangesAsync(); } } else { var transaction = new FinancialTransaction(statement.id, endOfMonthGr, endOfMonthFa, description, "debt", computeOption, item.ContractAmountDouble, 0, 0, isblock); await _financialTransactionRepository.CreateAsync(transaction); await _financialTransactionRepository.SaveChangesAsync(); } } #region RollCallServicCompute //ایجاد سند مالی حضورغیاب //قرارداد هایی که جدید نیستند و اقساط ندارند //کارگاه های استثناء : کباب مهدی 30520 و نمونه پروتئین 30739 if (item.SigningType != InstitutionContractSigningType.OtpBased && item.SigningType != InstitutionContractSigningType.Physical && !item.IsInstallment && item.ContractingPartyId != 30520 && item.ContractingPartyId != 30739) { try { //TODO //@refactor Need var employers = await _context.Employers .Where(x => x.ContractingPartyId == item.ContractingPartyId) .Select(x => x.id).ToListAsync(); var workshops = await _context.WorkshopEmployers .Where(x => employers.Contains(x.EmployerId)) .Select(x => x.WorkshopId).Distinct().ToListAsync(); var services = rollcallServiceList.Where(x => workshops.Contains(x.WorkshopId)).ToList(); if (services.Any()) { foreach (var rollCallService in services) { //var spaning = (int)(endOfMonthGr - rollCallService.StartService).TotalDays + 1; int monthCounter = 0; //var currentMonthStart = ($"{(endOfMonthGr.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); //var prevMonthEnd = currentMonthStart.AddDays(-1); //var prevMonthStart = ($"{(prevMonthEnd.ToFarsi()).Substring(0, 8)}01").ToGeorgianDateTime(); var monthCurrent = endOfMonthFa.Substring(5, 2); var yearCurrent = endOfMonthFa.Substring(0, 4); var currentMonthName = monthCurrent.ToFarsiMonthByNumber(); var workshop = await _context.Workshops.FirstOrDefaultAsync(x => x.id == rollCallService.WorkshopId); string rollCallTransactionDescription = ""; //if (rollCallService.StartService <= prevMonthStart) //{ // var monthPrev = prevMonthEnd.ToFarsi().Substring(5, 2); // var yearPrev = prevMonthEnd.ToFarsi().Substring(0, 4); // var prevMonthName = monthPrev.ToFarsiMonthByNumber(); // description = // $"{prevMonthName} و {currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; // monthCounter = 2; //} //else if (rollCallService.StartService <= currentMonthStart && // rollCallService.StartService > prevMonthStart) //{ // monthCounter = 1; // description = $"{currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; //} if (rollCallService.StartService <= firstDayOfMonthGr) { monthCounter = 1; rollCallTransactionDescription = $"{currentMonthName} {yearCurrent} - {workshop.WorkshopFullName}"; } var employees = await _context.RollCallEmployees .Where(x => x.WorkshopId == rollCallService.WorkshopId) .Select(x => x.id).ToListAsync(); var employeeCount = await _context.RollCallEmployeesStatus .Where(x => employees.Contains(x.RollCallEmployeeId)) .CountAsync(x => x.EndDate.Date == activeStatusDate.Date); if (employeeCount > 0 && monthCounter > 0) { var dailyWageYearlySalery = await _context.YearlySalaries .Include(i => i.YearlySalaryItemsList) .FirstOrDefaultAsync(x => x.StartDate.Date <= DateTime.Now.Date && x.EndDate >= DateTime.Now.Date); var dailyWage = dailyWageYearlySalery.YearlySalaryItemsList .Where(x => x.ItemName == "مزد روزانه") .Select(x => x.ItemValue).FirstOrDefault(); var planPercentage = await _context.PlanPercentages.FirstOrDefaultAsync(); var countPersonnel = employeeCount; var planByCountPerson = await _context.InstitutionPlans .FirstOrDefaultAsync(x => x.CountPerson == countPersonnel); var amountForOneMonth = (((dailyWage * planPercentage.RollCallPercent) / 100) * planByCountPerson.CountPerson * planByCountPerson.IncreasePercentage); var amountWithoutTax = amountForOneMonth * monthCounter; var tenPercent = amountWithoutTax * 10 / 100; var totalAmonut = amountWithoutTax + tenPercent; double roundFloor = Math.Floor(totalAmonut); double result = Math.Ceiling(roundFloor / 10000.0) * 10000; var financialStatment = await _context.FinancialStatments.FirstOrDefaultAsync(x => x.ContractingPartyId == item.ContractingPartyId); long financialStatementId = 0; if (financialStatment != null) { financialStatementId = financialStatment.id; } else { var statement = new FinancialStatment(item.ContractingPartyId, item.ContractingPartyName); await _context.FinancialStatments.AddAsync(statement); await _context.SaveChangesAsync(); financialStatementId = statement.id; } var transaction = new FinancialTransaction(financialStatementId, endOfMonthGr, endOfMonthFa, rollCallTransactionDescription, "debt", "بابت سرویس حضور غیاب", result, 0, 0); var alreadyCreated = await _context.FinancialTransactions.AnyAsync(x => x.FinancialStatementId == financialStatementId && x.Description == rollCallTransactionDescription && x.DescriptionOption == "بابت سرویس حضور غیاب" && x.TypeOfTransaction == "debt" && x.TdateFa == endOfMonthFa); if (!alreadyCreated) { serviceCounter++; Console.WriteLine(serviceCounter + " - " + rollCallService.StartService.ToFarsi() + " - " + rollCallService.WorkshopId + " - " + employeeCount + $" - {totalAmonut} - round {result}"); await _context.FinancialTransactions.AddAsync(transaction); await _context.SaveChangesAsync(); } //Console.WriteLine(" number : " + counter + " - " + rollCallService.StartService.ToFarsi() + " - WorkshopId : " + rollCallService.WorkshopId + " - monthCount : " + monthCounter + " - employeeCount : " + employeeCount + $" - Amount : {amountWithoutTax.ToMoney()}" + $" - ten : {tenPercent.ToMoney()} total : {totalAmonut.ToMoney()}"); } } } } catch (Exception) { string errMess = $"{item.ContractingPartyId}-RollCall"; await _smsService.Alarm("09114221321", errMess); } } #endregion } catch (Exception e) { string name = partyName.Length > 18 ? partyName.Substring(0, 18) : partyName; string errMess = $"{name}-خطا"; await _smsService.Alarm("09114221321", errMess); } count += 1; Console.WriteLine(count); } } #endregion #endregion } public async Task GetIdByInstallmentId(long installmentId) { return await _context.InstitutionContractSet.Include(x => x.Installments) .Where(x => 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 #region CustomViewModels public class WorkshopsAndEmployeeViewModel { public List WorkshopViewModels { get; set; } public string WorkshopCount { get; set; } public string EmployeeCount { get; set; } public int ArchiveCode { get; set; } } #endregion }