From 675971d32f59be1dd6133d3fddaab1465cd6fa2d Mon Sep 17 00:00:00 2001 From: prodigygirl Date: Fri, 19 May 2023 08:30:36 +0400 Subject: [PATCH] =?UTF-8?q?=D0=AD=D1=82=D0=B0=D0=BF=203.=20=D0=9F=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82=D1=87?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=B2=20pdf=20=D0=BD=D0=B0=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=87=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HospitalBusinessLogic/ApothecaryLogic.cs | 5 ++ .../HospitalBusinessLogic.csproj | 1 + .../MailWorker/AbstractMailWorker.cs | 54 +++++++++++++ .../MailWorker/MailKitWorker.cs | 40 ++++++++++ Hospital/HospitalBusinessLogic/ReportLogic.cs | 24 +++++- .../BindingModels/MailConfigBindingModel.cs | 10 +++ .../BindingModels/MailSendInfoBindingModel.cs | 13 +++ .../BindingModels/ReportBindingModel.cs | 1 + .../BusinessLogicContracts/IReportLogic.cs | 4 +- .../Controllers/ApothecaryController.cs | 20 +---- .../Controllers/ReportController.cs | 11 ++- Hospital/HospitalRestApi/Program.cs | 15 +++- Hospital/HospitalRestApi/appsettings.json | 7 +- .../Controllers/ReportController.cs | 48 +++++++---- .../HospitalWeb/Views/Recipe/Create.cshtml | 80 +++++++++---------- .../Views/Report/ReportPrescriptions.cshtml | 28 ++++++- 16 files changed, 273 insertions(+), 88 deletions(-) create mode 100644 Hospital/HospitalBusinessLogic/MailWorker/AbstractMailWorker.cs create mode 100644 Hospital/HospitalBusinessLogic/MailWorker/MailKitWorker.cs create mode 100644 Hospital/HospitalContracts/BindingModels/MailConfigBindingModel.cs create mode 100644 Hospital/HospitalContracts/BindingModels/MailSendInfoBindingModel.cs diff --git a/Hospital/HospitalBusinessLogic/ApothecaryLogic.cs b/Hospital/HospitalBusinessLogic/ApothecaryLogic.cs index ddf0a90..2c0fcec 100644 --- a/Hospital/HospitalBusinessLogic/ApothecaryLogic.cs +++ b/Hospital/HospitalBusinessLogic/ApothecaryLogic.cs @@ -4,6 +4,7 @@ using HospitalContracts.SearchModels; using HospitalContracts.StorageContracts; using HospitalContracts.ViewModels; using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; namespace HospitalBusinessLogic { @@ -103,6 +104,10 @@ namespace HospitalBusinessLogic throw new ArgumentNullException("Нет пароля пользователя", nameof(model.Password)); } + if (!Regex.IsMatch(model.Login, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,})+)$")) + { + throw new ArgumentException("Некорректно введена почта клиента", nameof(model.Login)); + } if (model.Password.Length < 5 || model.Password.Length > 15) { throw new ArgumentNullException("Пароль должен иметь длину от 5 до 15 символов", diff --git a/Hospital/HospitalBusinessLogic/HospitalBusinessLogic.csproj b/Hospital/HospitalBusinessLogic/HospitalBusinessLogic.csproj index b6a47db..7c6df20 100644 --- a/Hospital/HospitalBusinessLogic/HospitalBusinessLogic.csproj +++ b/Hospital/HospitalBusinessLogic/HospitalBusinessLogic.csproj @@ -8,6 +8,7 @@ + diff --git a/Hospital/HospitalBusinessLogic/MailWorker/AbstractMailWorker.cs b/Hospital/HospitalBusinessLogic/MailWorker/AbstractMailWorker.cs new file mode 100644 index 0000000..c1c12d1 --- /dev/null +++ b/Hospital/HospitalBusinessLogic/MailWorker/AbstractMailWorker.cs @@ -0,0 +1,54 @@ +using DocumentFormat.OpenXml.EMMA; +using HospitalContracts.BindingModels; +using HospitalContracts.BusinessLogicContracts; +using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; + +namespace HospitalBusinessLogic.MailWorker +{ + public abstract class AbstractMailWorker + { + protected string _mailLogin = string.Empty; + protected string _mailPassword = string.Empty; + protected string _smtpClientHost = string.Empty; + protected int _smtpClientPort; + 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; + _logger.LogDebug("Config: {login}, {password}, {clientHost},{ clientPOrt}", _mailLogin, _mailPassword, _smtpClientHost, + _smtpClientPort); + } + 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; + } + if (!Regex.IsMatch(info.MailAddress, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,})+)$")) + { + return; + } + _logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject); + await SendMailAsync(info); + } + protected abstract Task SendMailAsync(MailSendInfoBindingModel info); + } +} diff --git a/Hospital/HospitalBusinessLogic/MailWorker/MailKitWorker.cs b/Hospital/HospitalBusinessLogic/MailWorker/MailKitWorker.cs new file mode 100644 index 0000000..e3f5436 --- /dev/null +++ b/Hospital/HospitalBusinessLogic/MailWorker/MailKitWorker.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Logging; +using System.Net.Mail; +using System.Net; +using System.Text; +using MailKit.Net.Pop3; +using MailKit.Security; +using HospitalContracts.BindingModels; + +namespace HospitalBusinessLogic.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; + info.Attachments.ForEach(attachment => 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/Hospital/HospitalBusinessLogic/ReportLogic.cs b/Hospital/HospitalBusinessLogic/ReportLogic.cs index 76f3535..635b9e2 100644 --- a/Hospital/HospitalBusinessLogic/ReportLogic.cs +++ b/Hospital/HospitalBusinessLogic/ReportLogic.cs @@ -1,4 +1,5 @@ -using HospitalBusinessLogic.OfficePackage; +using HospitalBusinessLogic.MailWorker; +using HospitalBusinessLogic.OfficePackage; using HospitalBusinessLogic.OfficePackage.HelperModels; using HospitalBusinessLogic.OfficePackage.Implements; using HospitalContracts.BindingModels; @@ -7,6 +8,7 @@ using HospitalContracts.SearchModels; using HospitalContracts.StorageContracts; using HospitalContracts.ViewModels; using System.Linq; +using System.Net.Mail; namespace HospitalBusinessLogic { @@ -23,10 +25,12 @@ namespace HospitalBusinessLogic private readonly AbstractSaveToWord _saveToWord; private readonly AbstractSaveToPdf _saveToPdf; + private readonly AbstractMailWorker _mailWorker; + public ReportLogic(IMedicineStorage medicineStorage, IPatientStorage patientStorage, IPrescriptionStorage prescriptionStorage, ITreatmentStorage treatmentStorage, IProcedureStorage procedureStorage, IRecipeStorage recipeStorage, - AbstractSaveToExcel abstractSaveToExcel, AbstractSaveToWord abstractSaveToWord, AbstractSaveToPdf abstractSaveToPdf) + AbstractSaveToExcel abstractSaveToExcel, AbstractSaveToWord abstractSaveToWord, AbstractSaveToPdf abstractSaveToPdf, AbstractMailWorker abstractMailWorker) { _medicineStorage = medicineStorage; _patientStorage = patientStorage; @@ -38,6 +42,8 @@ namespace HospitalBusinessLogic _saveToExcel = abstractSaveToExcel; _saveToWord = abstractSaveToWord; _saveToPdf = abstractSaveToPdf; + + _mailWorker = abstractMailWorker; } public List GetMedicinePatients(ReportBindingModel model) @@ -138,7 +144,19 @@ namespace HospitalBusinessLogic public void SendMailWithReportAttachments(ReportBindingModel model) { var stream = SavePrescriptionsToPdfFile(model); - + if (stream == null) + { + throw new Exception("Pdf-document is not created"); + } + var attachments = new List(); + attachments.Add(new Attachment(stream, $"report-{DateTime.Now.ToShortDateString()}.pdf")); + _mailWorker.MailSendAsync(new MailSendInfoBindingModel() + { + Subject = "Отчет \"Поступления\"", + Text = $"Отчет по поступлениям лекарств, требующихся для выполнения процедур, за период с {model.DateFrom} по {model.DateTo}", + MailAddress = model.Email, + Attachments = attachments + }); } } } diff --git a/Hospital/HospitalContracts/BindingModels/MailConfigBindingModel.cs b/Hospital/HospitalContracts/BindingModels/MailConfigBindingModel.cs new file mode 100644 index 0000000..abac923 --- /dev/null +++ b/Hospital/HospitalContracts/BindingModels/MailConfigBindingModel.cs @@ -0,0 +1,10 @@ +namespace HospitalContracts.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; } + } +} diff --git a/Hospital/HospitalContracts/BindingModels/MailSendInfoBindingModel.cs b/Hospital/HospitalContracts/BindingModels/MailSendInfoBindingModel.cs new file mode 100644 index 0000000..758a6ed --- /dev/null +++ b/Hospital/HospitalContracts/BindingModels/MailSendInfoBindingModel.cs @@ -0,0 +1,13 @@ +using System.Net.Mail; + +namespace HospitalContracts.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; + + public List Attachments { get; set; } = new(); + } +} diff --git a/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs b/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs index d722c80..833f783 100644 --- a/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs +++ b/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs @@ -14,5 +14,6 @@ namespace HospitalContracts.BindingModels public DateTime? DateTo { get; set; } // выбранные лекарства public List Medicines { get; set; } = new(); + public string Email { get; set; } = string.Empty; } } diff --git a/Hospital/HospitalContracts/BusinessLogicContracts/IReportLogic.cs b/Hospital/HospitalContracts/BusinessLogicContracts/IReportLogic.cs index 00c2e0a..f8ae011 100644 --- a/Hospital/HospitalContracts/BusinessLogicContracts/IReportLogic.cs +++ b/Hospital/HospitalContracts/BusinessLogicContracts/IReportLogic.cs @@ -27,9 +27,9 @@ namespace HospitalContracts.BusinessLogicContracts /// MemoryStream SavePatientsToExcelFile(ReportBindingModel model); /// - /// Сохранение пациентов с указанием лекарств в файл-Pdf + /// Отправка отчета на почту по поступлением с указанием лекарств и процедур в файл-Pdf /// /// - MemoryStream SavePrescriptionsToPdfFile(ReportBindingModel model); + void SendMailWithReportAttachments(ReportBindingModel model); } } diff --git a/Hospital/HospitalRestApi/Controllers/ApothecaryController.cs b/Hospital/HospitalRestApi/Controllers/ApothecaryController.cs index 18ab231..425e04d 100644 --- a/Hospital/HospitalRestApi/Controllers/ApothecaryController.cs +++ b/Hospital/HospitalRestApi/Controllers/ApothecaryController.cs @@ -13,13 +13,11 @@ namespace HospitalRestApi.Controllers { private readonly ILogger _logger; private readonly IApothecaryLogic _logic; - //private readonly IMessageInfoLogic _mailLogic; public ApothecaryController(IApothecaryLogic logic, ILogger logger) { _logger = logger; _logic = logic; - //_mailLogic = mailLogic; } [HttpGet] @@ -64,22 +62,6 @@ namespace HospitalRestApi.Controllers _logger.LogError(ex, "Ошибка обновления данных"); throw; } - } - /* [HttpGet] - public List? GetMessages(int clientId) - { - try - { - return _mailLogic.ReadList(new MessageInfoSearchModel - { - ClientId = clientId - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка получения писем клиента"); - throw; - } - }*/ + } } } diff --git a/Hospital/HospitalRestApi/Controllers/ReportController.cs b/Hospital/HospitalRestApi/Controllers/ReportController.cs index 0cdeb79..f11fbfe 100644 --- a/Hospital/HospitalRestApi/Controllers/ReportController.cs +++ b/Hospital/HospitalRestApi/Controllers/ReportController.cs @@ -67,18 +67,17 @@ namespace HospitalRestApi.Controllers throw; } } + [HttpPost] - public ActionResult GetReportPrescriptionsPdf(DateTime startDate, DateTime endDate, ReportBindingModel model) + public void SendReportPrescriptionsPdf(ReportBindingModel model) { try { - var stream = _logic.SavePrescriptionsToPdfFile(model); - return File(stream, "application/pdf", "pdf.pdf"); - - } + _logic.SendMailWithReportAttachments(model); + } catch (Exception ex) { - _logger.LogError(ex, "Ошибка получения списка пациентов"); + _logger.LogError(ex, "Ошибка при отправке отчета на почту"); throw; } } diff --git a/Hospital/HospitalRestApi/Program.cs b/Hospital/HospitalRestApi/Program.cs index 274fc68..d01dde9 100644 --- a/Hospital/HospitalRestApi/Program.cs +++ b/Hospital/HospitalRestApi/Program.cs @@ -1,11 +1,14 @@ using HospitalBusinessLogic; +using HospitalBusinessLogic.MailWorker; using HospitalBusinessLogic.OfficePackage; using HospitalBusinessLogic.OfficePackage.Implements; +using HospitalContracts.BindingModels; using HospitalContracts.BusinessLogicContracts; using HospitalContracts.StorageContracts; using HospitalDatabaseImplement.Implements; using Microsoft.OpenApi.Models; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. @@ -31,7 +34,7 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); -//builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddControllers().AddJsonOptions((option) => { @@ -50,8 +53,18 @@ builder.Services.AddSwaggerGen(c => }); }); + 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()), +}); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { diff --git a/Hospital/HospitalRestApi/appsettings.json b/Hospital/HospitalRestApi/appsettings.json index 10f68b8..ad96a1d 100644 --- a/Hospital/HospitalRestApi/appsettings.json +++ b/Hospital/HospitalRestApi/appsettings.json @@ -5,5 +5,10 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + + "SmtpClientHost": "smtp.gmail.com", + "SmtpClientPort": "587", + "MailLogin": "MailNoNameLab@gmail.com", + "MailPassword": "yfbo xzzw mxee jaqt" } diff --git a/Hospital/HospitalWeb/Controllers/ReportController.cs b/Hospital/HospitalWeb/Controllers/ReportController.cs index 37e6186..6deafbb 100644 --- a/Hospital/HospitalWeb/Controllers/ReportController.cs +++ b/Hospital/HospitalWeb/Controllers/ReportController.cs @@ -14,32 +14,52 @@ namespace HospitalWeb.Controllers [HttpGet("/reports/patients")] public IActionResult ReportPatients() { + if (APIClient.Apothecary == null) + { + return Redirect("~/Home/Enter"); + } ViewBag.Medicines = APIClient.GetRequest>($"api/medicine/getmedicines"); return View(); } [HttpGet("/reports/precriptions")] public IActionResult ReportPrescriptions(List? report) - { + { + if (APIClient.Apothecary == null) + { + return Redirect("~/Home/Enter"); + } return View(report); } [HttpGet("/report/getprescriptions")] public IActionResult GetPrescriptions(DateTime startDate, DateTime endDate, string type) { - /* // если type - получение отчета на форме - // Преобразуем даты к нужному формату - string startDateString = startDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); - string endDateString = endDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); - var report = APIClient.GetRequest>($"api/report/getreportprescriptions?startDate={startDateString}&endDate={endDateString}"); - return View("ReportPrescriptions", report);*/ - // иначе отправка на почту - string startDateString = startDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); - string endDateString = endDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); - var fileData = APIClient.GetFileRequest($"api/report/getreportprescriptionspdf?", new ReportBindingModel { DateFrom = startDate, DateTo = endDate }); - if (fileData != null) - return File(fileData.Value.stream, fileData.Value.contentType!, "prescriptions.pdf"); - throw new Exception($"Failed to retrieve file from."); + if (APIClient.Apothecary == null) + { + return Redirect("~/Home/Enter"); + } + + if (type == "email") + { + APIClient.PostRequest($"api/report/sendreportprescriptionspdf", new ReportBindingModel { DateFrom = startDate, DateTo = endDate, Email = APIClient.Apothecary.Login }); + ViewBag.EmailSent = true; + ViewBag.EmailAddress = APIClient.Apothecary.Login; + return View("ReportPrescriptions"); + } + else if (type == "form") + { + // Преобразуем даты к нужному формату + string startDateString = startDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); + string endDateString = endDate.ToString("yyyy-MM-dd HH:mm:ss.fffffff"); + var report = APIClient.GetRequest>($"api/report/getreportprescriptions?startDate={startDateString}&endDate={endDateString}"); + return View("ReportPrescriptions", report); + } + else + { + return BadRequest("Invalid report type"); + } + } [HttpGet("/reports/download")] diff --git a/Hospital/HospitalWeb/Views/Recipe/Create.cshtml b/Hospital/HospitalWeb/Views/Recipe/Create.cshtml index 5eae7af..ada2f18 100644 --- a/Hospital/HospitalWeb/Views/Recipe/Create.cshtml +++ b/Hospital/HospitalWeb/Views/Recipe/Create.cshtml @@ -9,57 +9,57 @@ if (Model.Id > 0) {
-

Редактирование рецепта

+

Редактирование рецепта

} else {
-

Создание рецепта

+

Создание рецепта

}
- -
-
Название:
-
-
-
-
Добавление лекарств
-
- - + +
+
Название:
+
+
+
+
Добавление лекарств
+
+ + +
-
-
- - - - - - - - - @foreach (var medicine in Model.RecipeMedicines) +
+
Название
+ + + + + + + + @foreach (var medicine in Model.RecipeMedicines) { - - - - + + + + } - -
Название
@medicine.Value.Name - -
@medicine.Value.Name + +
-
-
-
-
- + +
-
- @foreach (var medicine in Model.RecipeMedicines.Keys) +
+
+
+ +
+
+ @foreach (var medicine in Model.RecipeMedicines.Keys) { - + } } @@ -75,7 +75,7 @@ } recipeMedicines[medicineId] = { Id: medicineId, Name: medicineName }; var row = $('').append($('').text(medicineName)); - var removeButton = $('
- +
- +
@if (Model != null && Model.Any()) @@ -48,4 +48,28 @@ } +} + +@section scripts { + @if (ViewBag.EmailSent != null && ViewBag.EmailSent) + { + + } } \ No newline at end of file