diff --git a/.gitignore b/.gitignore index efeea142..f2178c5f 100644 --- a/.gitignore +++ b/.gitignore @@ -365,3 +365,7 @@ MigrationBackup/ /ServiceHost/appsettings.Development.json /ServiceHost/appsettings.json /ServiceHost/web.config + +# Storage folder - ignore all uploaded files, thumbnails, and temporary files +ServiceHost/Storage + diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index d2b77817..6886f00e 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -6585,268 +6585,275 @@ public class InstitutionContractRepository : RepositoryBase - ///دریافت لیست پیامک قرادا های آبی بدهکار + ///دریافت لیست پیامک قراداد های آبی بدهکار /// /// - //public async Task> GetBlueSmsListData() - //{ + public async Task> GetWarningSmsListData() + { - // var institutionContracts = await _context.InstitutionContractSet.AsQueryable().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, - // IsInstallment = x.IsInstallment, - // VerificationStatus = x.VerificationStatus, - // SigningType = x.SigningType, - // }).Where(x => x.IsActiveString == "blue" && - // x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()).ToListAsync(); + var institutionContracts = await _context.InstitutionContractSet.AsQueryable().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, + IsInstallment = x.IsInstallment, + VerificationStatus = x.VerificationStatus, + SigningType = x.SigningType, + }).Where(x => x.IsActiveString == "blue" && + x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()).ToListAsync(); - // // قرارداد هایی که بطور یکجا پرداخت شده اند - // var paidInFull = institutionContracts.Where(x => - // x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); + var institutionContractsIds = institutionContracts.Select(x => x.id).ToList(); - // //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه - // institutionContracts = institutionContracts.Except(paidInFull).ToList(); + // قرارداد هایی که بطور یکجا پرداخت شده اند + var paidInFull = institutionContracts.Where(x => + x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); - // var contractingPartyList = await _context.PersonalContractingParties - // .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); + //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه + institutionContracts = institutionContracts.Except(paidInFull).ToList(); - // 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 contractingPartyList = await _context.PersonalContractingParties + .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).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(); - // var legalActionSentSms =await _context.SmsResults - // .Where(x => x.TypeOfSms == "اقدام قضایی").ToListAsync(); - // var warningSentSms = await _context.SmsResults.Where(x => x.TypeOfSms.Contains("هشدار")).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 oldInstitutionContract = institutionContracts.Where(x => x.IsInstallment == false).ToList(); - // var electronicInstitutionContract = institutionContracts.Where(x => x.IsInstallment == true).ToList(); + 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(); + var legalActionSentSms = await _context.SmsResults + .Where(x => x.TypeOfSms == "اقدام قضایی").ToListAsync(); + var warningSentSms = await _context.SmsResults.Where(x => x.TypeOfSms.Contains("هشدار")).ToListAsync(); - // foreach (var item in oldInstitutionContract) - // { - // try - // { - // var contractingParty = GetDetails(item.ContractingPartyId); - // bool hasLegalActionSentSms = legalActionSentSms.Any(x => x.InstitutionContractId == item.Id); + var oldInstitutionContract = institutionContracts.Where(x => x.IsInstallment == false).ToList(); + var electronicInstitutionContract = institutionContracts.Where(x => x.IsInstallment == true).ToList(); - // if (!string.IsNullOrWhiteSpace(contractingParty.LName) && !hasLegalActionSentSms) - // { - // //Thread.Sleep(500); - // var partyName = contractingParty.LName; + foreach (var item in oldInstitutionContract) + { + try + { + var contractingParty = GetDetails(item.ContractingPartyId); + bool hasLegalActionSentSms = legalActionSentSms.Any(x => x.InstitutionContractId == item.Id); + int year = Convert.ToInt32(item.ContractEndFa.Substring(0, 4)); + int month = Convert.ToInt32(item.ContractEndFa.Substring(5, 2)); + var endOfContractNextMonthStart = new PersianDateTime(year, month, 1).AddMonths(1); + var endOfContractNextMonthEnd = (($"{endOfContractNextMonthStart}").FindeEndOfMonth()).ToGeorgianDateTime(); + var now = DateTime.Now - // if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; + if (!string.IsNullOrWhiteSpace(contractingParty.LName) && !hasLegalActionSentSms && now.Date <= endOfContractNextMonthEnd.Date) + { + //Thread.Sleep(500); + var partyName = contractingParty.LName; - // 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)) - // { - // var hasFinancialStatement = - // financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId); + if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; - // var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); + 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)) + { + var hasFinancialStatement = + financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId); - // if (hasFinancialStatement && hasPhonNumber) - // { - // var phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) - // .Select(x => new CreateContactInfo - // { - // PhoneType = x.PhoneType, - // PhoneNumber = x.PhoneNumber, + var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); - // InstitutionContractId = x.InstitutionContractId, - // SendSms = x.SendSms - // }).Where(x => x.PhoneNumber.Length == 11).ToList(); + if (hasFinancialStatement && hasPhonNumber) + { + var phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) + .Select(x => new CreateContactInfo + { + PhoneType = x.PhoneType, + PhoneNumber = x.PhoneNumber, - // var transactions = financialStatmentList.FirstOrDefault(x => - // x.ContractingPartyId == item.ContractingPartyId); + 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.FinancialTransactionViewModels.Sum(x => x.Deptor); - // var creditor = transactions.FinancialTransactionViewModels.Sum(x => x.Creditor); - + var debtor = transactions.FinancialTransactionViewModels.Sum(x => x.Deptor); + var creditor = transactions.FinancialTransactionViewModels.Sum(x => x.Creditor); - // var id = $"{item.ContractingPartyId}"; - // var aprove = $"{transactions.Id}"; - // var balance = debtor - creditor; - // if (balance > 0) // اگر بدهکار بود - // { + var id = $"{item.ContractingPartyId}"; + var aprove = $"{transactions.Id}"; + var balance = debtor - creditor; - // if (isLegal) - // { - // if (item.OfficialCompany == "Official") // حقوقی بدهکار رسمی - // { - // var balanceToMoney = balance.ToMoney(); + if (balance > 0) // اگر بدهکار بود + { - // foreach (var number in phoneNumbers) - // { - - // var isLastAlarmSend = _context.SmsResults.Any(x => ( - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + if (isLegal) + { + if (item.OfficialCompany == "Official") // حقوقی بدهکار رسمی + { + var balanceToMoney = balance.ToMoney(); - // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && - // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) - // { + foreach (var number in phoneNumbers) + { - // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 608443, - // partyName, - // balanceToMoney, id, aprove); - // Thread.Sleep(1000); - // if (smsResult.IsSuccedded) - // { - // var createSmsResult = new SmsResult(smsResult.MessageId, - // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, - // item.ContractingPartyId, item.Id); - // _smsResultRepository.Create(createSmsResult); - // _smsResultRepository.SaveChanges(); - // Thread.Sleep(1000); - // } + var isLastAlarmSend = _context.SmsResults.Any(x => ( + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + var t = warningSentSms.Any(x=> x.) + if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + { - // } - // } + var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 608443, + partyName, + balanceToMoney, id, aprove); + Thread.Sleep(1000); + if (smsResult.IsSuccedded) + { + var createSmsResult = new SmsResult(smsResult.MessageId, + smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + item.ContractingPartyId, item.Id); + _smsResultRepository.Create(createSmsResult); + _smsResultRepository.SaveChanges(); + Thread.Sleep(1000); + } + + } + } - // } - // else if (item.OfficialCompany == "NotOfficial") // حقوقی بدهکار غیر رسمی - // { - // var balanceToMoney = balance.ToMoney(); - // foreach (var number in phoneNumbers) - // { - // var isSend = _context.SmsResults.Any(x => - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); - // var isLastAlarmSend = _context.SmsResults.Any(x => ( - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); - // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && - // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) - // { + } + else if (item.OfficialCompany == "NotOfficial") // حقوقی بدهکار غیر رسمی + { + var balanceToMoney = balance.ToMoney(); + foreach (var number in phoneNumbers) + { + var isSend = _context.SmsResults.Any(x => + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + var isLastAlarmSend = _context.SmsResults.Any(x => ( + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + { - // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 351691, - // partyName, - // balanceToMoney, id, aprove); - // Thread.Sleep(1000); - // if (smsResult.IsSuccedded) - // { - // var createSmsResult = new SmsResult(smsResult.MessageId, - // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, - // item.ContractingPartyId, item.Id); - // _smsResultRepository.Create(createSmsResult); - // _smsResultRepository.SaveChanges(); - // Thread.Sleep(1000); - // } + var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 351691, + partyName, + balanceToMoney, id, aprove); + Thread.Sleep(1000); + if (smsResult.IsSuccedded) + { + var createSmsResult = new SmsResult(smsResult.MessageId, + smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + item.ContractingPartyId, item.Id); + _smsResultRepository.Create(createSmsResult); + _smsResultRepository.SaveChanges(); + Thread.Sleep(1000); + } - // } - // } + } + } - // } - // } - // else - // { - // if (item.OfficialCompany == "Official") // حقیقی بدهکار رسمی - // { - // var balanceToMoney = balance.ToMoney(); + } + } + else + { + if (item.OfficialCompany == "Official") // حقیقی بدهکار رسمی + { + var balanceToMoney = balance.ToMoney(); - // foreach (var number in phoneNumbers) - // { - // var isSend = _context.SmsResults.Any(x => - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); - // var isLastAlarmSend = _context.SmsResults.Any(x => ( - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); - // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && - // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) - // { + foreach (var number in phoneNumbers) + { + var isSend = _context.SmsResults.Any(x => + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + var isLastAlarmSend = _context.SmsResults.Any(x => ( + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + { - // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 190430, - // partyName, - // balanceToMoney, id, aprove); - // Thread.Sleep(1000); - // if (smsResult.IsSuccedded) - // { - // var createSmsResult = new SmsResult(smsResult.MessageId, - // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, - // item.ContractingPartyId, item.Id); - // _smsResultRepository.Create(createSmsResult); - // _smsResultRepository.SaveChanges(); - // Thread.Sleep(1000); - // } - // } - // } + var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 190430, + partyName, + balanceToMoney, id, aprove); + Thread.Sleep(1000); + if (smsResult.IsSuccedded) + { + var createSmsResult = new SmsResult(smsResult.MessageId, + smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + item.ContractingPartyId, item.Id); + _smsResultRepository.Create(createSmsResult); + _smsResultRepository.SaveChanges(); + Thread.Sleep(1000); + } + } + } - // } - // else if (item.OfficialCompany == "NotOfficial") // حقیقی بدهکار غیر رسمی - // { - // var balanceToMoney = balance.ToMoney(); + } + else if (item.OfficialCompany == "NotOfficial") // حقیقی بدهکار غیر رسمی + { + var balanceToMoney = balance.ToMoney(); - // foreach (var number in phoneNumbers) - // { - // var isSend = _context.SmsResults.Any(x => - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); - // var isLastAlarmSend = _context.SmsResults.Any(x => ( - // x.ContractingPatyId == contractingParty.Id && - // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); - // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && - // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) - // { - // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 412829, - // partyName, - // balanceToMoney, id, aprove); - // Thread.Sleep(1000); - // if (smsResult.IsSuccedded) - // { - // var createSmsResult = new SmsResult(smsResult.MessageId, - // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, - // item.ContractingPartyId, item.Id); - // _smsResultRepository.Create(createSmsResult); - // _smsResultRepository.SaveChanges(); - // Thread.Sleep(1000); - // } + foreach (var number in phoneNumbers) + { + var isSend = _context.SmsResults.Any(x => + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + var isLastAlarmSend = _context.SmsResults.Any(x => ( + x.ContractingPatyId == contractingParty.Id && + x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + { + var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 412829, + partyName, + balanceToMoney, id, aprove); + Thread.Sleep(1000); + if (smsResult.IsSuccedded) + { + var createSmsResult = new SmsResult(smsResult.MessageId, + smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + item.ContractingPartyId, item.Id); + _smsResultRepository.Create(createSmsResult); + _smsResultRepository.SaveChanges(); + Thread.Sleep(1000); + } - // } - // } + } + } - // } - // } - // } - // } - // } - // } - // } - // catch (Exception e) - // { + } + } + } + } + } + } + } + catch (Exception e) + { - // string name = item.ContractingPartyName.Length > 18 ? item.ContractingPartyName.Substring(0, 18) : item.ContractingPartyName; - // string errMess = $"{name}-خطا"; - // _smsService.Alarm("09114221321", errMess); - // _logger.LogError(e, "BlueWarningSms"); - // } - // } - //} + string name = item.ContractingPartyName.Length > 18 ? item.ContractingPartyName.Substring(0, 18) : item.ContractingPartyName; + string errMess = $"{name}-خطا"; + _smsService.Alarm("09114221321", errMess); + _logger.LogError(e, "BlueWarningSms"); + } + } + } #endregion diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs index 3cbc8cec..4a3d9294 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs @@ -89,6 +89,7 @@ public class ProjectSectionDto public TimeSpan FinalEstimatedHours { get; set; } public TimeSpan TotalTimeSpent { get; set; } + public double ProgressPercentage { get; set; } public bool IsCompleted { get; set; } public bool IsInProgress { get; set; } diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs index 67ce006e..2c689cad 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs @@ -166,6 +166,7 @@ public static class ProjectMappingExtensions CreationDate = section.CreationDate, FinalEstimatedHours = section.FinalEstimatedHours, TotalTimeSpent = section.GetTotalTimeSpent(), + ProgressPercentage = section.GetProgressPercentage(), IsCompleted = section.IsCompleted(), IsInProgress = section.IsInProgress(), Activities = section.Activities.Select(a => a.ToDto()).ToList(), @@ -188,6 +189,7 @@ public static class ProjectMappingExtensions CreationDate = section.CreationDate, FinalEstimatedHours = section.FinalEstimatedHours, TotalTimeSpent = section.GetTotalTimeSpent(), + ProgressPercentage = section.GetProgressPercentage(), IsCompleted = section.IsCompleted(), IsInProgress = section.IsInProgress() // No activities or additional times for summary diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs index 7066148e..91a82c28 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs @@ -1,20 +1,28 @@ using GozareshgirProgramManager.Domain.ProjectAgg.Enums; namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; -public record GetProjectListDto + +// Base DTO shared across project, phase, and task +public class GetProjectItemDto { public Guid Id { get; init; } public string Name { get; init; } = string.Empty; public int Percentage { get; init; } public ProjectHierarchyLevel Level { get; init; } public Guid? ParentId { get; init; } - public bool HasFront { get; set; } - public bool HasBackend { get; set; } - public bool HasDesign { get; set; } public int TotalHours { get; set; } public int Minutes { get; set; } - + public AssignmentStatus Front { get; set; } + public AssignmentStatus Backend { get; set; } + public AssignmentStatus Design { get; set; } } +// Project DTO (no extra fields; inherits from base) +public class GetProjectDto : GetProjectItemDto +{ +} - +// Phase DTO (no extra fields; inherits from base) +public class GetPhaseDto : GetProjectItemDto +{ +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs index ceaf2e19..d26a06b1 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs @@ -3,6 +3,7 @@ using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Domain.ProjectAgg.Entities; using GozareshgirProgramManager.Domain.ProjectAgg.Enums; using Microsoft.EntityFrameworkCore; +using System.Linq; namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; @@ -17,47 +18,47 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler> Handle(GetProjectsListQuery request, CancellationToken cancellationToken) { - List projects; + var projects = new List(); + var phases = new List(); + var tasks = new List(); switch (request.HierarchyLevel) { case ProjectHierarchyLevel.Project: projects = await GetProjects(request.ParentId, cancellationToken); + await SetSkillFlags(projects, cancellationToken); break; case ProjectHierarchyLevel.Phase: - projects = await GetPhases(request.ParentId, cancellationToken); + phases = await GetPhases(request.ParentId, cancellationToken); + await SetSkillFlags(phases, cancellationToken); break; case ProjectHierarchyLevel.Task: - projects = await GetTasks(request.ParentId, cancellationToken); + tasks = await GetTasks(request.ParentId, cancellationToken); + // Tasks don't need SetSkillFlags because they have Sections list break; default: return OperationResult.Failure("سطح سلسله مراتب نامعتبر است"); } - await SetSkillFlags(projects, cancellationToken); - var response = new GetProjectsListResponse(projects); + var response = new GetProjectsListResponse(projects, phases, tasks); return OperationResult.Success(response); } - private async Task> GetProjects(Guid? parentId, CancellationToken cancellationToken) + private async Task> GetProjects(Guid? parentId, CancellationToken cancellationToken) { var query = _context.Projects.AsQueryable(); - - // پروژه‌ها سطح بالا هستند و parentId ندارند، فقط در صورت null بودن parentId نمایش داده می‌شوند if (parentId.HasValue) { - return new List(); // پروژه‌ها parent ندارند + return new List(); } - - var projects = await query + var entities = await query .OrderByDescending(p => p.CreationDate) .ToListAsync(cancellationToken); - var result = new List(); - - foreach (var project in projects) + var result = new List(); + foreach (var project in entities) { var (percentage, totalTime) = await CalculateProjectPercentage(project, cancellationToken); - result.Add(new GetProjectListDto + result.Add(new GetProjectDto { Id = project.Id, Name = project.Name, @@ -68,28 +69,24 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler> GetPhases(Guid? parentId, CancellationToken cancellationToken) + private async Task> GetPhases(Guid? parentId, CancellationToken cancellationToken) { var query = _context.ProjectPhases.AsQueryable(); - if (parentId.HasValue) { query = query.Where(x => x.ProjectId == parentId); } - - var phases = await query + var entities = await query .OrderByDescending(p => p.CreationDate) .ToListAsync(cancellationToken); - var result = new List(); - - foreach (var phase in phases) + var result = new List(); + foreach (var phase in entities) { var (percentage, totalTime) = await CalculatePhasePercentage(phase, cancellationToken); - result.Add(new GetProjectListDto + result.Add(new GetPhaseDto { Id = phase.Id, Name = phase.Name, @@ -100,28 +97,87 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler> GetTasks(Guid? parentId, CancellationToken cancellationToken) + private async Task> GetTasks(Guid? parentId, CancellationToken cancellationToken) { var query = _context.ProjectTasks.AsQueryable(); - if (parentId.HasValue) { query = query.Where(x => x.PhaseId == parentId); } - - var tasks = await query + var entities = await query .OrderByDescending(t => t.CreationDate) .ToListAsync(cancellationToken); - var result = new List(); + var result = new List(); + // دریافت تمام Skills + var allSkills = await _context.Skills + .Select(s => new { s.Id, s.Name }) + .ToListAsync(cancellationToken); - foreach (var task in tasks) + foreach (var task in entities) { var (percentage, totalTime) = await CalculateTaskPercentage(task, cancellationToken); - result.Add(new GetProjectListDto + var sections = await _context.TaskSections + .Include(s => s.Activities) + .Include(s => s.Skill) + .Where(s => s.TaskId == task.Id) + .ToListAsync(cancellationToken); + + // جمع‌آوری تمام userId های مورد نیاز + var userIds = sections + .Where(s => s.CurrentAssignedUserId > 0) + .Select(s => s.CurrentAssignedUserId) + .Distinct() + .ToList(); + + // دریافت اطلاعات کاربران + var users = await _context.Users + .Where(u => userIds.Contains(u.Id)) + .Select(u => new { u.Id, u.FullName }) + .ToDictionaryAsync(u => u.Id, u => u.FullName, cancellationToken); + + // محاسبه SpentTime و RemainingTime + var spentTime = TimeSpan.FromTicks(sections.Sum(s => s.Activities.Sum(a => a.GetTimeSpent().Ticks))); + var remainingTime = totalTime - spentTime; + + // ساخت section DTOs برای تمام Skills + var sectionDtos = allSkills.Select(skill => + { + var section = sections.FirstOrDefault(s => s.SkillId == skill.Id); + + if (section == null) + { + // اگر section وجود نداشت، یک DTO با وضعیت Unassigned برمی‌گردانیم + return new GetTaskSectionDto + { + Id = Guid.Empty, + SkillName = skill.Name ?? string.Empty, + SpentTime = TimeSpan.Zero, + TotalTime = TimeSpan.Zero, + Percentage = 0, + UserFullName = string.Empty, + AssignmentStatus = AssignmentStatus.Unassigned + }; + } + + // اگر section وجود داشت + return new GetTaskSectionDto + { + Id = section.Id, + SkillName = skill.Name ?? string.Empty, + SpentTime = TimeSpan.FromTicks(section.Activities.Sum(a => a.GetTimeSpent().Ticks)), + TotalTime = section.FinalEstimatedHours, + Percentage = (int)section.GetProgressPercentage(), + UserFullName = section.CurrentAssignedUserId > 0 && users.ContainsKey(section.CurrentAssignedUserId) + ? users[section.CurrentAssignedUserId] + : string.Empty, + AssignmentStatus = GetAssignmentStatus(section) + }; + }).ToList(); + + result.Add(new GetTaskDto { Id = task.Id, Name = task.Name, @@ -129,187 +185,175 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler projects, CancellationToken cancellationToken) + private async Task SetSkillFlags(List items, CancellationToken cancellationToken) where TItem : GetProjectItemDto { - if (!projects.Any()) + if (!items.Any()) return; - - var projectIds = projects.Select(x => x.Id).ToList(); - var hierarchyLevel = projects.First().Level; - + var ids = items.Select(x => x.Id).ToList(); + var hierarchyLevel = items.First().Level; switch (hierarchyLevel) { case ProjectHierarchyLevel.Project: - await SetSkillFlagsForProjects(projects, projectIds, cancellationToken); + await SetSkillFlagsForProjects(items, ids, cancellationToken); break; - case ProjectHierarchyLevel.Phase: - await SetSkillFlagsForPhases(projects, projectIds, cancellationToken); - break; - - case ProjectHierarchyLevel.Task: - await SetSkillFlagsForTasks(projects, projectIds, cancellationToken); + await SetSkillFlagsForPhases(items, ids, cancellationToken); break; } } - private async Task SetSkillFlagsForProjects(List projects, List projectIds, CancellationToken cancellationToken) + + private async Task SetSkillFlagsForProjects(List items, List projectIds, CancellationToken cancellationToken) where TItem : GetProjectItemDto { - var projectSections = await _context.ProjectSections - .Include(x => x.Skill) - .Where(s => projectIds.Contains(s.ProjectId)) + // For projects: gather all phases, then tasks, then sections + var phases = await _context.ProjectPhases + .Where(ph => projectIds.Contains(ph.ProjectId)) + .Select(ph => ph.Id) + .ToListAsync(cancellationToken); + var tasks = await _context.ProjectTasks + .Where(t => phases.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + var sections = await _context.TaskSections + .Include(s => s.Skill) + .Where(s => tasks.Contains(s.TaskId)) .ToListAsync(cancellationToken); - if (!projectSections.Any()) - return; - - foreach (var project in projects) + foreach (var item in items) { - var sections = projectSections.Where(s => s.ProjectId == project.Id).ToList(); - project.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); - project.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); - project.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); + var relatedPhases = phases; // used for filtering tasks by project + var relatedTasks = await _context.ProjectTasks + .Where(t => t.PhaseId != Guid.Empty && relatedPhases.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + var itemSections = sections.Where(s => relatedTasks.Contains(s.TaskId)); + item.Backend = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Backend")); + item.Front = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Frontend")); + item.Design = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "UI/UX Design")); } } - private async Task SetSkillFlagsForPhases(List projects, List phaseIds, CancellationToken cancellationToken) + private async Task SetSkillFlagsForPhases(List items, List phaseIds, CancellationToken cancellationToken) where TItem : GetProjectItemDto { - var phaseSections = await _context.PhaseSections - .Include(x => x.Skill) - .Where(s => phaseIds.Contains(s.PhaseId)) + // For phases: gather tasks, then sections + var tasks = await _context.ProjectTasks + .Where(t => phaseIds.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + var sections = await _context.TaskSections + .Include(s => s.Skill) + .Where(s => tasks.Contains(s.TaskId)) .ToListAsync(cancellationToken); - if (!phaseSections.Any()) - return; - - foreach (var phase in projects) + foreach (var item in items) { - var sections = phaseSections.Where(s => s.PhaseId == phase.Id).ToList(); - phase.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); - phase.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); - phase.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); - } - } - - private async Task SetSkillFlagsForTasks(List projects, List taskIds, CancellationToken cancellationToken) - { - var taskSections = await _context.TaskSections - .Include(x => x.Skill) - .Where(s => taskIds.Contains(s.TaskId)) - .ToListAsync(cancellationToken); - - if (!taskSections.Any()) - return; - - foreach (var task in projects) - { - var sections = taskSections.Where(s => s.TaskId == task.Id).ToList(); - task.HasBackend = sections.Any(x => x.Skill?.Name == "Backend"); - task.HasFront = sections.Any(x => x.Skill?.Name == "Frontend"); - task.HasDesign = sections.Any(x => x.Skill?.Name == "UI/UX Design"); + // Filter tasks for this phase + var phaseTaskIds = await _context.ProjectTasks + .Where(t => t.PhaseId == item.Id) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + var itemSections = sections.Where(s => phaseTaskIds.Contains(s.TaskId)); + item.Backend = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Backend")); + item.Front = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "Frontend")); + item.Design = GetAssignmentStatus(itemSections.FirstOrDefault(x => x.Skill?.Name == "UI/UX Design")); } } private async Task<(int Percentage, TimeSpan TotalTime)> CalculateProjectPercentage(Project project, CancellationToken cancellationToken) { - // گرفتن تمام فازهای پروژه var phases = await _context.ProjectPhases .Where(ph => ph.ProjectId == project.Id) .ToListAsync(cancellationToken); - if (!phases.Any()) return (0, TimeSpan.Zero); - - // محاسبه درصد هر فاز و میانگین‌گیری var phasePercentages = new List(); var totalTime = TimeSpan.Zero; - foreach (var phase in phases) { var (phasePercentage, phaseTime) = await CalculatePhasePercentage(phase, cancellationToken); phasePercentages.Add(phasePercentage); totalTime += phaseTime; } - var averagePercentage = phasePercentages.Any() ? (int)phasePercentages.Average() : 0; return (averagePercentage, totalTime); } private async Task<(int Percentage, TimeSpan TotalTime)> CalculatePhasePercentage(ProjectPhase phase, CancellationToken cancellationToken) { - // گرفتن تمام تسک‌های فاز var tasks = await _context.ProjectTasks .Where(t => t.PhaseId == phase.Id) .ToListAsync(cancellationToken); - if (!tasks.Any()) return (0, TimeSpan.Zero); - - // محاسبه درصد هر تسک و میانگین‌گیری var taskPercentages = new List(); var totalTime = TimeSpan.Zero; - foreach (var task in tasks) { var (taskPercentage, taskTime) = await CalculateTaskPercentage(task, cancellationToken); taskPercentages.Add(taskPercentage); totalTime += taskTime; } - var averagePercentage = taskPercentages.Any() ? (int)taskPercentages.Average() : 0; return (averagePercentage, totalTime); } private async Task<(int Percentage, TimeSpan TotalTime)> CalculateTaskPercentage(ProjectTask task, CancellationToken cancellationToken) { - // گرفتن تمام سکشن‌های تسک با activities var sections = await _context.TaskSections .Include(s => s.Activities) .Include(x=>x.AdditionalTimes) .Where(s => s.TaskId == task.Id) .ToListAsync(cancellationToken); - if (!sections.Any()) return (0, TimeSpan.Zero); - - // محاسبه درصد هر سکشن و میانگین‌گیری var sectionPercentages = new List(); var totalTime = TimeSpan.Zero; - foreach (var section in sections) { var (sectionPercentage, sectionTime) = CalculateSectionPercentage(section); sectionPercentages.Add(sectionPercentage); totalTime += sectionTime; } - var averagePercentage = sectionPercentages.Any() ? (int)sectionPercentages.Average() : 0; return (averagePercentage, totalTime); } private static (int Percentage, TimeSpan TotalTime) CalculateSectionPercentage(TaskSection section) { - // محاسبه کل زمان تخمین زده شده (اولیه + اضافی) - var totalEstimatedHours = section.FinalEstimatedHours.TotalHours; + return ((int)section.GetProgressPercentage(),section.FinalEstimatedHours); + } - // محاسبه کل زمان صرف شده از activities - var totalSpentTime = TimeSpan.FromHours(section.Activities.Sum(a => a.GetTimeSpent().TotalHours)); + private static AssignmentStatus GetAssignmentStatus(TaskSection? section) + { + // تعیین تکلیف نشده: section وجود ندارد + if (section == null) + return AssignmentStatus.Unassigned; - if (totalEstimatedHours <= 0) - return (0, section.FinalEstimatedHours); + // بررسی وجود user + bool hasUser = section.CurrentAssignedUserId > 0; + + // بررسی وجود time (InitialEstimatedHours بزرگتر از صفر باشد) + bool hasTime = section.InitialEstimatedHours > TimeSpan.Zero; - var totalSpentHours = totalSpentTime.TotalHours; + // تعیین تکلیف شده: هم user و هم time تعیین شده + if (hasUser && hasTime) + return AssignmentStatus.Assigned; - // محاسبه درصد (حداکثر 100%) - var percentage = (totalSpentHours / totalEstimatedHours) * 100; - return (Math.Min((int)Math.Round(percentage), 100), section.FinalEstimatedHours); + // فقط کاربر تعیین شده: user دارد ولی time ندارد + if (hasUser && !hasTime) + return AssignmentStatus.UserOnly; + + // تعیین تکلیف نشده: نه user دارد نه time + return AssignmentStatus.Unassigned; } } diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs index 928501dd..f4934501 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs @@ -1,5 +1,6 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; public record GetProjectsListResponse( - List Projects); - + List Projects, + List Phases, + List Tasks); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetTaskListDto.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetTaskListDto.cs new file mode 100644 index 00000000..d48493d7 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetTaskListDto.cs @@ -0,0 +1,31 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; + +public class GetTaskDto +{ + public Guid Id { get; init; } + public string Name { get; init; } = string.Empty; + public int Percentage { get; init; } + public ProjectHierarchyLevel Level { get; init; } + public Guid? ParentId { get; init; } + public int TotalHours { get; set; } + public int Minutes { get; set; } + + // Task-specific fields + public TimeSpan SpentTime { get; init; } + public TimeSpan RemainingTime { get; init; } + public List Sections { get; init; } +} + +public class GetTaskSectionDto +{ + public Guid Id { get; init; } + public string SkillName { get; init; } = string.Empty; + public TimeSpan SpentTime { get; init; } + public TimeSpan TotalTime { get; init; } + public int Percentage { get; init; } + public string UserFullName{ get; init; } = string.Empty; + public AssignmentStatus AssignmentStatus { get; set; } + +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs index e6502494..1157a932 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs @@ -106,6 +106,7 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler a.TotalSeconds), Histories = mergedHistories }, diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs index ab38750e..688a12c0 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs @@ -18,6 +18,7 @@ public class ProjectBoardListResponse public class ProjectProgressDto { public double CurrentSecond { get; set; } + public int Percentage { get; set; } public double CompleteSecond { get; set; } public List Histories { get; set; } } diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardDetail/ProjectDeployBoardDetailsQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardDetail/ProjectDeployBoardDetailsQueryHandler.cs index 33a1caa6..ddff2247 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardDetail/ProjectDeployBoardDetailsQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardDetail/ProjectDeployBoardDetailsQueryHandler.cs @@ -12,14 +12,16 @@ public record ProjectDeployBoardDetailsResponse( public record ProjectDeployBoardDetailPhaseItem( string Name, TimeSpan TotalTimeSpan, - TimeSpan DoneTimeSpan); + TimeSpan DoneTimeSpan, + int Percentage); public record ProjectDeployBoardDetailTaskItem( string Name, TimeSpan TotalTimeSpan, TimeSpan DoneTimeSpan, + int Percentage, List Skills) - : ProjectDeployBoardDetailPhaseItem(Name, TotalTimeSpan, DoneTimeSpan); + : ProjectDeployBoardDetailPhaseItem(Name, TotalTimeSpan, DoneTimeSpan,Percentage); public record ProjectDeployBoardDetailItemSkill(string OriginalUserFullName, string SkillName, int TimePercentage); @@ -79,22 +81,20 @@ public class var skillName = s.Skill?.Name ?? "بدون مهارت"; - var totalTimeSpent = s.GetTotalTimeSpent(); - - var timePercentage = s.FinalEstimatedHours.Ticks > 0 - ? (int)((totalTimeSpent.Ticks / (double)s.FinalEstimatedHours.Ticks) * 100) - : 0; + var timePercentage = (int)s.GetProgressPercentage(); return new ProjectDeployBoardDetailItemSkill( originalUserFullName, skillName, timePercentage); }).ToList(); + var taskPercentage = (int)Math.Round(skills.Average(x => x.TimePercentage)); return new ProjectDeployBoardDetailTaskItem( t.Name, totalTime, doneTime, + taskPercentage, skills); }).ToList(); @@ -104,7 +104,10 @@ public class var doneTimeSpan = tasksRes.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next.DoneTimeSpan)); - var phaseRes = new ProjectDeployBoardDetailPhaseItem(phase.Name, totalTimeSpan, doneTimeSpan); + var phasePercentage = tasksRes.Average(x => x.Percentage); + + var phaseRes = new ProjectDeployBoardDetailPhaseItem(phase.Name, totalTimeSpan, doneTimeSpan, + (int)phasePercentage); var res = new ProjectDeployBoardDetailsResponse(phaseRes, tasksRes); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardList/ProjectDeployBoardListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardList/ProjectDeployBoardListQueryHandler.cs index 6a0a7cda..d8f6e39d 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardList/ProjectDeployBoardListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectDeployBoardList/ProjectDeployBoardListQueryHandler.cs @@ -17,6 +17,7 @@ public record ProjectDeployBoardListItem() public int DoneTasks { get; set; } public TimeSpan TotalTimeSpan { get; set; } public TimeSpan DoneTimeSpan { get; set; } + public int Percentage { get; set; } public ProjectDeployStatus DeployStatus { get; set; } } public record GetProjectsDeployBoardListResponse(List Items); @@ -66,7 +67,8 @@ public class ProjectDeployBoardListQueryHandler:IBaseQueryHandler x.TaskId).Distinct().Count(), TotalTimeSpan = TimeSpan.FromTicks(g.Sum(x => x.InitialEstimatedHours.Ticks)), DoneTimeSpan = TimeSpan.FromTicks(g.Sum(x=>x.GetTotalTimeSpent().Ticks)), - DeployStatus = g.First().Task.Phase.DeployStatus + DeployStatus = g.First().Task.Phase.DeployStatus, + Percentage = (int)Math.Round(g.Average(x => x.GetProgressPercentage())) }).ToList(); var response = new GetProjectsDeployBoardListResponse(list); return OperationResult.Success(response); diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs index 891a60fc..245d8b39 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs @@ -106,7 +106,8 @@ public class SendMessageCommandHandler : IBaseCommandHandler m.SenderUserId).Distinct().ToList(); + var users = await _context.Users + .Where(u => senderUserIds.Contains(u.Id)) + .ToDictionaryAsync(u => u.Id, u => u.FullName, cancellationToken); + + // ✅ گرفتن تمامی زمان‌های اضافی (Additional Times) برای نمایش به صورت نوت + // در اینجا تمامی TaskSections مربوط به این تسک را می‌گیریم + // و برای هر کدام تمام AdditionalTimes آن را بارگذاری می‌کنیم + var taskSections = await _context.TaskSections + .Where(ts => ts.TaskId == request.TaskId) + .Include(ts => ts.AdditionalTimes) + .ToListAsync(cancellationToken); + var messageDtos = new List(); foreach (var message in messages) { + // ✅ نام فرستنده را از Dictionary Users بگیر، در صورت عدم وجود "کاربر ناشناس" نمایش بده + var senderName = users.ContainsKey(message.SenderUserId) + ? users[message.SenderUserId] + : "کاربر ناشناس"; + var dto = new MessageDto { Id = message.Id, TaskId = message.TaskId, SenderUserId = message.SenderUserId, - SenderName = "کاربر", // TODO: از User service + SenderName = senderName, // ✅ از User واقعی استفاده می‌کنیم MessageType = message.MessageType.ToString(), TextContent = message.TextContent, ReplyToMessageId = message.ReplyToMessageId, @@ -67,11 +88,16 @@ public class GetMessagesQueryHandler : IBaseQueryHandler ts.AdditionalTimes) + .Where(at => at.AddedAt > message.CreationDate) // ✅ تغییر به AddedAt (زمان واقعی اضافه شدن) + .OrderBy(at => at.AddedAt) + .FirstOrDefault(); + + if (additionalTimesAfterMessage != null) + { + // ✅ تمام AdditionalTimes بین این پیام و پیام قبلی را بگیر + var additionalTimesByDate = taskSections + .SelectMany(ts => ts.AdditionalTimes) + .Where(at => at.AddedAt <= message.CreationDate && + (messageDtos.Count == 1 || at.AddedAt > messageDtos[messageDtos.Count - 2].CreationDate)) + .OrderBy(at => at.AddedAt) + .ToList(); + + foreach (var additionalTime in additionalTimesByDate) + { + // ✅ نام کاربری که این زمان اضافی را اضافه کرد + var addedByUserName = additionalTime.AddedByUserId.HasValue && users.TryGetValue(additionalTime.AddedByUserId.Value, out var user) + ? user + : "سیستم"; + + // ✅ محتوای نوت را با اطلاعات کامل ایجاد کن + // نمایش می‌دهد: مقدار زمان + علت + نام کسی که اضافه کرد + var noteContent = $"⏱️ زمان اضافی: {additionalTime.Hours.TotalHours:F2} ساعت - {(string.IsNullOrWhiteSpace(additionalTime.Reason) ? "بدون علت" : additionalTime.Reason)} - توسط {addedByUserName}"; + + // ✅ نوت را به عنوان MessageDto خاصی ایجاد کن + var noteDto = new MessageDto + { + Id = Guid.NewGuid(), + TaskId = request.TaskId, + SenderUserId = 0, // ✅ سیستم برای نشان دادن اینکه یک پیام خودکار است + SenderName = "سیستم", + MessageType = "Note", // ✅ نوع پیام: Note (یادداشت سیستم) + TextContent = noteContent, + CreationDate = additionalTime.AddedAt, // ✅ تاریخ اضافه شدن زمان اضافی + IsMine = false + }; + + messageDtos.Add(noteDto); + } + } } + // ✅ مرتب کردن نهایی تمام پیام‌ها (معمولی + نوت‌ها) بر اساس زمان ایجاد + // اینطور که نوت‌های زمان اضافی در جای درست خود قرار می‌گیرند + messageDtos = messageDtos.OrderBy(m => m.CreationDate).ToList(); + var response = new PaginationResult() { List = messageDtos, diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/GetPinnedMessages/GetPinnedMessagesQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/GetPinnedMessages/GetPinnedMessagesQuery.cs index 6a7b46ee..15e1cf40 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/GetPinnedMessages/GetPinnedMessagesQuery.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/GetPinnedMessages/GetPinnedMessagesQuery.cs @@ -29,16 +29,25 @@ public class GetPinnedMessagesQueryHandler : IBaseQueryHandler m.PinnedDate) .ToListAsync(cancellationToken); + // ✅ گرفتن تمامی کاربران برای نمایش نام کامل فرستنده + var senderUserIds = messages.Select(m => m.SenderUserId).Distinct().ToList(); + var users = await _context.Users + .Where(u => senderUserIds.Contains(u.Id)) + .ToDictionaryAsync(u => u.Id, u => u.FullName, cancellationToken); + var messageDtos = new List(); foreach (var message in messages) { + // ✅ نام فرستنده را از User واقعی بگیر (به جای "کاربر" ثابت) + var senderName = users.GetValueOrDefault(message.SenderUserId, "کاربر ناشناس"); + var dto = new MessageDto { Id = message.Id, TaskId = message.TaskId, SenderUserId = message.SenderUserId, - SenderName = "کاربر", + SenderName = senderName, MessageType = message.MessageType.ToString(), TextContent = message.TextContent, IsPinned = message.IsPinned, diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/SearchMessages/SearchMessagesQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/SearchMessages/SearchMessagesQuery.cs index b2f23a5c..dffc1331 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/SearchMessages/SearchMessagesQuery.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Queries/SearchMessages/SearchMessagesQuery.cs @@ -40,15 +40,24 @@ public class SearchMessagesQueryHandler : IBaseQueryHandler m.SenderUserId).Distinct().ToList(); + var users = await _context.Users + .Where(u => senderUserIds.Contains(u.Id)) + .ToDictionaryAsync(u => u.Id, u => u.FullName, cancellationToken); + var messageDtos = new List(); foreach (var message in messages) { + // ✅ نام فرستنده را از User واقعی بگیر + var senderName = users.GetValueOrDefault(message.SenderUserId, "کاربر ناشناس"); + var dto = new MessageDto { Id = message.Id, TaskId = message.TaskId, SenderUserId = message.SenderUserId, - SenderName = "کاربر", + SenderName = senderName, MessageType = message.MessageType.ToString(), TextContent = message.TextContent, CreationDate = message.CreationDate, diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Services/FileManagement/IThumbnailGeneratorService.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Services/FileManagement/IThumbnailGeneratorService.cs index 142a4542..cff21a1a 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Services/FileManagement/IThumbnailGeneratorService.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Services/FileManagement/IThumbnailGeneratorService.cs @@ -9,15 +9,17 @@ public interface IThumbnailGeneratorService /// تولید thumbnail برای تصویر /// Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateImageThumbnailAsync( - string imagePath, - int width = 200, + string imagePath, + string category, + int width = 200, int height = 200); /// /// تولید thumbnail برای ویدیو /// Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync( - string videoPath); + string videoPath, + string category); /// /// حذف thumbnail diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs index 7209dd00..072422fe 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs @@ -157,6 +157,27 @@ public class TaskSection : EntityBase return TimeSpan.FromTicks(_activities.Sum(a => a.GetTimeSpent().Ticks)); } + /// + /// محاسبه درصد پیشرفت بر اساس زمان مصرف شده به تایم برآورد شده + /// اگر وضعیت Completed باشد، همیشه 100 درصد برمی‌گرداند + /// + public double GetProgressPercentage() + { + // اگر تسک کامل شده، همیشه 100 درصد + if (Status == TaskSectionStatus.Completed) + return 100.0; + + // اگر تایم برآورد شده صفر است، درصد صفر است + if (FinalEstimatedHours.TotalHours <= 0) + return 0.0; + + var timeSpent = GetTotalTimeSpent(); + var percentage = (timeSpent.TotalMinutes / FinalEstimatedHours.TotalMinutes) * 100.0; + + // محدود کردن درصد به 100 (در صورتی که زمان مصرف شده بیشتر از تخمین باشد) + return Math.Min(percentage, 100.0); + } + public bool IsCompleted() { return Status == TaskSectionStatus.Completed; diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/AssignmentStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/AssignmentStatus.cs new file mode 100644 index 00000000..91cbeffd --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/AssignmentStatus.cs @@ -0,0 +1,23 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +/// +/// وضعیت تکلیف دهی برای بخش‌های مختلف پروژه +/// +public enum AssignmentStatus +{ + /// + /// تعیین تکلیف نشده + /// + Unassigned = 0, + + /// + /// تعیین تکلیف شده + /// + Assigned = 1, + + /// + /// فقط کاربر تعیین شده + /// + UserOnly = 2, +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Entities/TaskChatMessage.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Entities/TaskChatMessage.cs index f82435be..d259872e 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Entities/TaskChatMessage.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Entities/TaskChatMessage.cs @@ -62,17 +62,25 @@ public class TaskChatMessage : EntityBase private void ValidateMessage() { + // ✅ بررسی پیام‌های متنی if (MessageType == MessageType.Text && string.IsNullOrWhiteSpace(TextContent)) { throw new BadRequestException("پیام متنی نمی‌تواند خالی باشد"); } + // ✅ بررسی پیام‌های فایلی - باید FileId داشته باشند if ((MessageType == MessageType.File || MessageType == MessageType.Voice || MessageType == MessageType.Image || MessageType == MessageType.Video) && FileId == null) { throw new BadRequestException("پیام‌های فایلی باید شناسه فایل داشته باشند"); } + + // ✅ بررسی یادداشت‌های سیستم - باید محتوای متنی داشته باشند + if (MessageType == MessageType.Note && string.IsNullOrWhiteSpace(TextContent)) + { + throw new BadRequestException("یادداشت نمی‌تواند خالی باشد"); + } } public void SetFile(Guid fileId) @@ -98,7 +106,7 @@ public class TaskChatMessage : EntityBase throw new BadRequestException("فقط فرستنده می‌تواند پیام را ویرایش کند"); } - if (MessageType != MessageType.Text) + if (MessageType != MessageType.Text || (MessageType != MessageType.Text && !string.IsNullOrWhiteSpace(TextContent))) { throw new BadRequestException("فقط پیام‌های متنی قابل ویرایش هستند"); } diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Enums/MessageType.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Enums/MessageType.cs index 4b30dcd4..f35c1034 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Enums/MessageType.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/TaskChatAgg/Enums/MessageType.cs @@ -10,5 +10,6 @@ public enum MessageType Image = 3, // تصویر Voice = 4, // پیام صوتی Video = 5, // ویدیو + Note = 6, // ✅ یادداشت سیستم (برای زمان اضافی و اطلاعات خودکار) } diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/LocalFileStorageService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/LocalFileStorageService.cs index a0630582..1fec469f 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/LocalFileStorageService.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/LocalFileStorageService.cs @@ -24,11 +24,11 @@ public class LocalFileStorageService : IFileStorageService var request = httpContextAccessor.HttpContext?.Request; if (request != null) { - _baseUrl = $"{request.Scheme}://{request.Host}/uploads"; + _baseUrl = $"{request.Scheme}://{request.Host}/storage"; } else { - _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/uploads"; + _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/storage"; } // ایجاد پوشه اگر وجود نداشت diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs index df55c827..baf6366b 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs @@ -1,4 +1,5 @@ using GozareshgirProgramManager.Application.Services.FileManagement; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; @@ -14,12 +15,21 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService private readonly string _thumbnailBasePath; private readonly string _baseUrl; - public ThumbnailGeneratorService(IConfiguration configuration) + public ThumbnailGeneratorService(IConfiguration configuration, + IHttpContextAccessor httpContextAccessor) { _thumbnailBasePath = configuration["FileStorage:ThumbnailPath"] - ?? Path.Combine(Directory.GetCurrentDirectory(), "Uploads", "Thumbnails"); + ?? Path.Combine(Directory.GetCurrentDirectory(), "storage", "Thumbnails"); + var request = httpContextAccessor.HttpContext?.Request; - _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/uploads"; + if (request != null) + { + _baseUrl = $"{request.Scheme}://{request.Host}/storage"; + } + else + { + _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/storage"; + } if (!Directory.Exists(_thumbnailBasePath)) { @@ -28,7 +38,8 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService } public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateImageThumbnailAsync( - string imagePath, + string imagePath, + string category, int width = 200, int height = 200) { @@ -54,14 +65,12 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService var extension = Path.GetExtension(imagePath); var thumbnailFileName = $"{fileName}_thumb{extension}"; - // مسیر ذخیره thumbnail - var thumbnailPath = Path.Combine(_thumbnailBasePath, thumbnailFileName); + // دریافت مسیر و URL توسط متد private + var (thumbnailPath, thumbnailUrl) = GetThumbnailPathAndUrl(thumbnailFileName, category); // ذخیره thumbnail با کیفیت 80 await image.SaveAsync(thumbnailPath, new JpegEncoder { Quality = 80 }); - // URL thumbnail - var thumbnailUrl = $"{_baseUrl}/thumbnails/{thumbnailFileName}"; return (thumbnailPath, thumbnailUrl); } @@ -72,7 +81,7 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService } } - public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync(string videoPath) + public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync(string videoPath, string category = "general") { // TODO: برای Video thumbnail باید از FFmpeg استفاده کنیم // فعلاً یک placeholder image برمی‌گردانیم @@ -107,5 +116,29 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService return null; } } -} + /// + /// دریافت مسیر فیزیکی و URL برای thumbnail بر اساس category + /// + private (string ThumbnailPath, string ThumbnailUrl) GetThumbnailPathAndUrl(string thumbnailFileName, string category) + { + var categoryFolder = string.IsNullOrWhiteSpace(category) ? "general" : category; + var categoryPath = Path.Combine(Directory.GetCurrentDirectory(), "storage", categoryFolder); + + if (!Directory.Exists(categoryPath)) + { + Directory.CreateDirectory(categoryPath); + } + + var thumbnailSubPath = Path.Combine(categoryPath, "Thumbnails"); + if (!Directory.Exists(thumbnailSubPath)) + { + Directory.CreateDirectory(thumbnailSubPath); + } + + var thumbnailPath = Path.Combine(thumbnailSubPath, thumbnailFileName); + var thumbnailUrl = $"{_baseUrl}/{categoryFolder}/thumbnails/{thumbnailFileName}"; + + return (thumbnailPath, thumbnailUrl); + } +} diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index 5a850414..0c238bc4 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -165,4 +165,12 @@ public class ProjectController : ProgramManagerBaseController var res = await _mediator.Send(command); return res; } + + [HttpPost("change-priority")] + public async Task> ChangePriority([FromBody] ChangeTaskPriorityCommand command) + { + var res = await _mediator.Send(command); + return res; + } + } \ No newline at end of file diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 76189996..f999964c 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -380,13 +380,7 @@ builder.Host.UseSerilog((context, services, configuration) => .ReadFrom.Configuration(context.Configuration) .ReadFrom.Services(services) .Enrich.FromLogContext(); - - // در محیط Development، EF Core Commands را هم لاگ می‌کنیم - if (context.HostingEnvironment.IsDevelopment()) - { - logConfig - .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Information); - } + logConfig.WriteTo.File( path: Path.Combine(logDirectory, "gozareshgir_log.txt"), @@ -493,7 +487,7 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); // Static files برای فایل‌های آپلود شده -var uploadsPath = builder.Configuration["FileStorage:LocalPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "Uploads"); +var uploadsPath = builder.Configuration["FileStorage:LocalPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "Storage"); if (!Directory.Exists(uploadsPath)) { Directory.CreateDirectory(uploadsPath); @@ -502,7 +496,7 @@ if (!Directory.Exists(uploadsPath)) app.UseStaticFiles(new StaticFileOptions { FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(uploadsPath), - RequestPath = "/uploads", + RequestPath = "/storage", OnPrepareResponse = ctx => { // Cache برای فایل‌ها (30 روز) diff --git a/ServiceHost/Storage/Apk/Android/GozreshgirWebView/gozareshgirV1.5.v1.0.apk b/ServiceHost/Storage/Apk/Android/GozreshgirWebView/gozareshgirV1.5.v1.0.apk deleted file mode 100644 index 62038ba0..00000000 Binary files a/ServiceHost/Storage/Apk/Android/GozreshgirWebView/gozareshgirV1.5.v1.0.apk and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989-thumbnail.jpg deleted file mode 100644 index f0183075..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989.jpg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989.jpg deleted file mode 100644 index 145a2f8c..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42416/EmployeePicture-1403-11-29-773852181989.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422-thumbnail.jpeg deleted file mode 100644 index aa26e4d6..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422.jpeg deleted file mode 100644 index 196a41f3..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/EmployeePicture-1403-11-30-622720870422.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366-thumbnail.jpeg deleted file mode 100644 index aa26e4d6..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366.jpeg deleted file mode 100644 index 1b7b4ebf..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage1-1403-11-30-622845188366.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535-thumbnail.jpeg deleted file mode 100644 index aa26e4d6..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535.jpeg deleted file mode 100644 index 196a41f3..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage2-1403-11-30-622882227535.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655-thumbnail.jpeg deleted file mode 100644 index aa26e4d6..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655.jpeg deleted file mode 100644 index 196a41f3..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/IdCardPage3-1403-11-30-622915207655.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099-thumbnail.jpg deleted file mode 100644 index 95e6806e..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099.jpg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099.jpg deleted file mode 100644 index 129024aa..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardFront-1403-11-30-622754962099.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736-thumbnail.jpeg deleted file mode 100644 index d5513557..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736.jpeg b/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736.jpeg deleted file mode 100644 index 62069205..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Confirmed/170/42565/NationalCardRear-1403-11-30-649899718736.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887-thumbnail.jpg deleted file mode 100644 index 5646abfd..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887.jpg b/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887.jpg deleted file mode 100644 index 9c9d9590..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42565/NationalCardRear-1403-11-30-622795832887.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124-thumbnail.jpg deleted file mode 100644 index fca0edf8..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124.jpg b/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124.jpg deleted file mode 100644 index 7a6766d1..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/Rejected/170/42821/EmployeePicture-1404-2-15-652859999124.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007-thumbnail.jpeg deleted file mode 100644 index aa26e4d6..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007.jpeg deleted file mode 100644 index 196a41f3..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/EmployeePicture-1403-11-30-641515603007.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993-thumbnail.jpg deleted file mode 100644 index 5646abfd..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993.jpg deleted file mode 100644 index 9c9d9590..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardFront-1403-11-30-641565540993.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133-thumbnail.jpg deleted file mode 100644 index 5646abfd..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133.jpg deleted file mode 100644 index 9c9d9590..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42819/NationalCardRear-1403-11-30-641614712133.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911-thumbnail.jpeg deleted file mode 100644 index d5513557..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911.jpeg deleted file mode 100644 index 62069205..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/EmployeePicture-1403-11-30-641877888911.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835-thumbnail.jpeg deleted file mode 100644 index 94937553..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835.jpeg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835.jpeg deleted file mode 100644 index bacedd2d..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/42821/NationalCardFront-1403-11-30-641908073835.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149-thumbnail.png b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149-thumbnail.png deleted file mode 100644 index 0ea5b4ee..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149-thumbnail.png and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149.png b/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149.png deleted file mode 100644 index 172b7540..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByAdmin/170/43064/EmployeePicture-1403-11-30-646654300149.png and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122-thumbnail.jpg deleted file mode 100644 index 24ebfd83..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122.jpg deleted file mode 100644 index 35f8afae..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardFront-1403-11-30-606228058122.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144-thumbnail.jpg deleted file mode 100644 index 24ebfd83..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144.jpg deleted file mode 100644 index 35f8afae..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42416/NationalCardRear-1403-11-30-606307237144.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987-thumbnail.jpg deleted file mode 100644 index 96297d0b..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987.jpg deleted file mode 100644 index 7fd6a25c..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/EmployeePicture-1403-11-30-623081234987.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340-thumbnail.jpg deleted file mode 100644 index 24ebfd83..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340.jpg b/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340.jpg deleted file mode 100644 index 35f8afae..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/SubmittedByClient/170/42566/NationalCardFront-1403-11-30-623166908340.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858-thumbnail.jpg deleted file mode 100644 index fca0edf8..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858.jpg deleted file mode 100644 index 7a6766d1..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/42821/EmployeePicture-1404-2-15-653376702858.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778-thumbnail.jpg deleted file mode 100644 index 047bb76e..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778.jpg deleted file mode 100644 index dbaac0d5..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/EmployeePicture-1403-11-30-600342657778.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480-thumbnail.jpeg b/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480-thumbnail.jpeg deleted file mode 100644 index 94937553..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480-thumbnail.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480.jpeg b/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480.jpeg deleted file mode 100644 index bacedd2d..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/170/8523/NationalCardFront-1403-11-30-600439780480.jpeg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264-thumbnail.jpg deleted file mode 100644 index fca0edf8..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264.jpg deleted file mode 100644 index 7a6766d1..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/EmployeePicture-1404-2-15-650997942264.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927-thumbnail.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927-thumbnail.jpg deleted file mode 100644 index fca0edf8..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927-thumbnail.jpg and /dev/null differ diff --git a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927.jpg b/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927.jpg deleted file mode 100644 index 7a6766d1..00000000 Binary files a/ServiceHost/Storage/EmployeeDocuments/temp/572/43228/NationalCardFront-1404-2-15-651445927927.jpg and /dev/null differ diff --git a/ServiceHost/Storage/Task/12296/RollCallBgService_638754044052039151.zip b/ServiceHost/Storage/Task/12296/RollCallBgService_638754044052039151.zip deleted file mode 100644 index d868647f..00000000 Binary files a/ServiceHost/Storage/Task/12296/RollCallBgService_638754044052039151.zip and /dev/null differ diff --git a/ServiceHost/Storage/Ticket/42/screenshot_638731627679227408.png b/ServiceHost/Storage/Ticket/42/screenshot_638731627679227408.png deleted file mode 100644 index 2801ac35..00000000 Binary files a/ServiceHost/Storage/Ticket/42/screenshot_638731627679227408.png and /dev/null differ diff --git a/ServiceHost/Storage/Ticket/43/screenshot_638737819107504668.png b/ServiceHost/Storage/Ticket/43/screenshot_638737819107504668.png deleted file mode 100644 index 83464160..00000000 Binary files a/ServiceHost/Storage/Ticket/43/screenshot_638737819107504668.png and /dev/null differ diff --git a/ServiceHost/Storage/Ticket/47/screenshot_638754047520224604.png b/ServiceHost/Storage/Ticket/47/screenshot_638754047520224604.png deleted file mode 100644 index bb053a8c..00000000 Binary files a/ServiceHost/Storage/Ticket/47/screenshot_638754047520224604.png and /dev/null differ diff --git a/ServiceHost/Storage/Ticket/48/screenshot_638754047808657807.png b/ServiceHost/Storage/Ticket/48/screenshot_638754047808657807.png deleted file mode 100644 index 17c3f4a8..00000000 Binary files a/ServiceHost/Storage/Ticket/48/screenshot_638754047808657807.png and /dev/null differ