diff --git a/.gitignore b/.gitignore index 89d3b553..6ea6524b 100644 --- a/.gitignore +++ b/.gitignore @@ -368,3 +368,6 @@ MigrationBackup/ # Storage folder - ignore all uploaded files, thumbnails, and temporary files ServiceHost/Storage +.env +.env.* + diff --git a/0_Framework/Application/Enums/TypeOfSmsSetting.cs b/0_Framework/Application/Enums/TypeOfSmsSetting.cs index 28089ced..a604e9e6 100644 --- a/0_Framework/Application/Enums/TypeOfSmsSetting.cs +++ b/0_Framework/Application/Enums/TypeOfSmsSetting.cs @@ -45,6 +45,11 @@ public enum TypeOfSmsSetting /// SendInstitutionContractConfirmationCode, + /// + /// لینک تاییدیه ایجاد قرارداد مالی + /// + SendInstitutionContractConfirmationLink, + /// /// یادآور وظایف /// diff --git a/0_Framework/Application/Sms/ApiResultViewModel.cs b/0_Framework/Application/Sms/ApiResultViewModel.cs index 0d5c1ca1..4bb3bd47 100644 --- a/0_Framework/Application/Sms/ApiResultViewModel.cs +++ b/0_Framework/Application/Sms/ApiResultViewModel.cs @@ -30,5 +30,22 @@ public class ApiReportDto public string DeliveryState { get; set; } public string DeliveryUnixTime { get; set; } public string DeliveryColor { get; set; } + public string FullName { get; set; } + +} + +public class SmsDetailsDto +{ + + + public string MessageText { get; set; } + + public long Mobile { get; set; } + + public string SendUnixTime { get; set; } + public string DeliveryState { get; set; } + public string DeliveryUnixTime { get; set; } + public string DeliveryColor { get; set; } + public string FullName { get; set; } } \ No newline at end of file diff --git a/0_Framework/Application/Sms/ISmsService.cs b/0_Framework/Application/Sms/ISmsService.cs index 20e41608..3c02e90f 100644 --- a/0_Framework/Application/Sms/ISmsService.cs +++ b/0_Framework/Application/Sms/ISmsService.cs @@ -16,15 +16,21 @@ public interface ISmsService /// /// Task SendVerifyCodeToClient(string number, string code); - bool SendAccountsInfo(string number,string fullName, string userName); + bool SendAccountsInfo(string number, string fullName, string userName); Task GetByMessageId(int messId); Task> GetApiResult(string startDate, string endDate); #region ForApi Task> GetApiReport(string startDate, string endDate); - -#endregion + /// + /// دریافت جزئیات پیامک + /// + /// + /// + /// + Task GetSmsDetailsByMessageId(int messId, string fullName); + #endregion string DeliveryStatus(byte? dv); string DeliveryColorStatus(byte? dv); @@ -33,9 +39,9 @@ public interface ISmsService #region Mahan Task GetCreditAmount(); - + public Task SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms = null); - + public Task SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName, long contractingPartyId, long institutionContractId); @@ -68,7 +74,7 @@ public interface ISmsService /// /// Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBill(string number, int tamplateId, string fullname, string amount, string id, string aprove); - + /// /// پیامک مسدودی طرف حساب /// قراردادهای قدیم diff --git a/0_Framework/Application/StaticWorkshopAccounts.cs b/0_Framework/Application/StaticWorkshopAccounts.cs index 44491a69..e1e340db 100644 --- a/0_Framework/Application/StaticWorkshopAccounts.cs +++ b/0_Framework/Application/StaticWorkshopAccounts.cs @@ -31,8 +31,9 @@ public static class StaticWorkshopAccounts /// 381 - مهدی قربانی /// 392 - عمار حسن دوست /// 20 - سمیرا الهی نیا + /// 322 - ماهان چمنی /// - public static List StaticAccountIds = [2, 3, 380, 381, 392, 20, 476]; + public static List StaticAccountIds = [2, 3, 380, 381, 392, 20, 476,322]; /// /// این تاریخ در جدول اکانت لفت ورک به این معنیست diff --git a/Company.Domain/SmsResultAgg/ISmsResultRepository.cs b/Company.Domain/SmsResultAgg/ISmsResultRepository.cs index 24ee411b..395e3f4c 100644 --- a/Company.Domain/SmsResultAgg/ISmsResultRepository.cs +++ b/Company.Domain/SmsResultAgg/ISmsResultRepository.cs @@ -1,4 +1,5 @@ -using _0_Framework.Domain; +using _0_Framework.Application.Enums; +using _0_Framework.Domain; using CompanyManagment.App.Contracts.SmsResult; using CompanyManagment.App.Contracts.SmsResult.Dto; using System.Collections.Generic; @@ -22,8 +23,9 @@ public interface ISmsResultRepository : IRepository /// /// /// + /// /// - Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date); + Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date, string typeOfSmsSetting); #endregion List Search(SmsResultSearchModel searchModel); diff --git a/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs b/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs index a2c864a5..8baacff0 100644 --- a/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs +++ b/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs @@ -1,6 +1,7 @@ using _0_Framework.Application.Enums; using _0_Framework.Domain; using CompanyManagment.App.Contracts.SmsResult; +using System.Collections.Generic; using System.Threading.Tasks; namespace Company.Domain.SmsResultAgg; @@ -27,4 +28,25 @@ public interface ISmsSettingsRepository : IRepository /// /// Task RemoveItem(long id); + + + #region ForApi + + /// + /// دریافت لیست پیامک های خودکار بر اساس نوع آن + /// Api + /// + /// + /// + Task> GetSmsSettingList(TypeOfSmsSetting typeOfSmsSetting); + + + + /// + /// دریافت اطلاعات تنظیمات پیامک جهت ویرایش + /// + /// + /// + Task GetSmsSettingDataToEdit(long id); + #endregion } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs index eb230aa4..1978e034 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs @@ -324,6 +324,7 @@ public class InstitutionContractCreationWorkshopsResponse { public List WorkshopTemps { get; set; } public string TotalAmount { get; set; } + public Guid TempId { get; set; } } public class InstitutionContractCreationWorkshopsRequest diff --git a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractExtensionCompleteRequest.cs b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractExtensionCompleteRequest.cs index 8de7ac89..e507db6d 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractExtensionCompleteRequest.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractExtensionCompleteRequest.cs @@ -7,6 +7,7 @@ public class InstitutionContractExtensionCompleteRequest public Guid TemporaryId { get; set; } public bool IsInstallment { get; set; } public long LawId { get; set; } + public bool CancelSendVerificationSms { get; set; } } public class InstitutionContractCreationCompleteRequest diff --git a/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs index e81a8ecf..9fb58b9e 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs @@ -1,4 +1,6 @@ -namespace CompanyManagment.App.Contracts.InstitutionContract; +using System.Collections.Generic; + +namespace CompanyManagment.App.Contracts.InstitutionContract; /// /// لیست پیامکهای بدهکاران قرارداد ملی @@ -113,10 +115,30 @@ public class BlockSmsListData /// -/// لیست قراداد های آبی -/// جهت ارسال هشدار یا اقدام قضائی +///پیامک آنی یادآور /// -public class BlueWarningSmsData +public class InstantReminderSendSms { + /// + /// نام طرف حساب + /// + public string FullName { get; set; } + /// + /// مبلغ بدهی + /// + public string Amount { get; set; } + public List InstantReminderSmsList { get; set; } +} + +public class InstantReminderSmsList +{ + /// + /// شماره تماس طرف حساب + /// + public string PhoneNumber { get; set; } + + + + } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs b/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs index f467ca34..5873ac60 100644 --- a/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs +++ b/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs @@ -60,3 +60,43 @@ public class SmsSettingViewModel /// public List EditSmsSettings { get; set; } } + + + +/// +/// لیست تنظیمات پیامک خودکار +/// +public class SmsSettingDto +{ + /// + /// آی دی + /// + public long Id { get; set; } + + /// + /// عدد روز از ماه + /// + public int DayOfMonth { get; set; } + + /// + /// نمایش ساعت و دقیقه + /// + public string TimeOfDayDisplay { get; set; } +} + + +public class CreateSmsSettingDto +{ + /// + /// عدد روز از ماه + /// + public int DayOfMonth { get; set; } + + /// + /// نمایش ساعت و دقیقه + /// + public string TimeOfDayDisplay { get; set; } +} + + + diff --git a/CompanyManagment.App.Contracts/SmsResult/Dto/SmsReportDto.cs b/CompanyManagment.App.Contracts/SmsResult/Dto/SmsReportDto.cs index 445ed2b0..9a1fc20a 100644 --- a/CompanyManagment.App.Contracts/SmsResult/Dto/SmsReportDto.cs +++ b/CompanyManagment.App.Contracts/SmsResult/Dto/SmsReportDto.cs @@ -9,6 +9,11 @@ public class SmsReportDto /// public string SentDate { get; set; } + /// + /// نوع پیامک + /// + public string TypeOfSms { get; set; } + } diff --git a/CompanyManagment.App.Contracts/SmsResult/ISmsResultApplication.cs b/CompanyManagment.App.Contracts/SmsResult/ISmsResultApplication.cs index 2c857396..cc8bfc54 100644 --- a/CompanyManagment.App.Contracts/SmsResult/ISmsResultApplication.cs +++ b/CompanyManagment.App.Contracts/SmsResult/ISmsResultApplication.cs @@ -1,4 +1,5 @@ using _0_Framework.Application; +using _0_Framework.Application.Enums; using CompanyManagment.App.Contracts.SmsResult.Dto; using System; using System.Collections.Generic; @@ -24,8 +25,9 @@ public interface ISmsResultApplication /// /// /// + /// /// - Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date); + Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date, string typeOfSmsSetting); #endregion diff --git a/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs b/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs index 49fdc4e8..1da9deb4 100644 --- a/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs +++ b/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs @@ -75,4 +75,45 @@ public interface ISmsSettingApplication /// /// Task InstantSendBlockSms(List command); + + + #region ForApi + + /// + /// دریافت لیست پیامک های خودکار بر اساس نوع آن + /// Api + /// + /// + /// + Task> GetSmsSettingList(TypeOfSmsSetting typeOfSmsSetting); + + /// + /// دریافت اطلاعات تنظیمات پیامک جهت ویرایش + /// + /// + /// + Task GetSmsSettingDataToEdit(long id); + + /// + /// ویرایش تنظیمات پیامک + /// + /// + /// + Task EditSmsSetting(SmsSettingDto command); + + /// + /// دریافت لیست ارسال آنی + /// + /// + Task> GetInstantReminderSmsListData(TypeOfSmsSetting typeOfSmsSetting); + + /// + /// ارسال پیامک آنی + /// + /// + /// + /// + Task InstantSmsSendApi(TypeOfSmsSetting typeOfSmsSetting, List phoneNumbers); + + #endregion } \ No newline at end of file diff --git a/CompanyManagment.Application/RollCallApplication.cs b/CompanyManagment.Application/RollCallApplication.cs index e73e4c3e..e618c3b0 100644 --- a/CompanyManagment.Application/RollCallApplication.cs +++ b/CompanyManagment.Application/RollCallApplication.cs @@ -447,8 +447,7 @@ public class RollCallApplication : IRollCallApplication return operation.Failed("کارمند در بازه انتخاب شده مرخصی ساعتی دارد"); } - if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.StartDate.Value.Date >= y.StartDateGr.Date && x.EndDate.Value.Date <= y.EndDateGr.Date))) - return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); + @@ -458,7 +457,10 @@ public class RollCallApplication : IRollCallApplication _rollCallDomainService.GetEmployeeShiftDateByRollCallStartDate(command.WorkshopId, command.EmployeeId, x.StartDate!.Value,x.EndDate.Value); }); - + if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.ShiftDate.Date >= y.StartDateGr.Date && x.ShiftDate.Date <= y.EndDateGr.Date))) + return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); + + if (newRollCallDates.Any(x => x.ShiftDate.Date != date.Date)) { return operation.Failed("حضور غیاب در حال ویرایش را نمیتوانید از تاریخ شیفت عقب تر یا جلو تر ببرید"); @@ -487,8 +489,8 @@ public class RollCallApplication : IRollCallApplication - if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.StartDate.Value.Date >= y.StartDateGr.Date - && x.EndDate.Value.Date <= y.EndDateGr.Date))) + if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.ShiftDate.Date >= y.StartDateGr.Date + && x.ShiftDate.Date <= y.EndDateGr.Date))) return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); @@ -632,9 +634,6 @@ public class RollCallApplication : IRollCallApplication return operation.Failed("کارمند در بازه انتخاب شده مرخصی ساعتی دارد"); } - if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.StartDate.Value.Date >= y.StartDateGr.Date && x.EndDate.Value.Date <= y.EndDateGr.Date))) - return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); - newRollCallDates.ForEach(x => { @@ -642,6 +641,11 @@ public class RollCallApplication : IRollCallApplication _rollCallDomainService.GetEmployeeShiftDateByRollCallStartDate(command.WorkshopId, command.EmployeeId, x.StartDate!.Value,x.EndDate.Value); }); + + if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.ShiftDate.Date >= y.StartDateGr.Date && x.ShiftDate.Date <= y.EndDateGr.Date))) + return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); + + if (newRollCallDates.Any(x => x.ShiftDate.Date != date.Date)) { return operation.Failed("حضور غیاب در حال ویرایش را نمیتوانید از تاریخ شیفت عقب تر یا جلو تر ببرید"); @@ -664,7 +668,7 @@ public class RollCallApplication : IRollCallApplication && (y.StartDate.Value.Date <= x.ContractEndGr.Date)))) return operation.Failed("برای بازه های وارد شده فیش حقوقی ثبت شده است"); - if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.StartDate.Value.Date >= y.StartDateGr.Date && x.EndDate.Value.Date <= y.EndDateGr.Date))) + if (newRollCallDates == null || !newRollCallDates.All(x => employeeStatuses.Any(y => x.ShiftDate.Date >= y.StartDateGr.Date && x.ShiftDate.Date <= y.EndDateGr.Date))) return operation.Failed("کارمند در بازه وارد شده غیر فعال است"); var currentDayRollCall = employeeRollCalls.FirstOrDefault(x => x.EndDate == null); diff --git a/CompanyManagment.Application/SmsResultApplication.cs b/CompanyManagment.Application/SmsResultApplication.cs index 2c94d837..76f7b50c 100644 --- a/CompanyManagment.Application/SmsResultApplication.cs +++ b/CompanyManagment.Application/SmsResultApplication.cs @@ -1,20 +1,26 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using _0_Framework.Application; +using _0_Framework.Application; +using _0_Framework.Application.Enums; +using _0_Framework.Application.Sms; using Company.Domain.SmsResultAgg; using CompanyManagment.App.Contracts.SmsResult; using CompanyManagment.App.Contracts.SmsResult.Dto; +using CompanyManagment.EFCore.Services; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using SmsResult = Company.Domain.SmsResultAgg.SmsResult; namespace CompanyManagment.Application; public class SmsResultApplication : ISmsResultApplication { private readonly ISmsResultRepository _smsResultRepository; + private readonly ISmsService _smsService; - public SmsResultApplication(ISmsResultRepository smsResultRepository) + public SmsResultApplication(ISmsResultRepository smsResultRepository, ISmsService smsService) { _smsResultRepository = smsResultRepository; + _smsService = smsService; } @@ -25,9 +31,9 @@ public class SmsResultApplication : ISmsResultApplication return await _smsResultRepository.GetSmsReportList(searchModel); } - public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date) + public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date, string typeOfSmsSetting) { - return await _smsResultRepository.GetSmsReportExpandList(searchModel, date); + return await _smsResultRepository.GetSmsReportExpandList(searchModel, date, typeOfSmsSetting); } #endregion @@ -67,4 +73,6 @@ public class SmsResultApplication : ISmsResultApplication }).ToList(); return result; } + + } \ No newline at end of file diff --git a/CompanyManagment.Application/SmsSettingApplication.cs b/CompanyManagment.Application/SmsSettingApplication.cs index 203a9e23..6b1d5651 100644 --- a/CompanyManagment.Application/SmsSettingApplication.cs +++ b/CompanyManagment.Application/SmsSettingApplication.cs @@ -9,6 +9,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; namespace CompanyManagment.Application; @@ -17,12 +19,15 @@ public class SmsSettingApplication : ISmsSettingApplication private readonly ISmsSettingsRepository _smsSettingsRepository; private readonly IInstitutionContractRepository _institutionContractRepository; private readonly IInstitutionContractSmsServiceRepository _institutionContractSmsServiceRepository; + private readonly IHostEnvironment _hostEnvironment; - public SmsSettingApplication(ISmsSettingsRepository smsSettingsRepository, IInstitutionContractRepository institutionContractRepository, IInstitutionContractSmsServiceRepository institutionContractSmsServiceRepository) + public SmsSettingApplication(ISmsSettingsRepository smsSettingsRepository, IInstitutionContractRepository institutionContractRepository, IInstitutionContractSmsServiceRepository institutionContractSmsServiceRepository, IHostEnvironment hostEnvironment) { _smsSettingsRepository = smsSettingsRepository; _institutionContractRepository = institutionContractRepository; _institutionContractSmsServiceRepository = institutionContractSmsServiceRepository; + _hostEnvironment = hostEnvironment; + } @@ -131,6 +136,12 @@ public class SmsSettingApplication : ISmsSettingApplication public async Task InstantSendReminderSms(List command) { var op = new OperationResult(); + if (_hostEnvironment.IsDevelopment()) + { + + return op.Failed(" در محیط توسعه امکان ارسال وجود ندارد "); + + } string typeOfSms = "یادآور بدهی ماهانه"; string sendMessStart = "شروع یادآور آنی"; string sendMessEnd = "پایان یادآور آنی"; @@ -151,6 +162,13 @@ public class SmsSettingApplication : ISmsSettingApplication public async Task InstantSendBlockSms(List command) { var op = new OperationResult(); + + if (_hostEnvironment.IsDevelopment()) + { + + return op.Failed(" در محیط توسعه امکان ارسال وجود ندارد "); + + } string typeOfSms = "اعلام مسدودی طرف حساب"; string sendMessStart = "شروع مسدودی آنی"; string sendMessEnd = "پایان مسدودی آنی "; @@ -165,4 +183,166 @@ public class SmsSettingApplication : ISmsSettingApplication return op.Failed("موردی انتخاب نشده است"); } } + + #region ForApi + + /// + /// دریافت لیست پیامک های خودکار بر اساس نوع آن + /// Api + /// + /// + /// + public async Task> GetSmsSettingList(TypeOfSmsSetting typeOfSmsSetting) + { + return await _smsSettingsRepository.GetSmsSettingList(typeOfSmsSetting); + } + + + public async Task GetSmsSettingDataToEdit(long id) + { + return await _smsSettingsRepository.GetSmsSettingDataToEdit(id); + } + + + public async Task EditSmsSetting(SmsSettingDto command) + { + var op = new OperationResult(); + var editSmsSetting = _smsSettingsRepository.Get(command.Id); + var timeSpan = new TimeSpan(); + if (string.IsNullOrWhiteSpace(command.TimeOfDayDisplay)) + return op.Failed("ساعت وارد نشده است"); + + try + { + timeSpan = TimeSpan.ParseExact(command.TimeOfDayDisplay, @"hh\:mm", null); + } + catch (Exception e) + { + return op.Failed("فرمت ساعت اشتباه است"); + } + + if (command.DayOfMonth < 1 || command.DayOfMonth > 31) + { + return op.Failed("عدد روز می بایست بین 1 تا 31 باشد"); + } + + if (_smsSettingsRepository.Exists(x => x.DayOfMonth == command.DayOfMonth && x.TimeOfDay == timeSpan && x.TypeOfSmsSetting == editSmsSetting.TypeOfSmsSetting && x.id != command.Id)) + return op.Failed("رکورد ایجاد شده تکراری است"); + + + editSmsSetting.Edit(command.DayOfMonth, timeSpan); + await _smsSettingsRepository.SaveChangesAsync(); + + return op.Succcedded(); + } + + + public async Task> GetInstantReminderSmsListData(TypeOfSmsSetting typeOfSmsSetting) + { + var result = new List(); + + + if (typeOfSmsSetting == TypeOfSmsSetting.InstitutionContractDebtReminder) + { + var data = await _institutionContractSmsServiceRepository.GetSmsListData(DateTime.Now, TypeOfSmsSetting.InstitutionContractDebtReminder); + + if (data.Any()) + { + result = data.GroupBy(x => x.PartyName).Select(m => new InstantReminderSendSms() + { + FullName = m.Key, + Amount = m.Select(c => c.Amount).First(), + InstantReminderSmsList = m.Select(c => new InstantReminderSmsList() + { + PhoneNumber = c.PhoneNumber, + }).ToList() + + + }).ToList(); + } + } + + if (typeOfSmsSetting == TypeOfSmsSetting.BlockContractingParty) + { + var data = await _institutionContractSmsServiceRepository.GetBlockListData(DateTime.Now); + + if (data.Any()) + { + result = data.GroupBy(x => x.PartyName).Select(m => new InstantReminderSendSms() + { + FullName = m.Key, + Amount = m.Select(c => c.Amount).First(), + InstantReminderSmsList = m.Select(c => new InstantReminderSmsList() + { + PhoneNumber = c.PhoneNumber, + }).ToList() + + + }).ToList(); + } + } + + return result; + } + + public async Task InstantSmsSendApi(TypeOfSmsSetting typeOfSmsSetting, List phoneNumbers) + { + + var op = new OperationResult(); + if (_hostEnvironment.IsDevelopment()) + { + var str = ""; + foreach (var item in phoneNumbers) + { + str += $" {item}, "; + } + return op.Failed(" در محیط توسعه امکان ارسال وجود ندارد " + " لیست ارسال شما " + str); + + } + if (typeOfSmsSetting == TypeOfSmsSetting.InstitutionContractDebtReminder) + { + if (phoneNumbers.Any()) + { + var data = await _institutionContractSmsServiceRepository.GetSmsListData(DateTime.Now, TypeOfSmsSetting.InstitutionContractDebtReminder); + + if (data.Any()) + { + phoneNumbers = phoneNumbers.Where(x => x.Length == 11).ToList(); + var sendItems = data.Where(x => phoneNumbers.Contains(x.PhoneNumber)).ToList(); + var res = await InstantSendReminderSms(sendItems); + return res; + + } + + return op.Succcedded(); + } + + return op.Failed("موردی انتخاب نشده است"); + + } + + if (typeOfSmsSetting == TypeOfSmsSetting.BlockContractingParty) + { + if (phoneNumbers.Any()) + { + var data = await _institutionContractSmsServiceRepository.GetBlockListData(DateTime.Now); + + if (data.Any()) + { + phoneNumbers = phoneNumbers.Where(x => x.Length == 11).ToList(); + var sendItems = data.Where(x => phoneNumbers.Contains(x.PhoneNumber)).ToList(); + var res = await InstantSendBlockSms(sendItems); + return res; + } + return op.Succcedded(); + } + return op.Failed("موردی انتخاب نشده است"); + } + + + + + return op.Failed("خطای انتخاب نوع ارسال"); + } + #endregion } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index b505dced..39c98954 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -2269,7 +2269,8 @@ public class InstitutionContractRepository : RepositoryBase x.WorkshopId.Value)??[]; + var workshopIds = prevInstitutionContracts.WorkshopGroup?.CurrentWorkshops?.Select(x => x.WorkshopId.Value) ?? + []; var workshopsNotInInstitution = employerWorkshopIds.Where(x => !workshopIds.Contains(x)).ToList(); @@ -2317,7 +2318,7 @@ public class InstitutionContractRepository : RepositoryBase workshopsNotInInstitution.Contains(x.WorkshopId) && x.StartWorkDate <= DateTime.Now && x.LeftWorkDate >= DateTime.Now) @@ -2959,8 +2960,11 @@ public class InstitutionContractRepository : RepositoryBase x.Id == request.TempId) .FirstOrDefaultAsync(); // creationTemp.SetContractingPartyInfo(request.LegalType,request.RealParty,request.LegalParty); - + bool tempCreated = false; if (creationTemp == null) { - throw new BadRequestException("دیتای درخواست شده نامعتبر است"); + creationTemp = new InstitutionContractCreationTemp(); + await _institutionContractCreationTemp.InsertOneAsync(creationTemp); } List workshopDetails = []; @@ -4460,7 +4465,8 @@ public class InstitutionContractRepository : RepositoryBase x.WorkshopServicesAmount).ToMoney(), - WorkshopTemps = workshopDetails + WorkshopTemps = workshopDetails, + TempId = creationTemp.Id }; return res; } @@ -5107,9 +5113,11 @@ public class InstitutionContractRepository : RepositoryBase var service = _rollCallServiceRepository.GetAllServiceByWorkshopId(workshopId); + //اگر سرویس حضور غیاب نداشت if (!service.Any(x => x.StartService.Date <= contractStart.Date && x.EndService.Date >= contractEnd.Date)) return false; //var rollCallEmployee = GetByEmployeeIdAndWorkshopId(employeeId, workshopId); //if (rollCallEmployee == null) // return false; - var rollCallEmployee = _context.RollCallEmployees - .Where(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId) - .Include(x => x.EmployeesStatus); - if (!rollCallEmployee.Any()) + var rollCallEmployee = _context.RollCallEmployees.Include(xs => xs.EmployeesStatus) + .FirstOrDefault(x => x.EmployeeId == employeeId && x.WorkshopId == workshopId); + //اگر تنظیمات حضور غیاب نداشت + if (rollCallEmployee == null) + return false; + + //اگر استاتوس نداشت + if (!rollCallEmployee.EmployeesStatus.Any()) return false; - var a = rollCallEmployee.Any(x => x.EmployeesStatus.Any(s => - (s.StartDate <= contractStart.Date && s.EndDate.Date >= contractEnd.Date) || - (s.StartDate.Date <= contractStart.Date && s.EndDate.Date > contractStart.Date))); - //var result = _employeeRollCallStatusRepository.w(x => x.RollCallEmployeeId == rollCallEmployee.Id && - // (x.StartDate.Date <= contractStart.Date && x.EndDate.Date >= contractEnd.Date) || - // (x.StartDate.Date <= contractStart.Date && x.EndDate.Date > contractStart.Date)); - return a; + var leftWork = + _context.LeftWorkList.FirstOrDefault(x => + x.StartWorkDate <= contractEnd.Date && x.LeftWorkDate > contractStart); + if (leftWork == null) + return false; + + var status = rollCallEmployee.EmployeesStatus.FirstOrDefault(s => + (s.StartDate <= contractStart.Date && s.EndDate.Date >= contractEnd.Date)); + //اگر استاتوس کامل پوشش داد + if (status != null) + return true; + + + status = rollCallEmployee.EmployeesStatus.FirstOrDefault(s => + (s.StartDate.Date <= contractStart.Date && s.EndDate.Date > contractStart.Date && + s.EndDate.Date < contractEnd.Date)); + //اگر قبل از پایان فیس استاتوس قطع شده ولی ترک کار داره + if (status != null && leftWork.HasLeft) + return true; + + + return false; } public List GetByWorkshopId(long workshopId) { diff --git a/CompanyManagment.EFCore/Repository/SmsResultRepository.cs b/CompanyManagment.EFCore/Repository/SmsResultRepository.cs index 18ccbe1d..ee557614 100644 --- a/CompanyManagment.EFCore/Repository/SmsResultRepository.cs +++ b/CompanyManagment.EFCore/Repository/SmsResultRepository.cs @@ -77,6 +77,9 @@ public class SmsResultRepository : RepositoryBase, ISmsResultRe case TypeOfSmsSetting.SendInstitutionContractConfirmationCode: typeOfSms = "کد تاییدیه قرارداد مالی"; break; + case TypeOfSmsSetting.SendInstitutionContractConfirmationLink: + typeOfSms = "لینک تاییدیه ایجاد قرارداد مالی"; + break; case TypeOfSmsSetting.TaskReminder: typeOfSms = "یادآور وظایف"; break; @@ -147,7 +150,7 @@ public class SmsResultRepository : RepositoryBase, ISmsResultRe // مرحله 2: گروه‌بندی و انتخاب آخرین رکورد هر روز روی Client var grouped = rawQuery - .GroupBy(x => x.DateOnly) + .GroupBy(x => (x.DateOnly, x.TypeOfSms)) .Select(g => g.OrderByDescending(x => x.CreationDate).First()) .OrderByDescending(x => x.CreationDate) .ToList(); @@ -155,15 +158,16 @@ public class SmsResultRepository : RepositoryBase, ISmsResultRe // مرحله 3: تبدیل به DTO و ToFarsi var result = grouped.Select(x => new SmsReportDto { - SentDate = x.CreationDate.ToFarsi() + SentDate = x.CreationDate.ToFarsi(), + TypeOfSms = x.TypeOfSms }).ToList(); return result; } - public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date) + public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date, string typeOfSmsSetting) { - if(string.IsNullOrWhiteSpace(date)) + if(string.IsNullOrWhiteSpace(date) || string.IsNullOrWhiteSpace(typeOfSmsSetting)) return new List(); if (date.TryToGeorgianDateTime(out var searchDate) == false) @@ -198,41 +202,12 @@ public class SmsResultRepository : RepositoryBase, ISmsResultRe query = query.Where(x => x.Mobile.Contains(searchModel.Mobile)).ToList(); } - if (searchModel.TypeOfSms != TypeOfSmsSetting.All && searchModel.TypeOfSms != TypeOfSmsSetting.Warning) - { - var typeOfSms = "All"; - switch (searchModel.TypeOfSms) - { - case TypeOfSmsSetting.InstitutionContractDebtReminder: - typeOfSms = "یادآور بدهی ماهانه"; - break; - case TypeOfSmsSetting.MonthlyInstitutionContract: - typeOfSms = "صورت حساب ماهانه"; - break; - case TypeOfSmsSetting.BlockContractingParty: - typeOfSms = "اعلام مسدودی طرف حساب"; - break; - case TypeOfSmsSetting.LegalAction: - typeOfSms = "اقدام قضایی"; - break; - case TypeOfSmsSetting.InstitutionContractConfirm: - typeOfSms = "یادآور تایید قرارداد مالی"; - break; - case TypeOfSmsSetting.SendInstitutionContractConfirmationCode: - typeOfSms = "کد تاییدیه قرارداد مالی"; - break; - case TypeOfSmsSetting.TaskReminder: - typeOfSms = "یادآور وظایف"; - break; - } - query = query.Where(x => x.TypeOfSms == typeOfSms).ToList(); - } - - if (searchModel.TypeOfSms == TypeOfSmsSetting.Warning) + if (typeOfSmsSetting.Contains("هشدار")) { query = query.Where(x => x.TypeOfSms.Contains("هشدار")).ToList(); } + query = query.Where(x => x.TypeOfSms == typeOfSmsSetting).ToList(); if (searchModel.SendStatus != SendStatus.All) { diff --git a/CompanyManagment.EFCore/Repository/SmsSettingsRepository.cs b/CompanyManagment.EFCore/Repository/SmsSettingsRepository.cs index d0922b29..da3c11b3 100644 --- a/CompanyManagment.EFCore/Repository/SmsSettingsRepository.cs +++ b/CompanyManagment.EFCore/Repository/SmsSettingsRepository.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using _0_Framework.Application.Enums; using _0_Framework.InfraStructure; @@ -68,4 +69,48 @@ public class SmsSettingsRepository : RepositoryBase, ISmsSetti _context.SmsSettings.Remove(removeItem); await _context.SaveChangesAsync(); } + + + #region ForApi + /// + /// دریافت لیست پیامک های خودکار بر اساس نوع آن + /// Api + /// + /// + /// + public async Task> GetSmsSettingList(TypeOfSmsSetting typeOfSmsSetting) + { + + var data = await _context.SmsSettings + .Where(x => x.TypeOfSmsSetting == typeOfSmsSetting) + .OrderBy(x => x.DayOfMonth).ThenBy(x => x.TimeOfDay) + .Select(x => + new SmsSettingDto() + { + Id = x.id, + DayOfMonth = x.DayOfMonth, + TimeOfDayDisplay = x.TimeOfDay.ToString(@"hh\:mm") + }).ToListAsync(); + + return data; + } + + public async Task GetSmsSettingDataToEdit(long id) + { + var edit = new SmsSettingDto(); + var getItem = await _context.SmsSettings.FirstOrDefaultAsync(x => x.id == id); + + if (getItem != null) + { + edit.Id = getItem.id; + edit.TimeOfDayDisplay = getItem.TimeOfDay.ToString(@"hh\:mm"); + edit.DayOfMonth = getItem.DayOfMonth; + + } + + return edit; + } + + + #endregion } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Services/SmsService.cs b/CompanyManagment.EFCore/Services/SmsService.cs index 11ea7adb..d73ac87f 100644 --- a/CompanyManagment.EFCore/Services/SmsService.cs +++ b/CompanyManagment.EFCore/Services/SmsService.cs @@ -205,6 +205,26 @@ public class SmsService : ISmsService }; return appendData; } + + public async Task GetSmsDetailsByMessageId(int messId, string fullName) + { + + SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa"); + var response = await smsIr.GetReportAsync(messId); + MessageReportResult messages = response.Data; + + var appendData = new SmsDetailsDto() + { + Mobile = messages.Mobile, + MessageText = messages.MessageText, + SendUnixTime = UnixTimeStampToDateTime(messages.SendDateTime), + DeliveryState = DeliveryStatus(messages.DeliveryState), + DeliveryUnixTime = UnixTimeStampToDateTime(messages.DeliveryDateTime), + DeliveryColor = DeliveryColorStatus(messages.DeliveryState), + FullName = fullName + }; + return appendData; + } public async Task> GetApiResult(string startDate, string endDate) { diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs deleted file mode 100644 index 1373f8a6..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs +++ /dev/null @@ -1,16 +0,0 @@ -using GozareshgirProgramManager.Application._Common.Interfaces; -using GozareshgirProgramManager.Domain.ProjectAgg.Enums; - -namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase; - -/// -/// Command to add a task to an existing phase -/// -public record AddTaskToPhaseCommand( - Guid PhaseId, - string Name, - string? Description = null, - ProjectTaskPriority Priority = ProjectTaskPriority.Medium, - int OrderIndex = 0, - DateTime? DueDate = null -) : IBaseCommand; diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs deleted file mode 100644 index 360811a7..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using GozareshgirProgramManager.Application._Common.Interfaces; -using GozareshgirProgramManager.Application._Common.Models; -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; -using MediatR; - -namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase; - -public class AddTaskToPhaseCommandHandler : IRequestHandler -{ - private readonly IProjectPhaseRepository _phaseRepository; - private readonly IUnitOfWork _unitOfWork; - - public AddTaskToPhaseCommandHandler( - IProjectPhaseRepository phaseRepository, - IUnitOfWork unitOfWork) - { - _phaseRepository = phaseRepository; - _unitOfWork = unitOfWork; - } - - public async Task Handle(AddTaskToPhaseCommand request, CancellationToken cancellationToken) - { - try - { - // Get phase - var phase = await _phaseRepository.GetByIdAsync(request.PhaseId); - if (phase == null) - { - return OperationResult.NotFound("فاز یافت نشد"); - } - - // Add task - var task = phase.AddTask(request.Name, request.Description); - task.SetPriority(request.Priority); - task.SetOrderIndex(request.OrderIndex); - - if (request.DueDate.HasValue) - { - task.SetDates(dueDate: request.DueDate); - } - - // Save changes - await _unitOfWork.SaveChangesAsync(cancellationToken); - - return OperationResult.Success(); - } - catch (Exception ex) - { - return OperationResult.Failure($"خطا در افزودن تسک: {ex.Message}"); - } - } -} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs index 475e7aab..547f09bb 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs @@ -4,4 +4,5 @@ using GozareshgirProgramManager.Domain.ProjectAgg.Enums; namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; public record CreateProjectCommand(string Name,ProjectHierarchyLevel Level, + ProjectTaskPriority? Priority, Guid? ParentId):IBaseCommand; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs index 1ba61509..ef4a4292 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs @@ -16,7 +16,8 @@ public class CreateProjectCommandHandler : IBaseCommandHandlerx.Id == request.ParentId.Value)) + + if (!_projectRepository.Exists(x => x.Id == request.ParentId.Value)) { throw new BadRequestException("والد پروژه یافت نشد"); } @@ -69,14 +70,15 @@ public class CreateProjectCommandHandler : IBaseCommandHandlerx.Id == request.ParentId.Value)) + + if (!_projectPhaseRepository.Exists(x => x.Id == request.ParentId.Value)) { throw new BadRequestException("والد پروژه یافت نشد"); } - var projectTask = new ProjectTask(request.Name, request.ParentId.Value); + var priority = request.Priority ?? ProjectTaskPriority.Low; + + var projectTask = new ProjectTask(request.Name, request.ParentId.Value, priority); await _projectTaskRepository.CreateAsync(projectTask); } -} - \ No newline at end of file +} \ No newline at end of file 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 91a82c28..9157ec1d 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 @@ -10,8 +10,10 @@ public class GetProjectItemDto 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; } + + public TimeSpan TotalTime { get; init; } + + public TimeSpan RemainingTime { get; init; } public AssignmentStatus Front { get; set; } public AssignmentStatus Backend { get; set; } public AssignmentStatus Design { get; set; } 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 a982caf3..9d184312 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 @@ -16,7 +16,8 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler> Handle(GetProjectsListQuery request, CancellationToken cancellationToken) + public async Task> Handle(GetProjectsListQuery request, + CancellationToken cancellationToken) { var projects = new List(); var phases = new List(); @@ -51,13 +52,14 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler(); } + var entities = await query .OrderByDescending(p => p.CreationDate) .ToListAsync(cancellationToken); var result = new List(); foreach (var project in entities) { - var (percentage, totalTime) = await CalculateProjectPercentage(project, cancellationToken); + var (percentage, totalTime,remainingTime) = await CalculateProjectPercentage(project, cancellationToken); result.Add(new GetProjectDto { Id = project.Id, @@ -65,10 +67,12 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler x.Percentage).ToList(); return result; } @@ -79,13 +83,14 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler x.ProjectId == parentId); } + var entities = await query .OrderByDescending(p => p.CreationDate) .ToListAsync(cancellationToken); var result = new List(); foreach (var phase in entities) { - var (percentage, totalTime) = await CalculatePhasePercentage(phase, cancellationToken); + var (percentage, totalTime,remainingTime) = await CalculatePhasePercentage(phase, cancellationToken); result.Add(new GetPhaseDto { Id = phase.Id, @@ -93,10 +98,12 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler x.Percentage).ToList(); + return result; } @@ -107,6 +114,7 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler x.PhaseId == parentId); } + var entities = await query .OrderByDescending(t => t.CreationDate) .ToListAsync(cancellationToken); @@ -118,7 +126,7 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler s.Activities) .Include(s => s.Skill) @@ -140,13 +148,12 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler 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 برمی‌گردانیم @@ -184,18 +191,20 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler x.Percentage).ToList(); + return result; } - private async Task SetSkillFlags(List items, CancellationToken cancellationToken) where TItem : GetProjectItemDto + private async Task SetSkillFlags(List items, CancellationToken cancellationToken) + where TItem : GetProjectItemDto { if (!items.Any()) return; @@ -213,7 +222,8 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler(List items, List projectIds, CancellationToken cancellationToken) where TItem : GetProjectItemDto + private async Task SetSkillFlagsForProjects(List items, List projectIds, + CancellationToken cancellationToken) where TItem : GetProjectItemDto { // For projects: gather all phases, then tasks, then sections var phases = await _context.ProjectPhases @@ -243,7 +253,8 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler(List items, List phaseIds, CancellationToken cancellationToken) where TItem : GetProjectItemDto + private async Task SetSkillFlagsForPhases(List items, List phaseIds, + CancellationToken cancellationToken) where TItem : GetProjectItemDto { // For phases: gather tasks, then sections var tasks = await _context.ProjectTasks @@ -269,68 +280,81 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler CalculateProjectPercentage(Project project, CancellationToken cancellationToken) + private async Task<(int Percentage, TimeSpan TotalTime,TimeSpan RemainingTime)> 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); + return (0, TimeSpan.Zero,TimeSpan.Zero); var phasePercentages = new List(); var totalTime = TimeSpan.Zero; + var remainingTime = TimeSpan.Zero; foreach (var phase in phases) { - var (phasePercentage, phaseTime) = await CalculatePhasePercentage(phase, cancellationToken); + var (phasePercentage, phaseTime,phaseRemainingTime) = await CalculatePhasePercentage(phase, cancellationToken); phasePercentages.Add(phasePercentage); totalTime += phaseTime; + remainingTime += phaseRemainingTime; } + var averagePercentage = phasePercentages.Any() ? (int)phasePercentages.Average() : 0; - return (averagePercentage, totalTime); + return (averagePercentage, totalTime,remainingTime); } - private async Task<(int Percentage, TimeSpan TotalTime)> CalculatePhasePercentage(ProjectPhase phase, CancellationToken cancellationToken) + private async Task<(int Percentage, TimeSpan TotalTime,TimeSpan RemainingTime)> 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); + return (0, TimeSpan.Zero,TimeSpan.Zero); var taskPercentages = new List(); var totalTime = TimeSpan.Zero; + var remainingTime = TimeSpan.Zero; foreach (var task in tasks) { - var (taskPercentage, taskTime) = await CalculateTaskPercentage(task, cancellationToken); + var (taskPercentage, taskTime,taskRemainingTime) = await CalculateTaskPercentage(task, cancellationToken); taskPercentages.Add(taskPercentage); totalTime += taskTime; + remainingTime += taskRemainingTime; } + var averagePercentage = taskPercentages.Any() ? (int)taskPercentages.Average() : 0; - return (averagePercentage, totalTime); + return (averagePercentage, totalTime,remainingTime); } - private async Task<(int Percentage, TimeSpan TotalTime)> CalculateTaskPercentage(ProjectTask task, CancellationToken cancellationToken) + private async Task<(int Percentage, TimeSpan TotalTime, TimeSpan RemainingTime)> CalculateTaskPercentage( + ProjectTask task, CancellationToken cancellationToken) { var sections = await _context.TaskSections .Include(s => s.Activities) - .Include(x=>x.AdditionalTimes) + .Include(x => x.AdditionalTimes) .Where(s => s.TaskId == task.Id) .ToListAsync(cancellationToken); if (!sections.Any()) - return (0, TimeSpan.Zero); + return (0, TimeSpan.Zero, TimeSpan.Zero); var sectionPercentages = new List(); var totalTime = TimeSpan.Zero; + var spentTime = TimeSpan.Zero; foreach (var section in sections) { var (sectionPercentage, sectionTime) = CalculateSectionPercentage(section); + var sectionSpent = TimeSpan.FromTicks(section.Activities.Sum(x => x.GetTimeSpent().Ticks)); sectionPercentages.Add(sectionPercentage); totalTime += sectionTime; + spentTime += sectionSpent; } + var remainingTime = totalTime - spentTime; var averagePercentage = sectionPercentages.Any() ? (int)sectionPercentages.Average() : 0; - return (averagePercentage, totalTime); + return (averagePercentage, totalTime, remainingTime); } private static (int Percentage, TimeSpan TotalTime) CalculateSectionPercentage(TaskSection section) { - return ((int)section.GetProgressPercentage(),section.FinalEstimatedHours); + return ((int)section.GetProgressPercentage(), section.FinalEstimatedHours); } private static AssignmentStatus GetAssignmentStatus(TaskSection? section) @@ -341,7 +365,7 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler 0; - + // بررسی وجود time (InitialEstimatedHours بزرگتر از صفر باشد) bool hasTime = section.InitialEstimatedHours > TimeSpan.Zero; @@ -356,5 +380,4 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler> { public long? UserId { get; set; } - public string? SearchText { get; set; } + public string? ProjectName { get; set; } public TaskSectionStatus? Status { get; set; } } \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs index a5b171f4..8eb4861f 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 @@ -46,11 +46,11 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.CurrentAssignedUserId == request.UserId); } - if (!string.IsNullOrWhiteSpace(request.SearchText)) + if (!string.IsNullOrWhiteSpace(request.ProjectName)) { - queryable = queryable.Where(x=>x.Task.Name.Contains(request.SearchText) - || x.Task.Phase.Name.Contains(request.SearchText) - || x.Task.Phase.Project.Name.Contains(request.SearchText)); + queryable = queryable.Where(x=>x.Task.Name.Contains(request.ProjectName) + || x.Task.Phase.Name.Contains(request.ProjectName) + || x.Task.Phase.Project.Name.Contains(request.ProjectName)); } var data = await queryable.ToListAsync(cancellationToken); @@ -70,6 +70,9 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.CurrentAssignedUserId == currentUserId) .ThenByDescending(x=>x.Task.Priority) .ThenBy(x => GetStatusOrder(x.Status)) + .ThenBy(x=>x.Task.Phase.ProjectId) + .ThenBy(x=>x.Task.PhaseId) + .ThenBy(x=>x.TaskId) .Select(x => { // محاسبه یکبار برای هر Activity و Cache کردن نتیجه 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 245d8b39..186f47b2 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 @@ -28,26 +28,25 @@ public class SendMessageCommandHandler : IBaseCommandHandler> Handle(SendMessageCommand request, CancellationToken cancellationToken) + public async Task> Handle(SendMessageCommand request, + CancellationToken cancellationToken) { var currentUserId = _authHelper.GetCurrentUserId() ?? throw new UnAuthorizedException("کاربر احراز هویت نشده است"); @@ -57,75 +56,21 @@ public class SendMessageCommandHandler : IBaseCommandHandler.NotFound("تسک یافت نشد"); } - + Guid? uploadedFileId = null; if (request.File != null) { - if (request.File.Length == 0) - { - return OperationResult.ValidationError("فایل خالی است"); - } - - const long maxFileSize = 100 * 1024 * 1024; - if (request.File.Length > maxFileSize) - { - return OperationResult.ValidationError("حجم فایل بیش از حد مجاز است (حداکثر 100MB)"); - } - - var fileType = DetectFileType(request.File.ContentType, Path.GetExtension(request.File.FileName)); - - var uploadedFile = new UploadedFile( - originalFileName: request.File.FileName, - fileSizeBytes: request.File.Length, - mimeType: request.File.ContentType, - fileType: fileType, - category: FileCategory.TaskChatMessage, - uploadedByUserId: currentUserId, - storageProvider: StorageProvider.LocalFileSystem + var uploadedFile = await _fileUploadService.UploadFileAsync + ( + request.File, + FileCategory.TaskChatMessage, + currentUserId ); - - await _fileRepository.AddAsync(uploadedFile); - await _fileRepository.SaveChangesAsync(); - - try + if (!uploadedFile.IsSuccess) { - using var stream = request.File.OpenReadStream(); - var uploadResult = await _fileStorageService.UploadAsync( - stream, - uploadedFile.UniqueFileName, - "TaskChatMessage" - ); - - uploadedFile.CompleteUpload(uploadResult.StoragePath, uploadResult.StorageUrl); - - if (fileType == FileType.Image) - { - var dimensions = await _thumbnailService.GetImageDimensionsAsync(uploadResult.StoragePath); - if (dimensions.HasValue) - { - uploadedFile.SetImageDimensions(dimensions.Value.Width, dimensions.Value.Height); - } - - var thumbnail = await _thumbnailService - .GenerateImageThumbnailAsync(uploadResult.StoragePath, category: "TaskChatMessage"); - if (thumbnail.HasValue) - { - uploadedFile.SetThumbnail(thumbnail.Value.ThumbnailUrl); - } - } - - await _fileRepository.UpdateAsync(uploadedFile); - await _fileRepository.SaveChangesAsync(); - - uploadedFileId = uploadedFile.Id; - } - catch (Exception ex) - { - await _fileRepository.DeleteAsync(uploadedFile); - await _fileRepository.SaveChangesAsync(); - - return OperationResult.ValidationError($"خطا در آپلود فایل: {ex.Message}"); + return OperationResult.Failure(uploadedFile.ErrorMessage ?? "خطا در آپلود فایل"); } + uploadedFileId = uploadedFile.FileId!.Value; } var message = new TaskChatMessage( @@ -209,4 +154,4 @@ public class SendMessageCommandHandler : IBaseCommandHandler +/// سرویس آپلود و مدیریت کامل فایل +/// این سرویس تمام مراحل آپلود، ذخیره، تولید thumbnail و... را انجام می‌دهد +/// +public interface IFileUploadService +{ + /// + /// آپلود فایل با تمام مراحل پردازش + /// + /// فایل برای آپلود + /// دسته‌بندی فایل + /// شناسه کاربر آپلودکننده + /// حداکثر حجم مجاز فایل (پیش‌فرض: 100MB) + /// شناسه فایل آپلود شده یا null در صورت خطا + Task UploadFileAsync( + IFormFile file, + FileCategory category, + long uploadedByUserId, + long maxFileSizeBytes = 100 * 1024 * 1024); + + /// + /// آپلود فایل با Stream + /// + Task UploadFileFromStreamAsync( + Stream fileStream, + string fileName, + string contentType, + FileCategory category, + long uploadedByUserId, + long maxFileSizeBytes = 100 * 1024 * 1024); +} + +/// +/// نتیجه عملیات آپلود فایل +/// +public class FileUploadResult +{ + public bool IsSuccess { get; set; } + public Guid? FileId { get; set; } + public string? ErrorMessage { get; set; } + public string? StorageUrl { get; set; } + public string? ThumbnailUrl { get; set; } + + public static FileUploadResult Success(Guid fileId, string storageUrl, string? thumbnailUrl = null) + { + return new FileUploadResult + { + IsSuccess = true, + FileId = fileId, + StorageUrl = storageUrl, + ThumbnailUrl = thumbnailUrl + }; + } + + public static FileUploadResult Failed(string errorMessage) + { + return new FileUploadResult + { + IsSuccess = false, + ErrorMessage = errorMessage + }; + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs index bd4230c3..7c71e909 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Constants/ProgramManagerPermissionCode.cs @@ -149,6 +149,22 @@ public static class ProgramManagerPermissionCode { public const int Code = 990111; } + + /// + /// اولویت بندی + /// + public static class Priority + { + public const int Code = 990112; + } + + /// + /// ایجاد تسک باگ + /// + public static class CreateBug + { + public const int Code = 990113; + } } #endregion @@ -226,11 +242,26 @@ public static class ProgramManagerPermissionCode { public const int Code = 990208; } + + /// + /// رد با تایید اتمام اجرا + /// + public static class RejectOrApproveTaskComplete + { + public const int Code = 990209; + } + } + + #endregion + + #region Workflow[تب کارپوشه] + public static class Workflow + { + public const int Code = 9903; } #endregion - public static Dictionary GetAllCodes() { var result = new Dictionary(); diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs index 60b98df9..129c5ff4 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs @@ -41,15 +41,7 @@ public class ProjectPhase : ProjectHierarchyNode public ProjectDeployStatus DeployStatus { get; set; } #region Task Management - - public ProjectTask AddTask(string name, string? description = null) - { - var task = new ProjectTask(name, Id, description); - _tasks.Add(task); - AddDomainEvent(new TaskAddedEvent(task.Id, Id, name)); - return task; - } - + public void RemoveTask(Guid taskId) { var task = _tasks.FirstOrDefault(t => t.Id == taskId); diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs index 8c11e2a0..81d0e861 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs @@ -16,11 +16,11 @@ public class ProjectTask : ProjectHierarchyNode _sections = new List(); } - public ProjectTask(string name, Guid phaseId, string? description = null) : base(name, description) + public ProjectTask(string name, Guid phaseId,ProjectTaskPriority priority, string? description = null) : base(name, description) { PhaseId = phaseId; _sections = new List(); - Priority = ProjectTaskPriority.Low; + Priority = priority; AddDomainEvent(new TaskCreatedEvent(Id, phaseId, name)); } diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs index 20618330..cf9ec45e 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -92,6 +92,7 @@ public static class DependencyInjection // File Storage Services services.AddScoped(); services.AddScoped(); + services.AddScoped(); // JWT Settings services.Configure(configuration.GetSection("JwtSettings")); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/FileUploadService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/FileUploadService.cs new file mode 100644 index 00000000..92d439b6 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/FileUploadService.cs @@ -0,0 +1,231 @@ +using GozareshgirProgramManager.Application.Services.FileManagement; +using GozareshgirProgramManager.Domain.FileManagementAgg.Entities; +using GozareshgirProgramManager.Domain.FileManagementAgg.Enums; +using GozareshgirProgramManager.Domain.FileManagementAgg.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; + +namespace GozareshgirProgramManager.Infrastructure.Services.FileManagement; + +/// +/// پیاده‌سازی سرویس آپلود کامل فایل +/// +public class FileUploadService : IFileUploadService +{ + private readonly IUploadedFileRepository _fileRepository; + private readonly IFileStorageService _fileStorageService; + private readonly IThumbnailGeneratorService _thumbnailService; + private readonly ILogger _logger; + + public FileUploadService( + IUploadedFileRepository fileRepository, + IFileStorageService fileStorageService, + IThumbnailGeneratorService thumbnailService, + ILogger logger) + { + _fileRepository = fileRepository; + _fileStorageService = fileStorageService; + _thumbnailService = thumbnailService; + _logger = logger; + } + + public async Task UploadFileAsync( + IFormFile file, + FileCategory category, + long uploadedByUserId, + long maxFileSizeBytes = 100 * 1024 * 1024) + { + try + { + // اعتبارسنجی ورودی + if (file.Length == 0) + { + return FileUploadResult.Failed("فایل خالی است"); + } + + if (file.Length > maxFileSizeBytes) + { + var maxSizeMb = maxFileSizeBytes / (1024 * 1024); + return FileUploadResult.Failed($"حجم فایل بیش از حد مجاز است (حداکثر {maxSizeMb}MB)"); + } + + using var stream = file.OpenReadStream(); + return await UploadFileFromStreamAsync( + stream, + file.FileName, + file.ContentType, + category, + uploadedByUserId, + maxFileSizeBytes); + } + catch (Exception ex) + { + _logger.LogError(ex, "خطا در آپلود فایل {FileName}", file.FileName); + return FileUploadResult.Failed($"خطا در آپلود فایل: {ex.Message}"); + } + } + + public async Task UploadFileFromStreamAsync( + Stream fileStream, + string fileName, + string contentType, + FileCategory category, + long uploadedByUserId, + long maxFileSizeBytes = 100 * 1024 * 1024) + { + UploadedFile? uploadedFile = null; + + try + { + // تشخیص نوع فایل + var fileType = DetectFileType(contentType, Path.GetExtension(fileName)); + + // ایجاد رکورد فایل در دیتابیس + uploadedFile = new UploadedFile( + originalFileName: fileName, + fileSizeBytes: fileStream.Length, + mimeType: contentType, + fileType: fileType, + category: category, + uploadedByUserId: uploadedByUserId, + storageProvider: StorageProvider.LocalFileSystem + ); + + await _fileRepository.AddAsync(uploadedFile); + await _fileRepository.SaveChangesAsync(); + + // آپلود فایل به استوریج + var categoryFolder = category.ToString(); + var uploadResult = await _fileStorageService.UploadAsync( + fileStream, + uploadedFile.UniqueFileName, + categoryFolder + ); + + // به‌روزرسانی اطلاعات آپلود + uploadedFile.CompleteUpload(uploadResult.StoragePath, uploadResult.StorageUrl); + + // پردازش‌های خاص بر اساس نوع فایل + string? thumbnailUrl = null; + if (fileType == FileType.Image) + { + thumbnailUrl = await ProcessImageAsync(uploadedFile, uploadResult.StoragePath, categoryFolder); + } + else if (fileType == FileType.Video) + { + thumbnailUrl = await ProcessVideoAsync(uploadedFile, uploadResult.StoragePath, categoryFolder); + } + + // ذخیره تغییرات نهایی + await _fileRepository.UpdateAsync(uploadedFile); + await _fileRepository.SaveChangesAsync(); + + _logger.LogInformation( + "فایل {FileName} با شناسه {FileId} با موفقیت آپلود شد", + fileName, + uploadedFile.Id); + + return FileUploadResult.Success(uploadedFile.Id, uploadResult.StorageUrl, thumbnailUrl); + } + catch (Exception ex) + { + _logger.LogError(ex, "خطا در آپلود فایل {FileName}", fileName); + + // در صورت خطا، فایل آپلود شده را حذف کنیم + if (uploadedFile != null) + { + try + { + await _fileRepository.DeleteAsync(uploadedFile); + await _fileRepository.SaveChangesAsync(); + } + catch (Exception deleteEx) + { + _logger.LogError(deleteEx, "خطا در حذف فایل ناموفق {FileId}", uploadedFile.Id); + } + } + + return FileUploadResult.Failed($"خطا در آپلود فایل: {ex.Message}"); + } + } + + /// + /// پردازش تصویر (ابعاد و thumbnail) + /// + private async Task ProcessImageAsync(UploadedFile file, string storagePath, string categoryFolder) + { + try + { + // دریافت ابعاد تصویر + var dimensions = await _thumbnailService.GetImageDimensionsAsync(storagePath); + if (dimensions.HasValue) + { + file.SetImageDimensions(dimensions.Value.Width, dimensions.Value.Height); + } + + // تولید thumbnail + var thumbnail = await _thumbnailService.GenerateImageThumbnailAsync( + storagePath, + category: categoryFolder); + + if (thumbnail.HasValue) + { + file.SetThumbnail(thumbnail.Value.ThumbnailUrl); + return thumbnail.Value.ThumbnailUrl; + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "خطا در پردازش تصویر {FileId}", file.Id); + } + + return null; + } + + /// + /// پردازش ویدیو (thumbnail) + /// + private async Task ProcessVideoAsync(UploadedFile file, string storagePath, string categoryFolder) + { + try + { + // تولید thumbnail از ویدیو + var thumbnail = await _thumbnailService.GenerateVideoThumbnailAsync( + storagePath, + category: categoryFolder); + + if (thumbnail.HasValue) + { + file.SetThumbnail(thumbnail.Value.ThumbnailUrl); + return thumbnail.Value.ThumbnailUrl; + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "خطا در پردازش ویدیو {FileId}", file.Id); + } + + return null; + } + + /// + /// تشخیص نوع فایل از روی MIME type و extension + /// + private FileType DetectFileType(string mimeType, string extension) + { + if (mimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) + return FileType.Image; + + if (mimeType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) + return FileType.Video; + + if (mimeType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase)) + return FileType.Audio; + + if (new[] { ".zip", ".rar", ".7z", ".tar", ".gz" }.Contains(extension.ToLower())) + return FileType.Archive; + + return FileType.Document; + } +} + diff --git a/ServiceHost/Areas/Admin/Controllers/SmsReportController.cs b/ServiceHost/Areas/Admin/Controllers/SmsReportController.cs index 254d5d05..5a864bd8 100644 --- a/ServiceHost/Areas/Admin/Controllers/SmsReportController.cs +++ b/ServiceHost/Areas/Admin/Controllers/SmsReportController.cs @@ -1,4 +1,7 @@ -using _0_Framework.Application.Sms; +using _0_Framework.Application; +using _0_Framework.Application.Enums; +using _0_Framework.Application.Sms; +using CompanyManagment.App.Contracts.InstitutionContract; using CompanyManagment.App.Contracts.SmsResult; using CompanyManagment.App.Contracts.SmsResult.Dto; using Microsoft.AspNetCore.Mvc; @@ -9,12 +12,14 @@ namespace ServiceHost.Areas.Admin.Controllers; public class SmsReportController : AdminBaseController { private readonly ISmsResultApplication _smsResultApplication; + private readonly ISmsSettingApplication _smsSettingApplication; private readonly ISmsService _smsService; - public SmsReportController(ISmsResultApplication smsResultApplication, ISmsService smsService) + public SmsReportController(ISmsResultApplication smsResultApplication, ISmsService smsService, ISmsSettingApplication smsSettingApplication) { _smsResultApplication = smsResultApplication; _smsService = smsService; + _smsSettingApplication = smsSettingApplication; } /// @@ -35,11 +40,25 @@ public class SmsReportController : AdminBaseController /// /// /// + /// /// [HttpGet("GetExpandedList")] - public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date) + public async Task> GetSmsReportExpandList(SmsReportSearchModel searchModel, string date, string typeOfSmsSetting) { - var result =await _smsResultApplication.GetSmsReportExpandList(searchModel, date); + var result =await _smsResultApplication.GetSmsReportExpandList(searchModel, date, typeOfSmsSetting); + return result; + } + + /// + /// دریافت جزئیات پیامک + /// + /// + /// + /// + [HttpGet("GetSmsDetails")] + public async Task GetSmsDetails(int messId, string fullName) + { + var result =await _smsService.GetSmsDetailsByMessageId(messId, fullName); return result; } @@ -56,4 +75,206 @@ public class SmsReportController : AdminBaseController return result; } + //تنظیمات پیامک خودکار + #region SmsSettings + + /// + /// لیست تنظیمات پیامک - یادآور + /// + /// + [HttpGet("ReminderSmsSettingList")] + public async Task> ReminderSmsSettingList() + { + var result = await _smsSettingApplication.GetSmsSettingList(TypeOfSmsSetting.InstitutionContractDebtReminder); + return result; + } + + + /// + /// لیست تنظیمات پیامک - مسدودی + /// + /// + [HttpGet("BlockSmsSettingList")] + public async Task> BlockSmsSettingList() + { + var result = await _smsSettingApplication.GetSmsSettingList(TypeOfSmsSetting.BlockContractingParty); + return result; + } + + /// + /// لیست تنظیمات پیامک - هشدار قضایی + /// + /// + [HttpGet("WarningSmsSettingList")] + public async Task> WarningSmsSettingList() + { + var result = await _smsSettingApplication.GetSmsSettingList(TypeOfSmsSetting.Warning); + return result; + } + + + /// + /// لیست تنظیمات پیامک - اقدام قضایی + /// + /// + [HttpGet("LegalActionSmsSettingList")] + public async Task> LegalActionSmsSettingList() + { + var result = await _smsSettingApplication.GetSmsSettingList(TypeOfSmsSetting.LegalAction); + return result; + } + + /// + /// لیست تنظیمات پیامک - تایید قراداد مالی + /// + /// + [HttpGet("ContractConfirmSmsSettingList")] + public async Task> ContractConfirmSmsSettingList() + { + var result = await _smsSettingApplication.GetSmsSettingList(TypeOfSmsSetting.InstitutionContractConfirm); + return result; + } + + //=====================Create========================= + + /// + /// ایجاد پیامک یادآور + /// + /// + [HttpPost("CreateReminderSmsSetting")] + public async Task> CreateReminderSmsSetting([FromBody] CreateSmsSettingDto command) + { + var result = await _smsSettingApplication.CreateSmsSetting(command.DayOfMonth, command.TimeOfDayDisplay, TypeOfSmsSetting.InstitutionContractDebtReminder); + return result; + } + + /// + /// ایجاد پیامک مسدودی + /// + /// + [HttpPost("CreateBlockSmsSetting")] + public async Task> CreateBlockSmsSetting([FromBody] CreateSmsSettingDto command) + { + var result = await _smsSettingApplication.CreateSmsSetting(command.DayOfMonth, command.TimeOfDayDisplay, TypeOfSmsSetting.BlockContractingParty); + return result; + } + + /// + /// ایجاد پیامک هشدار قضایی + /// + /// + [HttpPost("CreateWarningSmsSetting")] + public async Task> CreateWarningSmsSetting([FromBody] CreateSmsSettingDto command) + { + var result = await _smsSettingApplication.CreateSmsSetting(command.DayOfMonth, command.TimeOfDayDisplay, TypeOfSmsSetting.Warning); + return result; + } + + + /// + /// ایجاد پیامک اقدام قضایی + /// + /// + [HttpPost("CreateLegalActionSmsSetting")] + public async Task> CreateLegalActionSmsSetting([FromBody] CreateSmsSettingDto command) + { + var result = await _smsSettingApplication.CreateSmsSetting(command.DayOfMonth, command.TimeOfDayDisplay, TypeOfSmsSetting.LegalAction); + return result; + } + + + /// + /// ایجاد پیامک تایید قرارداد مالی + /// + /// + [HttpPost("CreateContractConfirmSmsSetting")] + public async Task> CreateContractConfirmSmsSetting([FromBody] CreateSmsSettingDto command) + { + var result = await _smsSettingApplication.CreateSmsSetting(command.DayOfMonth, command.TimeOfDayDisplay, TypeOfSmsSetting.InstitutionContractConfirm); + return result; + } + //=====================Edit========================= + + /// + /// دریافت اطلاعات ویرایش تنظیمات پیامک + /// + /// + /// + [HttpGet("GetEditData")] + public async Task GetEditData(long id) + { + return await _smsSettingApplication.GetSmsSettingDataToEdit(id); + } + + /// + /// ویرایش تنظیمات پیامک + /// + /// + /// + [HttpPut("EditSmsSetting")] + public async Task> EditSmsSetting([FromBody] SmsSettingDto command) + { + var result =await _smsSettingApplication.EditSmsSetting(command); + return result; + } + + //=====================Remove========================= + + /// + /// حذف تنظیمات پیامک + /// + /// + /// + [HttpDelete] + public async Task RemoveSmsSetting(long id) + { + await _smsSettingApplication.RemoveSetting(id); + } + + /// + /// دریافت لیست ارسال آنی یادآور + /// + /// + [HttpGet("GetInstantReminderSmsListData")] + public async Task> GetInstantReminderSmsListData() + { + var result =await _smsSettingApplication.GetInstantReminderSmsListData(TypeOfSmsSetting.InstitutionContractDebtReminder); + return result; + } + + /// + /// دریافت لیست ارسال آنی مسدودی + /// + /// + [HttpGet("GetInstantBlockSmsListData")] + public async Task> GetInstantBlockSmsListData() + { + var result = await _smsSettingApplication.GetInstantReminderSmsListData(TypeOfSmsSetting.BlockContractingParty); + return result; + } + + /// + /// ارسال پیامک آنی یادآور + /// + /// + /// + [HttpPost("InstantReminderSmsSend")] + public async Task> InstantReminderSmsSend([FromBody] List phoneNumbers) + { + var result = await _smsSettingApplication.InstantSmsSendApi(TypeOfSmsSetting.InstitutionContractDebtReminder, phoneNumbers); + return result; + } + + /// + /// ارسال پیامک آنی مسدودی + /// + /// + /// + [HttpPost("InstantBlockSmsSend")] + public async Task> InstantBlockSmsSend([FromBody] List phoneNumbers) + { + var result = await _smsSettingApplication.InstantSmsSendApi(TypeOfSmsSetting.BlockContractingParty, phoneNumbers); + return result; + } + #endregion } \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/CreateRole.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/CreateRole.cshtml index 5172224a..0dbf4b3c 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/CreateRole.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/CreateRole.cshtml @@ -1216,10 +1216,31 @@ - + + + +
+ + + + +
+ + +
+ + + + +
+ @@ -1310,8 +1331,28 @@ - + + +
+ + + +
+ + + + +
+ + + + +
diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml index f7193980..10f6af58 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml @@ -1202,15 +1202,35 @@ -
- - +
+ + -
-
+ + + +
+ + + + +
+ + +
+ + + + +
+ @@ -1292,17 +1312,36 @@ -
- - +
+ + -
+
+ + +
+ + + + +
+ + + +
+ + + +
-