From d3d94e39a8a43d789bc49bc6e7391623ad996e43 Mon Sep 17 00:00:00 2001 From: DavidMakarov Date: Wed, 29 May 2024 19:29:32 +0400 Subject: [PATCH 1/2] implement mail sending --- .../FactoryBuisinessLogic.csproj | 4 -- .../MailWorker/AbstractMailWorker.cs | 56 +++++++++++++++++++ .../MailWorker/MailKitWorker.cs | 43 ++++++++++++++ .../BindingModels/MailConfigBindingModel.cs | 12 ++++ .../BindingModels/MailSendInfoBindingModel.cs | 9 +++ .../Controllers/HomeController.cs | 18 ++++-- Factory/FactoryStorekeeperApp/Program.cs | 16 ++++++ .../FactoryStorekeeperApp/appsettings.json | 9 ++- 8 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 Factory/FactoryBuisinessLogic/MailWorker/AbstractMailWorker.cs create mode 100644 Factory/FactoryBuisinessLogic/MailWorker/MailKitWorker.cs create mode 100644 Factory/FactoryContracts/BindingModels/MailConfigBindingModel.cs create mode 100644 Factory/FactoryContracts/BindingModels/MailSendInfoBindingModel.cs diff --git a/Factory/FactoryBuisinessLogic/FactoryBuisinessLogic.csproj b/Factory/FactoryBuisinessLogic/FactoryBuisinessLogic.csproj index d7a8bba..3d7e10e 100644 --- a/Factory/FactoryBuisinessLogic/FactoryBuisinessLogic.csproj +++ b/Factory/FactoryBuisinessLogic/FactoryBuisinessLogic.csproj @@ -18,8 +18,4 @@ - - - - diff --git a/Factory/FactoryBuisinessLogic/MailWorker/AbstractMailWorker.cs b/Factory/FactoryBuisinessLogic/MailWorker/AbstractMailWorker.cs new file mode 100644 index 0000000..75b7b60 --- /dev/null +++ b/Factory/FactoryBuisinessLogic/MailWorker/AbstractMailWorker.cs @@ -0,0 +1,56 @@ +using FactoryContracts.BindingModels; +using Microsoft.Extensions.Logging; + +namespace FactoryBuisinessLogic.MailWorker +{ + public abstract class AbstractMailWorker + { + protected string _mailLogin = string.Empty; + protected string _mailPassword = string.Empty; + protected string _smtpClientHost = string.Empty; + protected int _smtpClientPort; + protected string _popHost = string.Empty; + protected int _popPort; + private readonly ILogger _logger; + + public AbstractMailWorker(ILogger logger) + { + _logger = logger; + } + + public void MailConfig(MailConfigBindingModel config) + { + _mailLogin = config.MailLogin; + _mailPassword = config.MailPassword; + _smtpClientHost = config.SmtpClientHost; + _smtpClientPort = config.SmtpClientPort; + _popHost = config.PopHost; + _popPort = config.PopPort; + _logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort); + } + + public async void MailSendAsync(MailSendInfoBindingModel info) + { + if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) + { + return; + } + + if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0) + { + return; + } + + if (string.IsNullOrEmpty(info.MailAddress) || string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text)) + { + return; + } + + _logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject); + + await SendMailAsync(info); + } + + protected abstract Task SendMailAsync(MailSendInfoBindingModel info); + } +} diff --git a/Factory/FactoryBuisinessLogic/MailWorker/MailKitWorker.cs b/Factory/FactoryBuisinessLogic/MailWorker/MailKitWorker.cs new file mode 100644 index 0000000..1248e27 --- /dev/null +++ b/Factory/FactoryBuisinessLogic/MailWorker/MailKitWorker.cs @@ -0,0 +1,43 @@ +using FactoryContracts.BindingModels; +using Microsoft.Extensions.Logging; +using System.Net.Mail; +using System.Net.Mime; +using System.Net; +using System.Text; + +namespace FactoryBuisinessLogic.MailWorker +{ + public class MailKitWorker : AbstractMailWorker + { + public MailKitWorker(ILogger logger) : base(logger) { } + + protected override async Task SendMailAsync(MailSendInfoBindingModel info) + { + using var objMailMessage = new MailMessage(); + using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort); + + try + { + objMailMessage.From = new MailAddress(_mailLogin); + objMailMessage.To.Add(new MailAddress(info.MailAddress)); + objMailMessage.Subject = info.Subject; + objMailMessage.Body = info.Text; + objMailMessage.SubjectEncoding = Encoding.UTF8; + objMailMessage.BodyEncoding = Encoding.UTF8; + Attachment attachment = new Attachment("D:\\temp\\report.pdf", new ContentType(MediaTypeNames.Application.Pdf)); + objMailMessage.Attachments.Add(attachment); + + objSmtpClient.UseDefaultCredentials = false; + objSmtpClient.EnableSsl = true; + objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword); + + await Task.Run(() => objSmtpClient.Send(objMailMessage)); + } + catch (Exception) + { + throw; + } + } + } +} diff --git a/Factory/FactoryContracts/BindingModels/MailConfigBindingModel.cs b/Factory/FactoryContracts/BindingModels/MailConfigBindingModel.cs new file mode 100644 index 0000000..7a90390 --- /dev/null +++ b/Factory/FactoryContracts/BindingModels/MailConfigBindingModel.cs @@ -0,0 +1,12 @@ +namespace FactoryContracts.BindingModels +{ + public class MailConfigBindingModel + { + public string MailLogin { get; set; } = string.Empty; + public string MailPassword { get; set; } = string.Empty; + public string SmtpClientHost { get; set; } = string.Empty; + public int SmtpClientPort { get; set; } + public string PopHost { get; set; } = string.Empty; + public int PopPort { get; set; } + } +} diff --git a/Factory/FactoryContracts/BindingModels/MailSendInfoBindingModel.cs b/Factory/FactoryContracts/BindingModels/MailSendInfoBindingModel.cs new file mode 100644 index 0000000..6caed45 --- /dev/null +++ b/Factory/FactoryContracts/BindingModels/MailSendInfoBindingModel.cs @@ -0,0 +1,9 @@ +namespace FactoryContracts.BindingModels +{ + public class MailSendInfoBindingModel + { + public string MailAddress { get; set; } = string.Empty; + public string Subject { get; set; } = string.Empty; + public string Text { get; set; } = string.Empty; + } +} diff --git a/Factory/FactoryStorekeeperApp/Controllers/HomeController.cs b/Factory/FactoryStorekeeperApp/Controllers/HomeController.cs index bbabb9d..81c740c 100644 --- a/Factory/FactoryStorekeeperApp/Controllers/HomeController.cs +++ b/Factory/FactoryStorekeeperApp/Controllers/HomeController.cs @@ -1,4 +1,5 @@ -using FactoryContracts.BindingModels; +using FactoryBuisinessLogic.MailWorker; +using FactoryContracts.BindingModels; using FactoryContracts.BusinessLogicsContracts; using FactoryContracts.SearchModels; using FactoryContracts.ViewModels; @@ -19,13 +20,14 @@ namespace FactoryStorekeeperApp.Controllers private readonly IProductLogic productLogic; private readonly IPlanProductionLogic planProductionLogic; private readonly IStorekeeperReportLogic storekeeperReportLogic; + private readonly AbstractMailWorker abstractMailWorker; private static bool IsLoggedIn { get { return Client.client != null; } } public HomeController(ILogger logger, IClientLogic clientLogic, IRequirementLogic requirementLogic, IProductLogic productLogic, IMachineLogic machineLogic, IPlanProductionLogic planProductionLogic, - IStorekeeperReportLogic storekeeperReportLogic) + IStorekeeperReportLogic storekeeperReportLogic, AbstractMailWorker abstractMailWorker) { _logger = logger; this.clientLogic = clientLogic; @@ -34,6 +36,7 @@ namespace FactoryStorekeeperApp.Controllers this.machineLogic = machineLogic; this.planProductionLogic = planProductionLogic; this.storekeeperReportLogic = storekeeperReportLogic; + this.abstractMailWorker = abstractMailWorker; } public IActionResult Index() @@ -538,8 +541,13 @@ namespace FactoryStorekeeperApp.Controllers DateTo = dateto, FileName="D:\\temp\\report.pdf" }); - // TODO: implement sending - throw new NotImplementedException(); - } + abstractMailWorker.MailSendAsync(new MailSendInfoBindingModel + { + MailAddress = Client.client.Email, + Subject = $"Отчет по станкам пользователя {Client.client.Login}", + Text = $"Отчет по станкам с {datefrom.ToShortDateString()} по {dateto.ToShortDateString()}" + }); + return Redirect("~/Home/Index"); + } } } diff --git a/Factory/FactoryStorekeeperApp/Program.cs b/Factory/FactoryStorekeeperApp/Program.cs index 77539bd..cc4ee48 100644 --- a/Factory/FactoryStorekeeperApp/Program.cs +++ b/Factory/FactoryStorekeeperApp/Program.cs @@ -1,6 +1,8 @@ +using FactoryBuisinessLogic.MailWorker; using FactoryBusinessLogic.BusinessLogics; using FactoryBusinessLogic.OfficePackage; using FactoryBusinessLogic.OfficePackage.Implements; +using FactoryContracts.BindingModels; using FactoryContracts.BusinessLogicsContracts; using FactoryContracts.StoragesContracts; using FactoryDatabaseImplement.Implements; @@ -25,10 +27,24 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddSingleton(); + builder.Services.AddControllersWithViews(); var app = builder.Build(); +var mailSender = app.Services.GetService(); + +mailSender?.MailConfig(new MailConfigBindingModel +{ + MailLogin = builder.Configuration?.GetSection("MailLogin")?.Value?.ToString() ?? string.Empty, + MailPassword = builder.Configuration?.GetSection("MailPassword")?.Value?.ToString() ?? string.Empty, + SmtpClientHost = builder.Configuration?.GetSection("SmtpClientHost")?.Value?.ToString() ?? string.Empty, + SmtpClientPort = Convert.ToInt32(builder.Configuration?.GetSection("SmtpClientPort")?.Value?.ToString()), + PopHost = builder.Configuration?.GetSection("PopHost")?.Value?.ToString() ?? string.Empty, + PopPort = Convert.ToInt32(builder.Configuration?.GetSection("PopPort")?.Value?.ToString()) +}); + // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { diff --git a/Factory/FactoryStorekeeperApp/appsettings.json b/Factory/FactoryStorekeeperApp/appsettings.json index eed7524..60e0a72 100644 --- a/Factory/FactoryStorekeeperApp/appsettings.json +++ b/Factory/FactoryStorekeeperApp/appsettings.json @@ -7,5 +7,12 @@ }, "AllowedHosts": "*", - "IPAddress": "http://localhost:5283/" + "IPAddress": "http://localhost:5283/", + + "SmtpClientHost": "smtp.gmail.com", + "SmtpClientPort": "587", + "PopHost": "pop.gmail.com", + "PopPort": "995", + "MailLogin": "labworker83@gmail.com", + "MailPassword": "wpxc drvx lhqb uqpe" } From 3f010876a14046a10c4c89dedc3cfbdf48f910db Mon Sep 17 00:00:00 2001 From: DavidMakarov Date: Wed, 29 May 2024 21:13:28 +0400 Subject: [PATCH 2/2] WorkpieceStorage add GetTimeReport --- .../BusinessLogics/WorkerReportLogic.cs | 1 + .../SearchModels/MachineSearchModel.cs | 2 +- .../WorkpieceTimeReportViewModel.cs | 4 +-- .../Implements/MachineStorage.cs | 3 --- .../Implements/WorkpieceStorage.cs | 26 +++++++++++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Factory/FactoryBuisinessLogic/BusinessLogics/WorkerReportLogic.cs b/Factory/FactoryBuisinessLogic/BusinessLogics/WorkerReportLogic.cs index c6a2964..e7f1299 100644 --- a/Factory/FactoryBuisinessLogic/BusinessLogics/WorkerReportLogic.cs +++ b/Factory/FactoryBuisinessLogic/BusinessLogics/WorkerReportLogic.cs @@ -36,6 +36,7 @@ namespace FactoryBusinessLogic.BusinessLogics } return products; } + public void SaveWorkpiecesToPdfFile(ClientSearchModel client, ReportBindingModel model) { _saveToPdf.CreateWorkerDoc(new WorkerPdfInfo diff --git a/Factory/FactoryContracts/SearchModels/MachineSearchModel.cs b/Factory/FactoryContracts/SearchModels/MachineSearchModel.cs index 62b976f..0247124 100644 --- a/Factory/FactoryContracts/SearchModels/MachineSearchModel.cs +++ b/Factory/FactoryContracts/SearchModels/MachineSearchModel.cs @@ -4,7 +4,7 @@ { public int? Id { get; set; } public string? MachineName { get; set; } - public int WorkpieceId { get; set; } + public int? WorkpieceId { get; set; } public int ClientId { get; set; } } } diff --git a/Factory/FactoryContracts/ViewModels/WorkpieceTimeReportViewModel.cs b/Factory/FactoryContracts/ViewModels/WorkpieceTimeReportViewModel.cs index 4cbb25e..5ce358f 100644 --- a/Factory/FactoryContracts/ViewModels/WorkpieceTimeReportViewModel.cs +++ b/Factory/FactoryContracts/ViewModels/WorkpieceTimeReportViewModel.cs @@ -3,7 +3,7 @@ public class WorkpieceTimeReportViewModel { public string WorkpieceName { get; set; } = string.Empty; - public List ExecutionPhases { get; set; } = new(); - public List Machines { get; set; } = new(); + public List ExecutionPhases { get; set; } = new(); + public List Machines { get; set; } = new(); } } diff --git a/Factory/FactoryDatabaseImplement/Implements/MachineStorage.cs b/Factory/FactoryDatabaseImplement/Implements/MachineStorage.cs index b930383..0111704 100644 --- a/Factory/FactoryDatabaseImplement/Implements/MachineStorage.cs +++ b/Factory/FactoryDatabaseImplement/Implements/MachineStorage.cs @@ -23,9 +23,6 @@ namespace FactoryDatabaseImplement.Implements public List GetFilteredList(MachineSearchModel model) { using var context = new FactoryDatabase(); - if (model.WorkpieceId.HasValue) - return context.Machines.Include(x => x.PlanProductions).Where(x => x.PlanProduction.Workpieces.FirstOrDefault(y => y.WorkpieceId == model.WorkpieceId) != null).Select(x => x.GetViewModel).ToList(); - if (!string.IsNullOrEmpty(model.MachineName)) { return context.Machines diff --git a/Factory/FactoryDatabaseImplement/Implements/WorkpieceStorage.cs b/Factory/FactoryDatabaseImplement/Implements/WorkpieceStorage.cs index a5277cb..447fe69 100644 --- a/Factory/FactoryDatabaseImplement/Implements/WorkpieceStorage.cs +++ b/Factory/FactoryDatabaseImplement/Implements/WorkpieceStorage.cs @@ -103,5 +103,31 @@ namespace FactoryDatabaseImplement.Implements } return null; } + + public List GetTimeReport(ClientSearchModel client, ReportBindingModel model) + { + using var context = new FactoryDatabase(); + return context.Workpieces + .Include(x => x.Client) + .Include(x => x.PlanProductions) + .ThenInclude(x => x.PlanProduction) + .Select(x => new WorkpieceTimeReportViewModel + { + WorkpieceName = x.WorkpieceName, + Machines = context.PlanProductionWorkpieces + .Include(x => x.PlanProduction) + .Where(ppw => ppw.WorkpieceId == x.Id) + .Select(ppw => ppw.PlanProduction.Machines + .Where(m => m.PlanProductionId == ppw.PlanProductionId) + .Select(m => m.Machine.GetViewModel).ToList()).FirstOrDefault()!, + ExecutionPhases = context.ExecutionPhases + .Where(ep => ep.PlanProductionId.HasValue) + .Include(ep => ep.PlanProduction) + .Where(ep => ep.PlanProduction.Workpieces + .FirstOrDefault(y => y.WorkpieceId == x.Id) != null) + .Select(x => x.GetViewModel).ToList() + + }).ToList(); + } } } \ No newline at end of file