diff --git a/0_Framework/Application/Enums/InstitutionContractVerificationStatus.cs b/0_Framework/Application/Enums/InstitutionContractVerificationStatus.cs
new file mode 100644
index 00000000..2739524a
--- /dev/null
+++ b/0_Framework/Application/Enums/InstitutionContractVerificationStatus.cs
@@ -0,0 +1,22 @@
+namespace _0_Framework.Application.Enums;
+
+///
+/// وضعیت تایید قرادا مالی
+///
+public enum InstitutionContractVerificationStatus
+{
+ ///
+ /// در انتظار تایید
+ ///
+ PendingForVerify = 0,
+
+ ///
+ /// در انتظار کارپوشه
+ ///
+ PendingWorkflow = 1,
+
+ ///
+ /// تایید شده
+ ///
+ Verified = 2
+}
\ No newline at end of file
diff --git a/0_Framework/Application/Enums/TypeOfSmsSetting.cs b/0_Framework/Application/Enums/TypeOfSmsSetting.cs
new file mode 100644
index 00000000..9b4512b7
--- /dev/null
+++ b/0_Framework/Application/Enums/TypeOfSmsSetting.cs
@@ -0,0 +1,36 @@
+namespace _0_Framework.Application.Enums;
+
+public enum TypeOfSmsSetting
+{
+
+ ///
+ /// پیامک
+ /// یادآور بدهی ماهیانه قرارداد مالی
+ ///
+ InstitutionContractDebtReminder,
+
+ ///
+ /// پیامک
+ /// صورت حساب ماهانه قرارداد مالی
+ ///
+ MonthlyInstitutionContract,
+
+ ///
+ /// پیامک
+ /// اعلام مسدودی طرف حساب
+ ///
+ BlockContractingParty,
+
+ ///
+ /// پیامک
+ /// هشدار اول
+ ///
+ Warning,
+
+
+ ///
+ ///پیامک اقدام قضائی
+ ///
+ LegalAction,
+
+}
\ No newline at end of file
diff --git a/0_Framework/Application/Sms/ISmsService.cs b/0_Framework/Application/Sms/ISmsService.cs
index bf55eb00..f0056ba1 100644
--- a/0_Framework/Application/Sms/ISmsService.cs
+++ b/0_Framework/Application/Sms/ISmsService.cs
@@ -32,6 +32,60 @@ public interface ISmsService
public Task SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName,
long contractingPartyId, long institutionContractId);
+ SmsResult TaskReminderSms(string number, string taskCount);
+
+ #endregion
+
+
+ #region InstitutionContractSMS
+ ///
+ /// پیامک اهانه جدید
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBillNew(string number, int tamplateId, string fullname, string amount, string code1,
+ string code2);
+ ///
+ /// پیامک ماهانه قدیم
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBill(string number, int tamplateId, string fullname, string amount, string id, string aprove);
+
+ ///
+ /// پیامک مسدودی طرف حساب
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, string aprove);
+
+ #endregion
+
+ #region AlarmMessage
+
+ ///
+ /// ارسال پیامک های خطا یا اعمال ارسال
+ ///
+ ///
+ ///
+ ///
+ Task Alarm(string number, string message);
+
#endregion
}
\ No newline at end of file
diff --git a/0_Framework/Application/Sms/SmsResult.cs b/0_Framework/Application/Sms/SmsResult.cs
new file mode 100644
index 00000000..266a76d4
--- /dev/null
+++ b/0_Framework/Application/Sms/SmsResult.cs
@@ -0,0 +1,32 @@
+namespace _0_Framework.Application.Sms;
+
+public class SmsResult
+{
+ public SmsResult()
+ {
+ IsSuccedded = false;
+ }
+
+ public bool IsSuccedded { get; set; }
+ public string Message { get; set; }
+ public byte StatusCode { get; set; }
+ public int MessageId { get; set; }
+
+ public SmsResult Succedded(byte statusCode, string message, int messageId)
+ {
+ IsSuccedded = true;
+ Message = message;
+ StatusCode = statusCode;
+ MessageId = messageId;
+ return this;
+ }
+
+ public SmsResult Failed(byte statusCode, string message, int messageId)
+ {
+ IsSuccedded = false;
+ Message = message;
+ StatusCode = statusCode;
+ MessageId = messageId;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj
new file mode 100644
index 00000000..d30ce3b8
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+ BackgroundInstitutionContract.Task
+ BackgroundInstitutionContract.Task
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/FileUploader.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/FileUploader.cs
new file mode 100644
index 00000000..2334c491
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/FileUploader.cs
@@ -0,0 +1,32 @@
+using _0_Framework.Application;
+
+namespace BackgroundInstitutionContract.Task
+{
+ public class FileUploader : IFileUploader
+ {
+ private readonly IWebHostEnvironment _webHostEnvironment;
+
+ public FileUploader(IWebHostEnvironment webHostEnvironment)
+ {
+ _webHostEnvironment = webHostEnvironment;
+ }
+
+ public string Upload(IFormFile file, string path)
+ {
+ if (file == null) return "";
+
+ var directoryPath = $"{_webHostEnvironment.WebRootPath}\\ProductPictures\\{path}";
+
+ if (!Directory.Exists(directoryPath))
+ Directory.CreateDirectory(directoryPath);
+
+ var fileName = $"{DateTime.Now.ToFileName()}-{file.FileName}";
+ var filePath = $"{directoryPath}\\{fileName}";
+ var output = System.IO.File.Create(filePath);
+ file.CopyTo(output);
+ return $"{path}/{fileName}";
+ }
+
+
+ }
+}
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs
new file mode 100644
index 00000000..a0365042
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs
@@ -0,0 +1,149 @@
+
+using _0_Framework.Application;
+using Company.Domain.ContarctingPartyAgg;
+using Company.Domain.InstitutionContractAgg;
+using Hangfire;
+
+namespace BackgroundInstitutionContract.Task.Jobs;
+
+public class JobSchedulerRegistrator
+{
+ private readonly IBackgroundJobClient _backgroundJobClient;
+ private readonly SmsReminder _smsReminder;
+ private readonly IInstitutionContractRepository _institutionContractRepository;
+ private static DateTime? _lastRunCreateTransaction;
+ private static DateTime? _lastRunSendMonthlySms;
+
+
+ public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository)
+ {
+ _smsReminder = smsReminder;
+ _backgroundJobClient = backgroundJobClient;
+ _institutionContractRepository = institutionContractRepository;
+ }
+
+ public void Register()
+ {
+
+ //RecurringJob.AddOrUpdate(
+ // "InstitutionContract.CreateFinancialTransaction",
+ // () => CreateFinancialTransaction(),
+ // "*/30 * * * *" // هر 30 دقیقه یکبار چک کن
+ //);
+
+ //RecurringJob.AddOrUpdate(
+ // "InstitutionContract.SendMonthlySms",
+ // () => SendMonthlySms(),
+ // "*/20 * * * *" // هر 30 دقیقه یکبار چک کن
+ //);
+
+ //RecurringJob.AddOrUpdate(
+ // "InstitutionContract.SendReminderSms",
+ // () => SendReminderSms(),
+ // "*/1 * * * *" // هر 1 دقیقه یکبار چک کن
+ //);
+ RecurringJob.AddOrUpdate(
+ "InstitutionContract.SendBlockSms",
+ () => SendBlockSms(),
+ "*/1 * * * *" // هر 1 دقیقه یکبار چک کن
+ );
+ }
+
+
+ ///
+ /// ایجاد سند بدهی ماهیانه برای قراداد مالی
+ ///
+ ///
+ [DisableConcurrentExecution(timeoutInSeconds: 1200)]
+ public async System.Threading.Tasks.Task CreateFinancialTransaction()
+ {
+ var now =DateTime.Now;
+ var endOfMonth = now.ToFarsi().FindeEndOfMonth();
+ var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
+
+ if (now.Date == endOfMonthGr.Date && now.Hour >= 2 && now.Hour < 4 &&
+ now.Date != _lastRunCreateTransaction?.Date)
+ {
+
+ var month = endOfMonth.Substring(5, 2);
+ var year = endOfMonth.Substring(0, 4);
+ var monthName = month.ToFarsiMonthByNumber();
+ var description = $"{monthName} {year}";
+
+
+
+ var endnew = ($"{endOfMonth.Substring(0, 8)}01").FindeEndOfMonth();
+
+ var endNewGr = endnew.ToGeorgianDateTime();
+ var endNewFa = endNewGr.ToFarsi();
+
+ try
+ {
+ await _institutionContractRepository.CreateTransactionForInstitutionContracts(endNewGr, endNewFa, description);
+ _lastRunCreateTransaction = now;
+ Console.WriteLine("CreateTransAction executed");
+
+ }
+ catch (Exception e)
+ {
+ //_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
+
+ }
+
+ }
+ }
+
+
+ ///
+ /// ارسال پیامک صورت حساب ماهانه
+ ///
+ ///
+ [DisableConcurrentExecution(timeoutInSeconds: 1000)]
+ public async System.Threading.Tasks.Task SendMonthlySms()
+ {
+ //var now = new DateTime(2025,11,21, 10,30,0);
+ var now = DateTime.Now;
+ var endOfMonth = now.ToFarsi().FindeEndOfMonth();
+ var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
+
+ if (now.Date == endOfMonthGr.Date && now.Hour >= 10 && now.Hour < 11 &&
+ now.Date != _lastRunSendMonthlySms?.Date)
+ {
+
+ try
+ {
+ await _institutionContractRepository.SendMonthlySms(now);
+ _lastRunSendMonthlySms = now;
+ Console.WriteLine("Send Monthly sms executed");
+
+ }
+ catch (Exception e)
+ {
+ //_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
+
+ }
+
+ }
+ }
+
+ ///
+ /// ارسال پیامک یاد آور بدهی
+ ///
+ ///
+ [DisableConcurrentExecution(timeoutInSeconds: 1200)]
+ public async System.Threading.Tasks.Task SendReminderSms()
+ {
+ await _institutionContractRepository.SendReminderSmsForBackgroundTask();
+ }
+
+ ///
+ /// ارسال پیامک مسدودی
+ ///
+ ///
+ [DisableConcurrentExecution(timeoutInSeconds: 100)]
+ public async System.Threading.Tasks.Task SendBlockSms()
+ {
+ await _institutionContractRepository.SendBlockSmsForBackgroundTask();
+ }
+
+}
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/SmsReminder.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/SmsReminder.cs
new file mode 100644
index 00000000..c9f1aeaf
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/SmsReminder.cs
@@ -0,0 +1,116 @@
+using _0_Framework.Application.Sms;
+using AccountManagement.Application.Contracts.Account;
+using AccountMangement.Infrastructure.EFCore;
+using Company.Domain.SmsResultAgg;
+using Microsoft.EntityFrameworkCore;
+using SmsResult = Company.Domain.SmsResultAgg.SmsResult;
+
+namespace BackgroundInstitutionContract.Task.Jobs;
+public class SmsReminder
+{
+ private readonly AccountContext _accountContext;
+ private readonly ISmsService _smsService;
+ private readonly ISmsResultRepository _smsResultRepository;
+
+ public SmsReminder(ISmsService smsService, AccountContext accountContext, ISmsResultRepository smsResultRepository)
+ {
+ _smsService = smsService;
+ _accountContext = accountContext;
+ _smsResultRepository = smsResultRepository;
+ }
+
+ public void Execute()
+ {
+ //var accounts = _accountContext.Accounts.Where(x => x.PositionId > 0 && x.IsActiveString == "true").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
+ //Thread.Sleep(300);
+ //var accounts = new List() { new AccountViewModel() { Mobile = "09114221321", Id = 2 } };
+ var accounts= _accountContext.Accounts.Where(x => x.Username.ToLower()=="mahan").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
+ var smsVM = accounts.Select(x => new AccountSmsTaskViewModel()
+ {
+ Mobile = x.Mobile,
+ AccountId = x.Id,
+ FullName = x.Fullname,
+ TaskCount = GetLateTasksCount(x.Id)
+ }).Where(x => x.TaskCount > 0 && !string.IsNullOrEmpty(x.Mobile) && x.Mobile.Length == 11).ToList();
+ Thread.Sleep(300);
+
+
+ foreach (var viewmodel in smsVM)
+ {
+ var smsResult = _smsService.TaskReminderSms(viewmodel.Mobile, $"{viewmodel.TaskCount}");
+ Thread.Sleep(1000);
+ var createSmsResult = new SmsResult(smsResult.MessageId, smsResult.Message, "یادآور وظایف",
+ viewmodel.FullName, viewmodel.Mobile, viewmodel.AccountId, viewmodel.AccountId);
+ _smsResultRepository.Create(createSmsResult);
+ _smsResultRepository.SaveChanges();
+ Thread.Sleep(1000);
+ }
+ }
+ private int GetLateTasksCount(long accountId)
+ {
+ var positionValue = _accountContext.Accounts
+ .Where(x => x.id == accountId)
+ .Include(p => p.Position)
+ .Select(x => x.Position.PositionValue)
+ .FirstOrDefault();
+
+ if (positionValue == 0)
+ return 0;
+
+
+ DateTime now = DateTime.Now;
+ int overdueTasksCount;
+
+ if (positionValue == 1)
+ {
+ overdueTasksCount = _accountContext.Assigns.Include(x => x.Task).Where(x => x.AssignedId == accountId &&
+ x.AssignerId == accountId && x.Task.Assigns.Count == 1 &&
+ !x.IsCancel && !x.IsCanceledRequest &&
+ !x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
+ .GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+
+ //overdueTasksCount = _accountContext.Tasks.Include(x =>
+ // x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
+ // !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
+ // !x.Assigns.Any(a => a.TimeRequest)
+ // && x.Assigns.Any(a => a.AssignedId == accountId && a.AssignerId == accountId) &&
+ // (x.Assigns.First(a => a.AssignedId == accountId && a.AssignerId == accountId)
+ // .EndTaskDate.Date <= DateTime.Now.Date) && x.Assigns.Count == 1);
+ }
+ else
+ {
+
+ overdueTasksCount = _accountContext.Assigns
+ .Include(x => x.Task)
+ .Where(x => x.AssignedId == accountId &&
+ !x.IsCancel && !x.IsCanceledRequest &&
+ !x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
+ .GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+ }
+
+
+ //overdueTasksCount = _accountContext.Tasks.Include(x =>
+ // x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
+ // !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
+ // !x.Assigns.Any(a => a.TimeRequest)
+ // && x.Assigns.Any(a => a.AssignedId == accountId) &&
+ // (x.Assigns.First(a => a.AssignedId == accountId).EndTaskDate.Date <= DateTime.Now.Date));
+
+
+ var overdueRequestsCount = _accountContext.Assigns.Include(x => x.Task)
+ .Where(x => (x.IsCanceledRequest
+ || x.IsDoneRequest || x.TimeRequest) && !x.IsCancel && !x.IsDone &&
+ x.Task.IsActiveString == "true" &&
+ x.Task.SenderId == accountId).GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+
+ return overdueTasksCount + overdueRequestsCount;
+ }
+
+}
+public class AccountSmsTaskViewModel
+{
+ public int TaskCount { get; set; }
+ public long AccountId { get; set; }
+ public string Mobile { get; set; }
+ public string FullName { get; set; }
+}
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/JobsBootstrapper.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/JobsBootstrapper.cs
new file mode 100644
index 00000000..67c287f7
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/JobsBootstrapper.cs
@@ -0,0 +1,25 @@
+using BackgroundInstitutionContract.Task.Jobs;
+
+
+namespace BackgroundInstitutionContract.Task;
+
+public class JobsBootstrapper
+{
+ public static void Configure(IServiceCollection services)
+ {
+ var currentNamespace = typeof(JobSchedulerRegistrator).Namespace; // همون namespace کلاس
+
+ var assembly = typeof(JobSchedulerRegistrator).Assembly;
+
+ var jobTypes = assembly.GetTypes()
+ .Where(t =>
+ t is { IsClass: true, IsAbstract: false, Namespace: not null } &&
+ t.Namespace.StartsWith(currentNamespace, StringComparison.Ordinal))
+ .ToList();
+
+ foreach (var jobType in jobTypes)
+ {
+ services.AddTransient(jobType);
+ }
+ }
+}
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs
new file mode 100644
index 00000000..0c6798e6
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Program.cs
@@ -0,0 +1,59 @@
+using _0_Framework.Application;
+using _0_Framework.Application.Sms;
+using _0_Framework.Application.UID;
+using _0_Framework.InfraStructure.Mongo;
+using AccountManagement.Configuration;
+using BackgroundInstitutionContract.Task;
+using BackgroundInstitutionContract.Task.Jobs;
+using CompanyManagment.EFCore.Services;
+using Hangfire;
+using Microsoft.AspNetCore.Identity;
+using MongoDB.Driver;
+using PersonalContractingParty.Config;
+using Query.Bootstrapper;
+using WorkFlow.Infrastructure.Config;
+
+var builder = WebApplication.CreateBuilder(args);
+var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb");
+builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString));
+builder.Services.AddHangfireServer();
+var connectionString = builder.Configuration.GetConnectionString("MesbahDb");
+var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb");
+builder.Services.AddSingleton();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.Configure(builder.Configuration);
+
+#region MongoDb
+
+var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");
+var mongoDbSettings = mongoConnectionSection.Get();
+var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
+var mongoDatabase = mongoClient.GetDatabase(mongoDbSettings.DatabaseName);
+
+builder.Services.AddSingleton(mongoDatabase);
+
+#endregion
+
+PersonalBootstrapper.Configure(builder.Services, connectionString);
+TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
+AccountManagementBootstrapper.Configure(builder.Services, connectionString);
+WorkFlowBootstrapper.Configure(builder.Services, connectionString);
+QueryBootstrapper.Configure(builder.Services);
+JobsBootstrapper.Configure(builder.Services);
+builder.Services.AddHttpClient();
+builder.Services.AddHttpContextAccessor();
+var app = builder.Build();
+
+app.MapHangfireDashboard();
+app.MapGet("/", () => "Hello World!");
+
+using (var scope = app.Services.CreateScope())
+{
+ var jobScheduler = scope.ServiceProvider.GetRequiredService();
+ jobScheduler.Register();
+}
+
+app.Run();
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Properties/launchSettings.json b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Properties/launchSettings.json
new file mode 100644
index 00000000..e9f19892
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:56492",
+ "sslPort": 44378
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5216",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7223;http://localhost:5217",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json
new file mode 100644
index 00000000..2dc32b9b
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.Development.json
@@ -0,0 +1,46 @@
+{
+ "DetailedErrors": true,
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "ConnectionStrings": {
+ //تست
+ //"MesbahDb": "Data Source=DESKTOP-NUE119G\\MSNEW;Initial Catalog=Mesbah_db;Integrated Security=True"
+
+ //server
+ //"MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
+
+
+ //local
+ "MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;",
+
+ //dad-mehr
+ //"MesbahDb": "Data Source=.;Initial Catalog=teamWork;Integrated Security=True;TrustServerCertificate=true;",
+
+ "TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;",
+
+ //mahan Docker
+ //"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;",
+ "HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;"
+ },
+
+ "GoogleRecaptchaV3": {
+ "SiteKey": "6Lfhp_AnAAAAAB79WkrMoHd1k8ir4m8VvfjE7FTH",
+ "SecretKey": "6Lfhp_AnAAAAANjDDY6DPrbbUQS7k6ZCRmrVP5Lb"
+ },
+ "SmsSecrets": {
+ "ApiKey": "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa",
+ "SecretKey": "dadmehr"
+ },
+ "Domain": ".gozareshgir.ir",
+ "MongoDb": {
+ "ConnectionString": "mongodb://localhost:27017",
+ "DatabaseName": "Gozareshgir"
+ }
+
+
+}
\ No newline at end of file
diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.json b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.json
new file mode 100644
index 00000000..10f68b8c
--- /dev/null
+++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj b/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj
new file mode 100644
index 00000000..0ab571f8
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BackgroundJobs/BackgroundJobs.Task/FileUploader.cs b/BackgroundJobs/BackgroundJobs.Task/FileUploader.cs
new file mode 100644
index 00000000..0d8610d9
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/FileUploader.cs
@@ -0,0 +1,32 @@
+using _0_Framework.Application;
+
+namespace BackgroundJobs.Task
+{
+ public class FileUploader : IFileUploader
+ {
+ private readonly IWebHostEnvironment _webHostEnvironment;
+
+ public FileUploader(IWebHostEnvironment webHostEnvironment)
+ {
+ _webHostEnvironment = webHostEnvironment;
+ }
+
+ public string Upload(IFormFile file, string path)
+ {
+ if (file == null) return "";
+
+ var directoryPath = $"{_webHostEnvironment.WebRootPath}\\ProductPictures\\{path}";
+
+ if (!Directory.Exists(directoryPath))
+ Directory.CreateDirectory(directoryPath);
+
+ var fileName = $"{DateTime.Now.ToFileName()}-{file.FileName}";
+ var filePath = $"{directoryPath}\\{fileName}";
+ var output = System.IO.File.Create(filePath);
+ file.CopyTo(output);
+ return $"{path}/{fileName}";
+ }
+
+
+ }
+}
diff --git a/BackgroundJobs/BackgroundJobs.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundJobs/BackgroundJobs.Task/Jobs/JobSchedulerRegistrator.cs
new file mode 100644
index 00000000..50807e29
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/Jobs/JobSchedulerRegistrator.cs
@@ -0,0 +1,62 @@
+using Hangfire;
+
+namespace BackgroundJobs.Task.Jobs;
+
+public class JobSchedulerRegistrator
+{
+ private readonly IBackgroundJobClient _backgroundJobClient;
+ private readonly SmsReminder _smsReminder;
+ private static DateTime? _lastRunDateMorning;
+ private static DateTime? _lastRunDateEvening;
+
+ public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient)
+ {
+ _smsReminder = smsReminder;
+ _backgroundJobClient = backgroundJobClient;
+ }
+
+ public void Register()
+ {
+ RecurringJob.AddOrUpdate(
+ "Task.SmsReminderChecker",
+ () => SmsReminderCheckAndSchedule(),
+ "*/5 * * * *" // هر 5 دقیقه یکبار چک کن
+ );
+ }
+
+ public void SmsReminderCheckAndSchedule()
+ {
+ var now = DateTime.Now;
+
+ var startMorning = new TimeSpan(9, 0, 0);
+ var endMorning = new TimeSpan(9, 40, 0);
+
+ var startEvening = new TimeSpan(15, 30, 0);
+ var endEvening = new TimeSpan(15, 40, 0);
+
+ // صبح
+ if (now.DayOfWeek != DayOfWeek.Friday &&
+ now.TimeOfDay >= startMorning &&
+ now.TimeOfDay < endMorning)
+ {
+ if (_lastRunDateMorning?.Date != now.Date)
+ {
+ _backgroundJobClient.Enqueue(() => _smsReminder.Execute());
+ _lastRunDateMorning = now;
+ }
+ }
+
+ // عصر - پنجشنبه و جمعه تعطیل است
+ if (now.DayOfWeek != DayOfWeek.Friday &&
+ now.DayOfWeek != DayOfWeek.Thursday &&
+ now.TimeOfDay >= startEvening &&
+ now.TimeOfDay < endEvening)
+ {
+ if (_lastRunDateEvening?.Date != now.Date)
+ {
+ _backgroundJobClient.Enqueue(() => _smsReminder.Execute());
+ _lastRunDateEvening = now;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/BackgroundJobs/BackgroundJobs.Task/Jobs/SmsReminder.cs b/BackgroundJobs/BackgroundJobs.Task/Jobs/SmsReminder.cs
new file mode 100644
index 00000000..3b1f4980
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/Jobs/SmsReminder.cs
@@ -0,0 +1,116 @@
+using _0_Framework.Application.Sms;
+using AccountManagement.Application.Contracts.Account;
+using AccountMangement.Infrastructure.EFCore;
+using Company.Domain.SmsResultAgg;
+using Microsoft.EntityFrameworkCore;
+using SmsResult = Company.Domain.SmsResultAgg.SmsResult;
+
+namespace BackgroundJobs.Task.Jobs;
+public class SmsReminder
+{
+ private readonly AccountContext _accountContext;
+ private readonly ISmsService _smsService;
+ private readonly ISmsResultRepository _smsResultRepository;
+
+ public SmsReminder(ISmsService smsService, AccountContext accountContext, ISmsResultRepository smsResultRepository)
+ {
+ _smsService = smsService;
+ _accountContext = accountContext;
+ _smsResultRepository = smsResultRepository;
+ }
+
+ public void Execute()
+ {
+ //var accounts = _accountContext.Accounts.Where(x => x.PositionId > 0 && x.IsActiveString == "true").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
+ //Thread.Sleep(300);
+ //var accounts = new List() { new AccountViewModel() { Mobile = "09114221321", Id = 2 } };
+ var accounts= _accountContext.Accounts.Where(x => x.Username.ToLower()=="mahan").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
+ var smsVM = accounts.Select(x => new AccountSmsTaskViewModel()
+ {
+ Mobile = x.Mobile,
+ AccountId = x.Id,
+ FullName = x.Fullname,
+ TaskCount = GetLateTasksCount(x.Id)
+ }).Where(x => x.TaskCount > 0 && !string.IsNullOrEmpty(x.Mobile) && x.Mobile.Length == 11).ToList();
+ Thread.Sleep(300);
+
+
+ foreach (var viewmodel in smsVM)
+ {
+ var smsResult = _smsService.TaskReminderSms(viewmodel.Mobile, $"{viewmodel.TaskCount}");
+ Thread.Sleep(1000);
+ var createSmsResult = new SmsResult(smsResult.MessageId, smsResult.Message, "یادآور وظایف",
+ viewmodel.FullName, viewmodel.Mobile, viewmodel.AccountId, viewmodel.AccountId);
+ _smsResultRepository.Create(createSmsResult);
+ _smsResultRepository.SaveChanges();
+ Thread.Sleep(1000);
+ }
+ }
+ private int GetLateTasksCount(long accountId)
+ {
+ var positionValue = _accountContext.Accounts
+ .Where(x => x.id == accountId)
+ .Include(p => p.Position)
+ .Select(x => x.Position.PositionValue)
+ .FirstOrDefault();
+
+ if (positionValue == 0)
+ return 0;
+
+
+ DateTime now = DateTime.Now;
+ int overdueTasksCount;
+
+ if (positionValue == 1)
+ {
+ overdueTasksCount = _accountContext.Assigns.Include(x => x.Task).Where(x => x.AssignedId == accountId &&
+ x.AssignerId == accountId && x.Task.Assigns.Count == 1 &&
+ !x.IsCancel && !x.IsCanceledRequest &&
+ !x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
+ .GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+
+ //overdueTasksCount = _accountContext.Tasks.Include(x =>
+ // x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
+ // !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
+ // !x.Assigns.Any(a => a.TimeRequest)
+ // && x.Assigns.Any(a => a.AssignedId == accountId && a.AssignerId == accountId) &&
+ // (x.Assigns.First(a => a.AssignedId == accountId && a.AssignerId == accountId)
+ // .EndTaskDate.Date <= DateTime.Now.Date) && x.Assigns.Count == 1);
+ }
+ else
+ {
+
+ overdueTasksCount = _accountContext.Assigns
+ .Include(x => x.Task)
+ .Where(x => x.AssignedId == accountId &&
+ !x.IsCancel && !x.IsCanceledRequest &&
+ !x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
+ .GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+ }
+
+
+ //overdueTasksCount = _accountContext.Tasks.Include(x =>
+ // x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
+ // !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
+ // !x.Assigns.Any(a => a.TimeRequest)
+ // && x.Assigns.Any(a => a.AssignedId == accountId) &&
+ // (x.Assigns.First(a => a.AssignedId == accountId).EndTaskDate.Date <= DateTime.Now.Date));
+
+
+ var overdueRequestsCount = _accountContext.Assigns.Include(x => x.Task)
+ .Where(x => (x.IsCanceledRequest
+ || x.IsDoneRequest || x.TimeRequest) && !x.IsCancel && !x.IsDone &&
+ x.Task.IsActiveString == "true" &&
+ x.Task.SenderId == accountId).GroupBy(x => x.TaskId).Select(x => x.First()).Count();
+
+ return overdueTasksCount + overdueRequestsCount;
+ }
+
+}
+public class AccountSmsTaskViewModel
+{
+ public int TaskCount { get; set; }
+ public long AccountId { get; set; }
+ public string Mobile { get; set; }
+ public string FullName { get; set; }
+}
\ No newline at end of file
diff --git a/BackgroundJobs/BackgroundJobs.Task/JobsBootstrapper.cs b/BackgroundJobs/BackgroundJobs.Task/JobsBootstrapper.cs
new file mode 100644
index 00000000..a89f8265
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/JobsBootstrapper.cs
@@ -0,0 +1,24 @@
+using BackgroundJobs.Task.Jobs;
+
+namespace BackgroundJobs.Task;
+
+public class JobsBootstrapper
+{
+ public static void Configure(IServiceCollection services)
+ {
+ var currentNamespace = typeof(JobSchedulerRegistrator).Namespace; // همون namespace کلاس
+
+ var assembly = typeof(JobSchedulerRegistrator).Assembly;
+
+ var jobTypes = assembly.GetTypes()
+ .Where(t =>
+ t is { IsClass: true, IsAbstract: false, Namespace: not null } &&
+ t.Namespace.StartsWith(currentNamespace, StringComparison.Ordinal))
+ .ToList();
+
+ foreach (var jobType in jobTypes)
+ {
+ services.AddTransient(jobType);
+ }
+ }
+}
\ No newline at end of file
diff --git a/BackgroundJobs/BackgroundJobs.Task/Program.cs b/BackgroundJobs/BackgroundJobs.Task/Program.cs
new file mode 100644
index 00000000..dac1199a
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/Program.cs
@@ -0,0 +1,59 @@
+using _0_Framework.Application;
+using _0_Framework.Application.Sms;
+using _0_Framework.Application.UID;
+using _0_Framework.InfraStructure.Mongo;
+using AccountManagement.Configuration;
+using BackgroundJobs.Task;
+using BackgroundJobs.Task.Jobs;
+using CompanyManagment.EFCore.Services;
+using Hangfire;
+using Microsoft.AspNetCore.Identity;
+using MongoDB.Driver;
+using PersonalContractingParty.Config;
+using Query.Bootstrapper;
+using WorkFlow.Infrastructure.Config;
+
+var builder = WebApplication.CreateBuilder(args);
+var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb");
+builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString));
+builder.Services.AddHangfireServer();
+var connectionString = builder.Configuration.GetConnectionString("MesbahDb");
+var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb");
+builder.Services.AddSingleton();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.AddTransient();
+builder.Services.Configure(builder.Configuration);
+
+#region MongoDb
+
+var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");
+var mongoDbSettings = mongoConnectionSection.Get();
+var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
+var mongoDatabase = mongoClient.GetDatabase(mongoDbSettings.DatabaseName);
+
+builder.Services.AddSingleton(mongoDatabase);
+
+#endregion
+
+PersonalBootstrapper.Configure(builder.Services, connectionString);
+TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
+AccountManagementBootstrapper.Configure(builder.Services, connectionString);
+WorkFlowBootstrapper.Configure(builder.Services, connectionString);
+QueryBootstrapper.Configure(builder.Services);
+JobsBootstrapper.Configure(builder.Services);
+builder.Services.AddHttpClient();
+builder.Services.AddHttpContextAccessor();
+var app = builder.Build();
+
+app.MapHangfireDashboard();
+app.MapGet("/", () => "Hello World!");
+
+using (var scope = app.Services.CreateScope())
+{
+ var jobScheduler = scope.ServiceProvider.GetRequiredService();
+ jobScheduler.Register();
+}
+
+app.Run();
\ No newline at end of file
diff --git a/BackgroundJobs/BackgroundJobs.Task/Properties/launchSettings.json b/BackgroundJobs/BackgroundJobs.Task/Properties/launchSettings.json
new file mode 100644
index 00000000..197ad0e4
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:56492",
+ "sslPort": 44378
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5216",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7222;http://localhost:5216",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/BackgroundJobs/BackgroundJobs.Task/appsettings.Development.json b/BackgroundJobs/BackgroundJobs.Task/appsettings.Development.json
new file mode 100644
index 00000000..2dc32b9b
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/appsettings.Development.json
@@ -0,0 +1,46 @@
+{
+ "DetailedErrors": true,
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "ConnectionStrings": {
+ //تست
+ //"MesbahDb": "Data Source=DESKTOP-NUE119G\\MSNEW;Initial Catalog=Mesbah_db;Integrated Security=True"
+
+ //server
+ //"MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
+
+
+ //local
+ "MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;",
+
+ //dad-mehr
+ //"MesbahDb": "Data Source=.;Initial Catalog=teamWork;Integrated Security=True;TrustServerCertificate=true;",
+
+ "TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;",
+
+ //mahan Docker
+ //"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;",
+ "HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;"
+ },
+
+ "GoogleRecaptchaV3": {
+ "SiteKey": "6Lfhp_AnAAAAAB79WkrMoHd1k8ir4m8VvfjE7FTH",
+ "SecretKey": "6Lfhp_AnAAAAANjDDY6DPrbbUQS7k6ZCRmrVP5Lb"
+ },
+ "SmsSecrets": {
+ "ApiKey": "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa",
+ "SecretKey": "dadmehr"
+ },
+ "Domain": ".gozareshgir.ir",
+ "MongoDb": {
+ "ConnectionString": "mongodb://localhost:27017",
+ "DatabaseName": "Gozareshgir"
+ }
+
+
+}
\ No newline at end of file
diff --git a/BackgroundJobs/BackgroundJobs.Task/appsettings.json b/BackgroundJobs/BackgroundJobs.Task/appsettings.json
new file mode 100644
index 00000000..10f68b8c
--- /dev/null
+++ b/BackgroundJobs/BackgroundJobs.Task/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/Company.Domain/FinancialTransactionAgg/FinancialTransaction.cs b/Company.Domain/FinancialTransactionAgg/FinancialTransaction.cs
index 65c20a40..061836b3 100644
--- a/Company.Domain/FinancialTransactionAgg/FinancialTransaction.cs
+++ b/Company.Domain/FinancialTransactionAgg/FinancialTransaction.cs
@@ -26,6 +26,35 @@ public class FinancialTransaction : EntityBase
}
+ ///
+ /// ایجاد از طرف بک گراند سرویس
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public FinancialTransaction(long financialStatementId, DateTime tdateGr, string tdateFa, string description,
+ string typeOfTransaction, string descriptionOption, double deptor, double creditor, double balance,
+ bool sentSms)
+ {
+ FinancialStatementId = financialStatementId;
+ TdateGr = tdateGr;
+ TdateFa = tdateFa;
+ Description = description;
+ TypeOfTransaction = typeOfTransaction;
+ DescriptionOption = descriptionOption;
+ Deptor = deptor;
+ Creditor = creditor;
+ Balance = balance;
+ SentSms = sentSms;
+ }
+
public long FinancialStatementId { get; private set; }
public DateTime TdateGr { get; private set; }
public string TdateFa { get; private set; }
diff --git a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs
index 3a91fcdf..1cc32693 100644
--- a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs
+++ b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using _0_Framework.Application;
+using _0_Framework.Application.Enums;
using _0_Framework.Domain;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.Workshop;
@@ -44,7 +45,7 @@ public interface IInstitutionContractRepository : IRepository
///
///
- void RollcallServiceCreateTransaction();
+ Task RollCallServiceCreateTransaction();
Task> GetList(InstitutionContractListSearchModel searchModel);
Task GetListStats(InstitutionContractListSearchModel searchModel);
@@ -77,4 +78,71 @@ public interface IInstitutionContractRepository : IRepository> GetInstitutionContractSelectList(string search, string selected);
Task> PrintAllAsync(List ids);
+
+
+ #region ReminderSMS
+ ///
+ /// دریافت لیست - ارسال پیامک
+ /// فراخوانی از سمت بک گراند سرویس
+ ///
+ ///
+ Task SendReminderSmsForBackgroundTask();
+
+ ///
+ /// ارسال پیامک صورت حساب ماهانه
+ ///
+ ///
+ ///
+ Task SendMonthlySms(DateTime now);
+
+ ///
+ /// ارسال پیامک مسدودی از طرف بک گراند سرویس
+ ///
+ ///
+ Task SendBlockSmsForBackgroundTask();
+
+ ///
+ /// دریافت لیست واجد شرایط بلاک
+ /// جهت ارسال پیامک مسدودی
+ ///
+ ///
+ ///
+ Task> GetBlockListData(DateTime checkDate);
+
+ ///
+ /// ارسال پیامک مسدودی
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SendBlockSmsToContractingParties(List smsListData, string typeOfSms,
+ string sendMessStart, string sendMessEnd);
+
+ ///
+ ///دریافت لیست بدهکارن
+ /// جهت ارسال پیامک
+ ///
+ ///
+ Task> GetSmsListData(DateTime checkDate, TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// ارسال پیامک های یاد آور بدهی
+ ///
+ ///
+ Task SendReminderSmsToContractingParties(List smsListData, string typeOfSms, string sendMessStart, string sendMessEnd);
+
+ #endregion
+
+ #region CreateMontlyTransaction
+
+ ///
+ /// ایجاد سند مالی برای قرارداد ها
+ ///
+ ///
+ Task CreateTransactionForInstitutionContracts(DateTime endOfMonthGr, string endOfMonthFa, string description);
+
+
+ #endregion
}
\ No newline at end of file
diff --git a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs
index 2df07cf1..0484a1c7 100644
--- a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs
+++ b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Cryptography;
+using _0_Framework.Application.Enums;
using _0_Framework.Domain;
using Company.Domain.InstitutionContractContactInfoAgg;
using CompanyManagment.App.Contracts.InstitutionContract;
@@ -371,20 +372,3 @@ public enum InstitutionContractAmendmentChangeType
WorkshopCreated
}
-public enum InstitutionContractVerificationStatus
-{
- ///
- /// در انتظار تایید
- ///
- PendingForVerify = 0,
-
- ///
- /// در انتظار کارپوشه
- ///
- PendingWorkflow = 1,
-
- ///
- /// تایید شده
- ///
- Verified = 2
-}
\ No newline at end of file
diff --git a/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs b/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs
new file mode 100644
index 00000000..a2c864a5
--- /dev/null
+++ b/Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs
@@ -0,0 +1,30 @@
+using _0_Framework.Application.Enums;
+using _0_Framework.Domain;
+using CompanyManagment.App.Contracts.SmsResult;
+using System.Threading.Tasks;
+
+namespace Company.Domain.SmsResultAgg;
+
+public interface ISmsSettingsRepository : IRepository
+{
+ ///
+ /// ویرایش پیامک خودکار
+ ///
+ ///
+ ///
+ Task GetSmsSettingToEdit(long id);
+
+ ///
+ /// دریافت لیست پیامک های خودکار بر اساس نوع آن
+ ///
+ ///
+ ///
+ Task GetSmsSettingsByType(TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// حذف از دیتابیس
+ ///
+ ///
+ ///
+ Task RemoveItem(long id);
+}
\ No newline at end of file
diff --git a/Company.Domain/SmsResultAgg/SmsSetting.cs b/Company.Domain/SmsResultAgg/SmsSetting.cs
new file mode 100644
index 00000000..3ca835fa
--- /dev/null
+++ b/Company.Domain/SmsResultAgg/SmsSetting.cs
@@ -0,0 +1,72 @@
+using _0_Framework.Application.Enums;
+using _0_Framework.Domain;
+using System;
+
+namespace Company.Domain.SmsResultAgg;
+
+public class SmsSetting : EntityBaseWithoutCreationDate
+{
+ ///
+ /// ایجاد تنظیمات پیامک
+ ///
+ ///
+ ///
+ ///
+ public SmsSetting(TypeOfSmsSetting typeOfSmsSetting, int dayOfMonth, TimeSpan timeOfDay)
+ {
+ TypeOfSmsSetting = typeOfSmsSetting;
+ DayOfMonth = dayOfMonth;
+ TimeOfDay = timeOfDay;
+ IsActive = true;
+ }
+
+ ///
+ /// نوع پیامک
+ ///
+ public TypeOfSmsSetting TypeOfSmsSetting { get; set; }
+
+ ///
+ /// عدد روز از ماه
+ ///
+ public int DayOfMonth { get; set; }
+
+
+ ///
+ /// ساعت
+ ///
+ public TimeSpan TimeOfDay { get; set; }
+
+ ///
+ /// فعال/غیرفعال
+ ///
+ public bool IsActive { get; set; }
+
+ ///
+ /// ویرایش تنظیمات پیامک
+ ///
+ ///
+ ///
+ public void Edit(int dayOfMonth, TimeSpan timeOfDay)
+ {
+ DayOfMonth = dayOfMonth;
+ TimeOfDay = timeOfDay;
+ }
+
+ ///
+ /// فعال نمودن
+ ///
+ public void Active()
+ {
+ IsActive = true;
+ }
+
+ ///
+ /// غیر فعال نمودن
+ ///
+ public void DeActive()
+ {
+ IsActive = false;
+ }
+
+
+}
\ No newline at end of file
diff --git a/CompanyManagment.App.Contracts/FinancialStatment/FinancialStatmentViewModel.cs b/CompanyManagment.App.Contracts/FinancialStatment/FinancialStatmentViewModel.cs
index 4b63cb82..01976a5e 100644
--- a/CompanyManagment.App.Contracts/FinancialStatment/FinancialStatmentViewModel.cs
+++ b/CompanyManagment.App.Contracts/FinancialStatment/FinancialStatmentViewModel.cs
@@ -9,6 +9,7 @@ public class FinancialStatmentViewModel
public long Id { get; set; }
public long ContractingPartyId { get; set; }
public string ContractingPartyName { get; set; }
+ public string PublicId { get; set; }
public List FinancialTransactionViewModels { get; set; }
diff --git a/CompanyManagment.App.Contracts/FinancilTransaction/FinancialTransactionViewModel.cs b/CompanyManagment.App.Contracts/FinancilTransaction/FinancialTransactionViewModel.cs
index 42b0b017..9866db57 100644
--- a/CompanyManagment.App.Contracts/FinancilTransaction/FinancialTransactionViewModel.cs
+++ b/CompanyManagment.App.Contracts/FinancilTransaction/FinancialTransactionViewModel.cs
@@ -10,6 +10,7 @@ public class FinancialTransactionViewModel
public string TdateFa { get; set; }
public string Description { get; set; }
public string TypeOfTransaction { get; set; }
+ public string DescriptionOption { get; set; }
public double Deptor { get; set; }
public string DeptorString { get; set; }
public double Creditor { get; set; }
@@ -20,4 +21,7 @@ public class FinancialTransactionViewModel
public string MessageText { get; set; }
public string SentSmsDateFa { get; set; }
public int Counter { get; set; }
+
+
+
}
\ No newline at end of file
diff --git a/CompanyManagment.App.Contracts/Hubs/SendSmsHub.cs b/CompanyManagment.App.Contracts/Hubs/SendSmsHub.cs
new file mode 100644
index 00000000..0327bf2d
--- /dev/null
+++ b/CompanyManagment.App.Contracts/Hubs/SendSmsHub.cs
@@ -0,0 +1,20 @@
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.SignalR;
+
+namespace CompanyManagment.App.Contracts.Hubs;
+
+
+public class SendSmsHub : Hub
+{
+
+ public async Task send(long id)
+ {
+ await Groups.AddToGroupAsync(Context.ConnectionId, GetGroupName(id));
+ }
+
+ public static string GetGroupName(long id)
+ {
+ return $"group-sms-{id}";
+ }
+}
\ No newline at end of file
diff --git a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractInstallmentViewModel.cs b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractInstallmentViewModel.cs
index 86655873..77bee51d 100644
--- a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractInstallmentViewModel.cs
+++ b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractInstallmentViewModel.cs
@@ -27,7 +27,13 @@ public class InstitutionContractInstallmentViewModel
/// مبلغ قسط
///
public string Amount { get; set; }
-
+
+ ///
+ /// مبلغ قسط
+ /// Double
+ ///
+ public double AmountDouble { get; set; }
+
///
/// عدد قسط فارسی
///
diff --git a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractViewModel.cs b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractViewModel.cs
index 5a4478fe..2b3032cc 100644
--- a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractViewModel.cs
+++ b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using _0_Framework.Application.Enums;
using CompanyManagment.App.Contracts.Employer;
using CompanyManagment.App.Contracts.Workshop;
@@ -25,6 +26,7 @@ public class InstitutionContractViewModel
public DateTime ContractEndGr { get; set; }
public string ContractEndFa { get; set; }
public string ContractAmount { get; set; }
+ public double ContractAmountDouble { get; set; }
public string DailyCompenseation { get; set; }
public string Obligation { get; set; }
@@ -70,4 +72,9 @@ public class InstitutionContractViewModel
public int LeftWorkEmployeeCount { get; set; }
public int InsuranceLeftWorkEmployeeCount { get; set; }
public string IsExpier { get; set; }
+
+ public bool IsInstallment { get; set; }
+ public InstitutionContractVerificationStatus VerificationStatus { get; set; }
+
+ public List InstallmentList { get; set; }
}
\ No newline at end of file
diff --git a/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs
new file mode 100644
index 00000000..35a89e68
--- /dev/null
+++ b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs
@@ -0,0 +1,97 @@
+namespace CompanyManagment.App.Contracts.InstitutionContract;
+
+///
+/// لیست پیامکهای بدهکاران قرارداد ملی
+///
+public class SmsListData
+{
+ ///
+ /// شماره تماس طرف حساب
+ ///
+ public string PhoneNumber { get; set; }
+ ///
+ /// تمپلیت آی دی
+ ///
+ public int TemplateId { get; set; }
+
+ ///
+ /// نام طرف حساب
+ ///
+ public string PartyName { get; set; }
+
+ ///
+ /// مبلغ بدهی
+ ///
+ public string Amount { get; set; }
+ ///
+ /// آی دی طرف حساب
+ ///
+ public long ContractingPartyId { get; set; }
+
+ ///
+ /// آی دی صورت حساب مالی
+ ///
+ public string AproveId { get; set; }
+
+ ///
+ /// نوع متد ارسال پیامک
+ ///
+ public string TypeOfSmsMethod { get; set; }
+
+ ///
+ /// پابلیک آی دی بخش یک
+ ///
+ public string Code1 { get; set; }
+
+ ///
+ /// پابلیک آی دی بخش دو
+ ///
+ public string Code2 { get; set; }
+
+ ///
+ /// ای دی قراداد مالی
+ ///
+ public long InstitutionContractId { get; set; }
+}
+
+///
+/// لیست پیامک های بلاک
+///
+public class BlockSmsListData
+{
+ ///
+ /// شماره تماس طرف حساب
+ ///
+ public string PhoneNumber { get; set; }
+
+ ///
+ /// نام طرف حساب
+ ///
+ public string PartyName { get; set; }
+
+ ///
+ /// مبلغ بدهی
+ ///
+ public string Amount { get; set; }
+ ///
+ /// آی دی طرف حساب
+ ///
+ public long ContractingPartyId { get; set; }
+
+
+
+ ///
+ /// نوع حساب - رسمی یا غیر رسمی
+ ///
+ public string AccountType { get; set; }
+
+ ///
+ /// ای دی قراداد مالی
+ ///
+ public long InstitutionContractId { get; set; }
+
+ ///
+ /// آی دی صورت حساب مالی
+ ///
+ public string AproveId { get; set; }
+}
\ No newline at end of file
diff --git a/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs b/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs
new file mode 100644
index 00000000..f467ca34
--- /dev/null
+++ b/CompanyManagment.App.Contracts/SmsResult/CreateSmsSetting.cs
@@ -0,0 +1,62 @@
+using _0_Framework.Application.Enums;
+using System;
+using System.Collections.Generic;
+using _0_Framework.Domain;
+
+namespace CompanyManagment.App.Contracts.SmsResult;
+
+///
+/// مدل ایجاد تنظیمات پیامک
+///
+public class CreateSmsSetting
+{
+ ///
+ /// نوع پیامک
+ ///
+ public TypeOfSmsSetting TypeOfSmsSetting { get; set; }
+
+ ///
+ /// عدد روز از ماه
+ ///
+ public int DayOfMonth { get; set; }
+
+
+ ///
+ /// ساعت
+ ///
+ public TimeSpan TimeOfDay { get; set; }
+
+
+}
+
+///
+/// ویرایش تنظیمات پیامک
+///
+public class EditSmsSetting : CreateSmsSetting
+{
+ ///
+ /// آی دی
+ ///
+ public long Id { get; set; }
+
+ ///
+ /// فعال/غیرفعال
+ ///
+ public bool IsActive { get; set; }
+
+ ///
+ /// نمایش ساعت و دقیقه
+ ///
+ public string TimeOfDayDisplay { get; set; }
+}
+
+///
+/// ویو مدل تنظیمات پیامک
+///
+public class SmsSettingViewModel
+{
+ ///
+ /// لیست تنظیمات پیامک
+ ///
+ public List EditSmsSettings { get; set; }
+}
diff --git a/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs b/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs
new file mode 100644
index 00000000..49fdc4e8
--- /dev/null
+++ b/CompanyManagment.App.Contracts/SmsResult/ISmsSettingApplication.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using _0_Framework.Application;
+using _0_Framework.Application.Enums;
+using CompanyManagment.App.Contracts.InstitutionContract;
+
+namespace CompanyManagment.App.Contracts.SmsResult;
+
+public interface ISmsSettingApplication
+{
+
+ ///
+ /// دریافت لیست پیامک های خودکار بر اساس نوع آن
+ ///
+ ///
+ ///
+ public Task GetSmsSettingsByType(TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// ایجاد تنظیمات پیامک یادآور
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task CreateSmsSetting(int dayOfMonth, string timeOfDay, TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// ویرایش پیامک خودکار
+ ///
+ ///
+ ///
+ Task GetSmsSettingToEdit(long id);
+
+ ///
+ /// ایجاد تنظیمات پیامک یادآور
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task EditeSmsSetting(EditSmsSetting command);
+
+ ///
+ /// حذف از دیتابیس
+ ///
+ ///
+ ///
+ Task RemoveSetting(long id);
+
+ ///
+ /// دریافت لیست بدهکاران
+ ///
+ ///
+ ///
+ Task> GetSmsListData(TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// دریافت لیست کسانی که باید بلاک شوند
+ ///
+ ///
+ ///
+ Task> GetBlockSmsListData(TypeOfSmsSetting typeOfSmsSetting);
+
+ ///
+ /// ارسال پیامک یاد آور آنی
+ ///
+ ///
+ ///
+ Task InstantSendReminderSms(List command);
+
+ ///
+ /// ارسال پیامک مسدودس
+ ///
+ ///
+ ///
+ Task InstantSendBlockSms(List command);
+}
\ No newline at end of file
diff --git a/CompanyManagment.Application/SmsSettingApplication.cs b/CompanyManagment.Application/SmsSettingApplication.cs
new file mode 100644
index 00000000..5888d331
--- /dev/null
+++ b/CompanyManagment.Application/SmsSettingApplication.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using _0_Framework.Application;
+using _0_Framework.Application.Enums;
+using Company.Domain.InstitutionContractAgg;
+using Company.Domain.SmsResultAgg;
+using CompanyManagment.App.Contracts.InstitutionContract;
+using CompanyManagment.App.Contracts.SmsResult;
+
+namespace CompanyManagment.Application;
+
+public class SmsSettingApplication : ISmsSettingApplication
+{
+ private readonly ISmsSettingsRepository _smsSettingsRepository;
+ private readonly IInstitutionContractRepository _institutionContractRepository;
+
+ public SmsSettingApplication(ISmsSettingsRepository smsSettingsRepository, IInstitutionContractRepository institutionContractRepository)
+ {
+ _smsSettingsRepository = smsSettingsRepository;
+ _institutionContractRepository = institutionContractRepository;
+ }
+
+
+ public async Task GetSmsSettingsByType(TypeOfSmsSetting typeOfSmsSetting)
+ {
+ return await _smsSettingsRepository.GetSmsSettingsByType(typeOfSmsSetting);
+ }
+
+ ///
+ /// ایجاد تنظیمات پیامک یادآور
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task CreateSmsSetting(int dayOfMonth, string timeOfDay,
+ TypeOfSmsSetting typeOfSmsSetting)
+ {
+ var op = new OperationResult();
+ var timeSpan = new TimeSpan();
+ if (string.IsNullOrWhiteSpace(timeOfDay))
+ return op.Failed("ساعت وارد نشده است");
+
+ try
+ {
+ timeSpan = TimeSpan.ParseExact(timeOfDay, @"hh\:mm", null);
+ }
+ catch (Exception e)
+ {
+ return op.Failed("فرمت ساعت اشتباه است");
+ }
+
+
+ if (dayOfMonth < 1 || dayOfMonth > 31)
+ {
+ return op.Failed("عدد روز می بایست بین 1 تا 31 باشد");
+ }
+
+ if (_smsSettingsRepository.Exists(x => x.DayOfMonth == dayOfMonth && x.TimeOfDay == timeSpan && x.TypeOfSmsSetting == typeOfSmsSetting))
+ return op.Failed("رکورد ایجاد شده تکراری است");
+
+ var create = new SmsSetting(typeOfSmsSetting, dayOfMonth, timeSpan);
+ await _smsSettingsRepository.CreateAsync(create);
+ await _smsSettingsRepository.SaveChangesAsync();
+
+
+ return op.Succcedded();
+ }
+
+ public async Task GetSmsSettingToEdit(long id)
+ {
+ return await _smsSettingsRepository.GetSmsSettingToEdit(id);
+ }
+
+ public async Task EditeSmsSetting(EditSmsSetting command)
+ {
+ var op = new OperationResult();
+ 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 == command.TypeOfSmsSetting && x.id != command.Id))
+ return op.Failed("رکورد ایجاد شده تکراری است");
+
+ var editSmsSetting = _smsSettingsRepository.Get(command.Id);
+ editSmsSetting.Edit(command.DayOfMonth, timeSpan);
+ await _smsSettingsRepository.SaveChangesAsync();
+
+ return op.Succcedded();
+ }
+
+ public async Task RemoveSetting(long id)
+ {
+ await _smsSettingsRepository.RemoveItem(id);
+ }
+
+
+
+
+
+ public async Task> GetSmsListData(TypeOfSmsSetting typeOfSmsSetting)
+ {
+ return await _institutionContractRepository.GetSmsListData(DateTime.Now, typeOfSmsSetting);
+ }
+
+ public async Task> GetBlockSmsListData(TypeOfSmsSetting typeOfSmsSetting)
+ {
+ return await _institutionContractRepository.GetBlockListData(DateTime.Now);
+ }
+
+
+ public async Task InstantSendReminderSms(List command)
+ {
+ var op = new OperationResult();
+ string typeOfSms = "یادآور بدهی ماهانه";
+ string sendMessStart = "شروع یادآور آنی";
+ string sendMessEnd = "پایان یادآور آنی";
+
+ if (command.Any())
+ {
+ await _institutionContractRepository.SendReminderSmsToContractingParties(command, typeOfSms, sendMessStart, sendMessEnd);
+ return op.Succcedded();
+ }
+ else
+ {
+ return op.Failed("موردی انتخاب نشده است");
+ }
+
+
+ }
+
+ public async Task InstantSendBlockSms(List command)
+ {
+ var op = new OperationResult();
+ string typeOfSms = "اعلام مسدودی طرف حساب";
+ string sendMessStart = "شروع مسدودی آنی";
+ string sendMessEnd = "پایان مسدودی آنی ";
+ if (command.Any())
+ {
+ await _institutionContractRepository.SendBlockSmsToContractingParties(command, typeOfSms, sendMessStart,
+ sendMessEnd);
+ return op.Succcedded();
+ }
+ else
+ {
+ return op.Failed("موردی انتخاب نشده است");
+ }
+ }
+}
\ No newline at end of file
diff --git a/CompanyManagment.EFCore/CompanyContext.cs b/CompanyManagment.EFCore/CompanyContext.cs
index cb829e56..b7abcbe0 100644
--- a/CompanyManagment.EFCore/CompanyContext.cs
+++ b/CompanyManagment.EFCore/CompanyContext.cs
@@ -163,6 +163,12 @@ public class CompanyContext : DbContext
//-------Main-Project----------------------------
+ #region SmsSettings
+
+ public DbSet SmsSettings { get; set; }
+
+ #endregion
+
#region Mahan
//-----------------------------RollCallWorkshopSettings-----------------------------
diff --git a/CompanyManagment.EFCore/Mapping/SmsSettingMapping.cs b/CompanyManagment.EFCore/Mapping/SmsSettingMapping.cs
new file mode 100644
index 00000000..b3c43d65
--- /dev/null
+++ b/CompanyManagment.EFCore/Mapping/SmsSettingMapping.cs
@@ -0,0 +1,30 @@
+using System;
+using _0_Framework.Application.Enums;
+using Company.Domain.SmsResultAgg;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace CompanyManagment.EFCore.Mapping;
+
+public class SmsSettingMapping : IEntityTypeConfiguration
+{
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("SmsSettings");
+ builder.HasKey(x => x.id);
+
+
+ builder.Property(x => x.DayOfMonth)
+ .IsRequired();
+
+ builder.Property(x => x.TimeOfDay)
+ .HasColumnType("time(0)")
+ .IsRequired();
+
+ builder.Property(x => x.TypeOfSmsSetting).HasConversion(
+ v => v.ToString(),
+ v => (TypeOfSmsSetting)Enum.Parse(typeof(TypeOfSmsSetting), v)).HasMaxLength(70);
+
+
+ }
+}
\ No newline at end of file
diff --git a/CompanyManagment.EFCore/Migrations/20251115080049_SmsSettingsTable.Designer.cs b/CompanyManagment.EFCore/Migrations/20251115080049_SmsSettingsTable.Designer.cs
new file mode 100644
index 00000000..b12b8b81
--- /dev/null
+++ b/CompanyManagment.EFCore/Migrations/20251115080049_SmsSettingsTable.Designer.cs
@@ -0,0 +1,11140 @@
+//
+using System;
+using System.Collections.Generic;
+using CompanyManagment.EFCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace CompanyManagment.EFCore.Migrations
+{
+ [DbContext(typeof(CompanyContext))]
+ [Migration("20251115080049_SmsSettingsTable")]
+ partial class SmsSettingsTable
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.10")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("Company.Domain.AdminMonthlyOverviewAgg.AdminMonthlyOverview", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Month")
+ .HasColumnType("int");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasMaxLength(155)
+ .HasColumnType("nvarchar(155)");
+
+ b.Property("WorkshopId")
+ .HasColumnType("bigint");
+
+ b.Property("Year")
+ .HasColumnType("int");
+
+ b.HasKey("id");
+
+ b.ToTable("AdminMonthlyOverviews");
+ });
+
+ modelBuilder.Entity("Company.Domain.AndroidApkVersionAgg.AndroidApkVersion", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("IsActive")
+ .IsRequired()
+ .HasMaxLength(5)
+ .HasColumnType("nvarchar(5)");
+
+ b.Property("Path")
+ .HasMaxLength(255)
+ .HasColumnType("nvarchar(255)");
+
+ b.Property("Title")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("VersionCode")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property("VersionName")
+ .HasMaxLength(35)
+ .HasColumnType("nvarchar(35)");
+
+ b.HasKey("id");
+
+ b.ToTable("AndroidApkVersions", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetails", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("AccountNumber")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("BankName")
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("CardNumber")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("IBan")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.HasKey("id");
+
+ b.ToTable("AuthorizedBankDetails", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.AuthorizedPersonAgg.AuthorizedPerson", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("BirthDate")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("DeathStatus")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("FatherName")
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("FirstName")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("Gender")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("IsVerified")
+ .HasColumnType("bit");
+
+ b.Property("LastName")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("NationalCode")
+ .IsRequired()
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("ShenasnameSeri")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("ShenasnameSerial")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("ShenasnamehNumber")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property("VerificationDate")
+ .HasColumnType("datetime2");
+
+ b.HasKey("id");
+
+ b.HasIndex("NationalCode")
+ .IsUnique();
+
+ b.ToTable("AuthorizedPersons", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.BankAgg.Bank", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("BankLogoMediaId")
+ .HasColumnType("bigint");
+
+ b.Property("BankName")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.HasKey("id");
+
+ b.ToTable("Banks", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.BillAgg.EntityBill", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("Appointed")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Contact")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsActiveString")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ProcessingStage")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("SubjectBill")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("nvarchar(500)");
+
+ b.HasKey("id");
+
+ b.ToTable("TextManager_Bill", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.Board.Board", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("BoardChairman")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("BoardType_Id")
+ .HasColumnType("int");
+
+ b.Property("Branch")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("DisputeResolutionPetitionDate")
+ .HasColumnType("datetime2");
+
+ b.Property("ExpertReport")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("File_Id")
+ .HasColumnType("bigint");
+
+ b.HasKey("id");
+
+ b.HasIndex("BoardType_Id");
+
+ b.HasIndex("File_Id");
+
+ b.ToTable("Boards", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.BoardType.BoardType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Title")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("BoardTypes", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.ChapterAgg.EntityChapter", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("Chapter")
+ .IsRequired()
+ .HasMaxLength(60)
+ .HasColumnType("nvarchar(60)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("IsActiveString")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Subtitle_Id")
+ .HasColumnType("bigint");
+
+ b.HasKey("id");
+
+ b.HasIndex("Subtitle_Id");
+
+ b.ToTable("TextManager_Chapter", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.CheckoutAgg.Checkout", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("AbsenceDeduction")
+ .HasColumnType("float");
+
+ b.Property("AbsencePeriod")
+ .HasColumnType("float");
+
+ b.Property("AbsenceValue")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("ArchiveCode")
+ .HasMaxLength(15)
+ .HasColumnType("nvarchar(15)");
+
+ b.Property("AverageHoursPerDay")
+ .HasColumnType("float");
+
+ b.Property("BaseYearsPay")
+ .HasColumnType("float");
+
+ b.Property("BonusesPay")
+ .HasColumnType("float");
+
+ b.Property("ConsumableItems")
+ .HasColumnType("float");
+
+ b.Property("ContractEnd")
+ .HasColumnType("datetime2");
+
+ b.Property("ContractId")
+ .HasColumnType("bigint");
+
+ b.Property("ContractNo")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("ContractStart")
+ .HasColumnType("datetime2");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("CreditLeaves")
+ .HasColumnType("float");
+
+ b.Property("DateOfBirth")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("EmployeeFullName")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("EmployeeId")
+ .HasColumnType("bigint");
+
+ b.Property("EmployeeMandatoryHours")
+ .IsRequired()
+ .HasMaxLength(30)
+ .HasColumnType("nvarchar(30)");
+
+ b.Property("FamilyAllowance")
+ .HasColumnType("float");
+
+ b.Property("FathersName")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property("FridayPay")
+ .HasColumnType("float");
+
+ b.Property("FridayWorkValue")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("HasAmountConflict")
+ .HasColumnType("bit");
+
+ b.Property("HasInsuranceShareTheSameAsList")
+ .HasColumnType("bit");
+
+ b.Property("HasRollCall")
+ .HasColumnType("bit");
+
+ b.Property("HousingAllowance")
+ .HasColumnType("float");
+
+ b.Property("InstallmentDeduction")
+ .HasColumnType("float");
+
+ b.Property("InsuranceDeduction")
+ .HasColumnType("float");
+
+ b.Property("IsActiveString")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("IsUpdateNeeded")
+ .HasColumnType("bit");
+
+ b.Property("LeaveCheckout")
+ .HasColumnType("bit");
+
+ b.Property("LeavePay")
+ .HasColumnType("float");
+
+ b.Property("MarriedAllowance")
+ .HasColumnType("float");
+
+ b.Property("MissionPay")
+ .HasColumnType("float");
+
+ b.Property("Month")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("MonthlySalary")
+ .HasColumnType("float");
+
+ b.Property("NationalCode")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("NightworkPay")
+ .HasColumnType("float");
+
+ b.Property("OverNightWorkValue")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("OverTimeWorkValue")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("OvertimePay")
+ .HasColumnType("float");
+
+ b.Property("PersonnelCode")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("RewardPay")
+ .HasColumnType("float");
+
+ b.Property("RotatingShiftValue")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("SalaryAidDeduction")
+ .HasColumnType("float");
+
+ b.Property("ShiftPay")
+ .HasColumnType("float");
+
+ b.Property("Signature")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property("SumOfWorkingDays")
+ .HasMaxLength(6)
+ .HasColumnType("nvarchar(6)");
+
+ b.Property("TaxDeducation")
+ .HasColumnType("float");
+
+ b.Property("TotalClaims")
+ .HasMaxLength(25)
+ .HasColumnType("nvarchar(25)");
+
+ b.Property("TotalDayOfBunosesCompute")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("TotalDayOfLeaveCompute")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("TotalDayOfYearsCompute")
+ .HasMaxLength(10)
+ .HasColumnType("nvarchar(10)");
+
+ b.Property("TotalDeductions")
+ .HasMaxLength(25)
+ .HasColumnType("nvarchar(25)");
+
+ b.Property("TotalPayment")
+ .HasColumnType("float");
+
+ b.Property("WorkingHoursId")
+ .HasColumnType("bigint");
+
+ b.Property("WorkshopId")
+ .HasColumnType("bigint");
+
+ b.Property("WorkshopName")
+ .HasMaxLength(70)
+ .HasColumnType("nvarchar(70)");
+
+ b.Property("Year")
+ .HasMaxLength(4)
+ .HasColumnType("nvarchar(4)");
+
+ b.Property("YearsPay")
+ .HasColumnType("float");
+
+ b.HasKey("id");
+
+ b.HasIndex("WorkshopId");
+
+ b.ToTable("Checkouts", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.CheckoutAgg.CheckoutWarningMessage", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CheckoutId")
+ .HasColumnType("bigint");
+
+ b.Property("TypeOfCheckoutWarning")
+ .IsRequired()
+ .HasMaxLength(30)
+ .HasColumnType("nvarchar(30)");
+
+ b.Property("WarningMessage")
+ .HasMaxLength(150)
+ .HasColumnType("nvarchar(150)");
+
+ b.HasKey("id");
+
+ b.HasIndex("CheckoutId");
+
+ b.ToTable("CheckoutWarningMessage", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.ClassifiedSalaryAgg.ClassifiedSalary", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("EndDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Group1")
+ .HasColumnType("float");
+
+ b.Property("Group10")
+ .HasColumnType("float");
+
+ b.Property("Group11")
+ .HasColumnType("float");
+
+ b.Property("Group12")
+ .HasColumnType("float");
+
+ b.Property("Group13")
+ .HasColumnType("float");
+
+ b.Property("Group14")
+ .HasColumnType("float");
+
+ b.Property("Group15")
+ .HasColumnType("float");
+
+ b.Property("Group16")
+ .HasColumnType("float");
+
+ b.Property("Group17")
+ .HasColumnType("float");
+
+ b.Property("Group18")
+ .HasColumnType("float");
+
+ b.Property("Group19")
+ .HasColumnType("float");
+
+ b.Property("Group2")
+ .HasColumnType("float");
+
+ b.Property("Group20")
+ .HasColumnType("float");
+
+ b.Property("Group3")
+ .HasColumnType("float");
+
+ b.Property("Group4")
+ .HasColumnType("float");
+
+ b.Property("Group5")
+ .HasColumnType("float");
+
+ b.Property("Group6")
+ .HasColumnType("float");
+
+ b.Property("Group7")
+ .HasColumnType("float");
+
+ b.Property("Group8")
+ .HasColumnType("float");
+
+ b.Property("Group9")
+ .HasColumnType("float");
+
+ b.Property("StartDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Year")
+ .HasColumnType("int");
+
+ b.HasKey("id");
+
+ b.ToTable("ClassifiedSalaries", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.ClientEmployeeWorkshopAgg.ClientEmployeeWorkshop", b =>
+ {
+ b.Property("WorkshopId")
+ .HasColumnType("bigint");
+
+ b.Property("EmployeeId")
+ .HasColumnType("bigint");
+
+ b.HasKey("WorkshopId", "EmployeeId");
+
+ b.HasIndex("EmployeeId");
+
+ b.ToTable("ClientWorkshopEmployee", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.Contact2Agg.EntityContact", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("IsActiveString")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("NameContact")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Signature")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("id");
+
+ b.ToTable("TextManager_Contact", (string)null);
+ });
+
+ modelBuilder.Entity("Company.Domain.ContactUsAgg.ContactUs", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .HasMaxLength(200)
+ .HasColumnType("nvarchar(200)");
+
+ b.Property("FirstName")
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("FullName")
+ .HasMaxLength(200)
+ .HasColumnType("nvarchar(200)");
+
+ b.Property("LastName")
+ .HasMaxLength(100)
+ .HasColumnType("nvarchar(100)");
+
+ b.Property("Message")
+ .HasMaxLength(500)
+ .HasColumnType("nvarchar(500)");
+
+ b.Property("PhoneNumber")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property("Title")
+ .HasMaxLength(200)
+ .HasColumnType("nvarchar(200)");
+
+ b.HasKey("id");
+
+ b.ToTable("ContactUs");
+ });
+
+ modelBuilder.Entity("Company.Domain.ContarctingPartyAgg.PersonalContractingParty", b =>
+ {
+ b.Property("id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id"));
+
+ b.Property("Address")
+ .HasMaxLength(500)
+ .HasColumnType("nvarchar(500)");
+
+ b.Property("AgentPhone")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("ArchiveCode")
+ .HasColumnType("int");
+
+ b.Property("BlockTimes")
+ .HasColumnType("int");
+
+ b.Property("CeoFName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CeoLName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("City")
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime2");
+
+ b.Property("DateOfBirth")
+ .HasColumnType("datetime2");
+
+ b.Property("FName")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("nvarchar(50)");
+
+ b.Property("FatherName")
+ .HasMaxLength(20)
+ .HasColumnType("nvarchar(20)");
+
+ b.Property