diff --git a/Sevomin.Models/Helpers/ScheduledTasks/ExpiringJob.cs b/Sevomin.Models/Helpers/ScheduledTasks/ExpiringJob.cs new file mode 100644 index 0000000..ec7fd46 --- /dev/null +++ b/Sevomin.Models/Helpers/ScheduledTasks/ExpiringJob.cs @@ -0,0 +1,25 @@ +using FluentScheduler; +using Sevomin.Models.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sevomin.Models.Helpers.ScheduledTasks +{ + public class ExpiringJob : ITask + { + public async void Execute() + { + var expiringJobs = JobRepository.Current.ListAll().Where(j => j.ExpireDate.Date == DateTime.Now.AddDays(-2).Date); + foreach (var job in expiringJobs) + { + SevominEmailer emailer = new SevominEmailer(); + emailer.EmailType = EmailType.ExpiringJob; + emailer.Parameters.Add("", ""); + await emailer.SendAsync(string.IsNullOrWhiteSpace(job.ContactPersonEMail) ? job.Avalin.Email : job.ContactPersonEMail, "", true); + } + } + } +} \ No newline at end of file diff --git a/Sevomin.Models/Helpers/ScheduledTasks/NewApplication.cs b/Sevomin.Models/Helpers/ScheduledTasks/NewApplication.cs new file mode 100644 index 0000000..90e776d --- /dev/null +++ b/Sevomin.Models/Helpers/ScheduledTasks/NewApplication.cs @@ -0,0 +1,26 @@ +using FluentScheduler; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sevomin.Models.Helpers.ScheduledTasks +{ + public class NewApplication : ITask + { + public async void Execute() + { + var avalins = SevominDbContext.Current.DovominJobs.Where(dj => dj.ApplyDate.Date == DateTime.Now.AddDays(-2).Date).Select(a => a.Job.Avalin); + + foreach (var avalin in avalins.Distinct()) + { + SevominEmailer emailer = new SevominEmailer(); + emailer.EmailType = EmailType.NewApplication; + emailer.Parameters.Add("", ""); + + await emailer.SendAsync(avalin.Email, "", true); + } + } + } +} diff --git a/Sevomin.Models/Helpers/ScheduledTasks/NewJob.cs b/Sevomin.Models/Helpers/ScheduledTasks/NewJob.cs new file mode 100644 index 0000000..f95cee8 --- /dev/null +++ b/Sevomin.Models/Helpers/ScheduledTasks/NewJob.cs @@ -0,0 +1,29 @@ +using FluentScheduler; +using Sevomin.Models.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sevomin.Models.Helpers.ScheduledTasks +{ + public class NewJob : ITask + { + public async void Execute() + { + var newJobs = JobRepository.Current.ListAll().Where(j => j.CreateDate.Date == DateTime.Now.AddDays(-1).Date).ToList(); + if (newJobs.Count > 0) + { + foreach (var dovomin in UserRepository.Current.ListAll().Where(u => u is Dovomin && u.EmailConfirmed)) + { + SevominEmailer emailer = new SevominEmailer(); + emailer.EmailType = EmailType.NewJob; + emailer.Parameters.Add("", ""); + + await emailer.SendAsync(dovomin.Email, "", true); + } + } + } + } +} diff --git a/Sevomin.Models/Helpers/SevominEmailer.cs b/Sevomin.Models/Helpers/SevominEmailer.cs index 7e75273..c4e53ec 100644 --- a/Sevomin.Models/Helpers/SevominEmailer.cs +++ b/Sevomin.Models/Helpers/SevominEmailer.cs @@ -12,7 +12,10 @@ namespace Sevomin.Models.Helpers { EmailConfirmation, PasswordReset, - NewPassword + NewPassword, + NewApplication, + NewJob, + ExpiringJob } public class SevominEmailer @@ -23,6 +26,9 @@ namespace Sevomin.Models.Helpers private string EmailConfirmationFilePath; private string NewPasswordFilePath; private string PasswordResetFilePath; + private string ExpiringJobFilePath; + private string NewJobFilePath; + private string NewApplicationFilePath; public SevominEmailer() { EmailFolderPath = Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/app_data"), "emails"); @@ -31,12 +37,21 @@ namespace Sevomin.Models.Helpers EmailConfirmationFilePath = Path.Combine(EmailFolderPath, "email-confirmation.html"); NewPasswordFilePath = Path.Combine(EmailFolderPath, "new-password.html"); PasswordResetFilePath = Path.Combine(EmailFolderPath, "password-reset.html"); + ExpiringJobFilePath = Path.Combine(EmailFolderPath, "expiring-job.html"); + NewJobFilePath = Path.Combine(EmailFolderPath, "new-job.html"); + NewApplicationFilePath = Path.Combine(EmailFolderPath, "new-application.html"); if(!File.Exists(EmailConfirmationFilePath)) throw new ApplicationException("Email confirmation template does not exist in the right address."); if (!File.Exists(NewPasswordFilePath)) throw new ApplicationException("New password template does not exist in the right address."); if (!File.Exists(PasswordResetFilePath)) throw new ApplicationException("Password reset template does not exist in the right address."); + if (!File.Exists(ExpiringJobFilePath)) + throw new ApplicationException("Expiring job template does not exist in the right address."); + if (!File.Exists(NewJobFilePath)) + throw new ApplicationException("New job template does not exist in the right address."); + if (!File.Exists(NewApplicationFilePath)) + throw new ApplicationException("New application template does not exist in the right address."); Parameters = new Dictionary(); } public SevominEmailer(Dictionary parameters, EmailType emailType) : this() @@ -64,6 +79,18 @@ namespace Sevomin.Models.Helpers template = File.ReadAllText(NewPasswordFilePath, Encoding.UTF8); break; + case EmailType.ExpiringJob: + template = + File.ReadAllText(ExpiringJobFilePath, Encoding.UTF8); + break; + case EmailType.NewApplication: + template = + File.ReadAllText(NewApplicationFilePath, Encoding.UTF8); + break; + case EmailType.NewJob: + template = + File.ReadAllText(NewJobFilePath, Encoding.UTF8); + break; default: template = string.Empty; break; @@ -75,7 +102,7 @@ namespace Sevomin.Models.Helpers msg.SubjectEncoding = Encoding.UTF8; msg.BodyEncoding = Encoding.UTF8; msg.Subject = subject; - msg.IsBodyHtml = isHtml; + msg.IsBodyHtml = isHtml; Func getBody = () => { foreach (var param in Parameters) @@ -90,4 +117,4 @@ namespace Sevomin.Models.Helpers }); } } -} \ No newline at end of file +} diff --git a/Sevomin.Models/Helpers/SevominRegistry.cs b/Sevomin.Models/Helpers/SevominRegistry.cs new file mode 100644 index 0000000..335724c --- /dev/null +++ b/Sevomin.Models/Helpers/SevominRegistry.cs @@ -0,0 +1,20 @@ +using FluentScheduler; +using Sevomin.Models.Helpers.ScheduledTasks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sevomin.Models.Helpers +{ + public class SevominRegistry : Registry + { + public SevominRegistry() + { + Schedule().ToRunEvery(2).Days().At(8, 0); + Schedule().ToRunEvery(1).Days().At(8, 10); + Schedule().ToRunEvery(2).Days().At(8, 20); + } + } +} diff --git a/Sevomin.Models/Repositories/IRepository.cs b/Sevomin.Models/Repositories/IRepository.cs index 149551a..3dda753 100644 --- a/Sevomin.Models/Repositories/IRepository.cs +++ b/Sevomin.Models/Repositories/IRepository.cs @@ -13,6 +13,7 @@ namespace Sevomin.Models.Repositories public interface IUserRepository : IRepository { User FindWithConfirmationCode(string code); + IQueryable ListAll(); } public interface IJobRepository : IRepository diff --git a/Sevomin.Models/Repositories/UserRepository.cs b/Sevomin.Models/Repositories/UserRepository.cs index 72e40a8..2a9655b 100644 --- a/Sevomin.Models/Repositories/UserRepository.cs +++ b/Sevomin.Models/Repositories/UserRepository.cs @@ -57,5 +57,10 @@ namespace Sevomin.Models.Repositories { SevominDbContext.Current.SaveChanges(); } + + public IQueryable ListAll() + { + return SevominDbContext.Current.Users; + } } } diff --git a/Sevomin.Models/Sevomin.Models.csproj b/Sevomin.Models/Sevomin.Models.csproj index 58a3510..3679d4a 100644 --- a/Sevomin.Models/Sevomin.Models.csproj +++ b/Sevomin.Models/Sevomin.Models.csproj @@ -38,6 +38,9 @@ False ..\packages\EntityFramework.6.1.0\lib\net45\EntityFramework.SqlServer.dll + + ..\packages\FluentScheduler.3.1.42\lib\net40\FluentScheduler.dll + ..\packages\MailChimp.NET.1.1.0.2\lib\net40\MailChimp.dll @@ -73,6 +76,10 @@ + + + + diff --git a/Sevomin.Models/packages.config b/Sevomin.Models/packages.config index 06b644b..07da302 100644 --- a/Sevomin.Models/packages.config +++ b/Sevomin.Models/packages.config @@ -1,6 +1,7 @@  + diff --git a/Sevomin.WebFrontend/Global.asax.cs b/Sevomin.WebFrontend/Global.asax.cs index 970960f..527e026 100644 --- a/Sevomin.WebFrontend/Global.asax.cs +++ b/Sevomin.WebFrontend/Global.asax.cs @@ -1,6 +1,10 @@ using Elmah; +using FluentScheduler; using Sevomin.Models; +using Sevomin.Models.Helpers; using Sevomin.WebFrontend.Controllers; +using System; +using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using System.Web.Routing; @@ -13,6 +17,8 @@ namespace Sevomin.WebFrontend { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); + + TaskManager.Initialize(new SevominRegistry()); } void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e) @@ -26,6 +32,13 @@ namespace Sevomin.WebFrontend } } + static void TaskManager_UnobservedTaskException(Task sender, UnhandledExceptionEventArgs e) + { + var error = new Elmah.Error(e.ExceptionObject as Exception); + + Elmah.ErrorLog.GetDefault(System.Web.HttpContext.Current).Log(error); + } + protected void Application_EndRequest() { if (Context.Response.StatusCode == 404) diff --git a/Sevomin.WebFrontend/Sevomin.WebFrontend.csproj b/Sevomin.WebFrontend/Sevomin.WebFrontend.csproj index 2c5667d..f732d0a 100644 --- a/Sevomin.WebFrontend/Sevomin.WebFrontend.csproj +++ b/Sevomin.WebFrontend/Sevomin.WebFrontend.csproj @@ -41,6 +41,9 @@ ..\packages\elmah.corelibrary.1.2.2\lib\Elmah.dll + + ..\packages\FluentScheduler.3.1.42\lib\net40\FluentScheduler.dll + False ..\packages\Microsoft.AspNet.Identity.Core.2.0.0\lib\net45\Microsoft.AspNet.Identity.Core.dll