From c529bcf1b93a753a86cf610580793072848e4a38 Mon Sep 17 00:00:00 2001
From: prodigygirl <Prodigygirl1.0@yandex.ru>
Date: Thu, 18 May 2023 18:23:17 +0400
Subject: [PATCH] =?UTF-8?q?=D0=AD=D1=82=D0=B0=D0=BF=202.=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=20=D0=BD=D0=B0=20=D1=84=D0=BE=D1=80?=
 =?UTF-8?q?=D0=BC=D1=83=20=D0=B8=D0=BB=D0=B8=20=D0=BD=D0=B0=20=D1=81=D0=BA?=
 =?UTF-8?q?=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Controllers/ReportController.cs           | 87 +++++++++++++++++++
 Hospital/HospitalRestApi/Program.cs           |  7 +-
 Hospital/HospitalWeb/APIClient.cs             | 19 ++++
 .../Controllers/RecipeController.cs           |  2 -
 .../Controllers/ReportController.cs           | 62 +++++++++++++
 Hospital/HospitalWeb/HelpModels/FileFormat.cs |  8 ++
 .../Views/Report/ReportPatients.cshtml        | 34 ++++++++
 .../Views/Report/ReportPrescriptions.cshtml   | 51 +++++++++++
 .../HospitalWeb/Views/Shared/_Layout.cshtml   |  9 ++
 9 files changed, 275 insertions(+), 4 deletions(-)
 create mode 100644 Hospital/HospitalRestApi/Controllers/ReportController.cs
 create mode 100644 Hospital/HospitalWeb/Controllers/ReportController.cs
 create mode 100644 Hospital/HospitalWeb/HelpModels/FileFormat.cs
 create mode 100644 Hospital/HospitalWeb/Views/Report/ReportPatients.cshtml
 create mode 100644 Hospital/HospitalWeb/Views/Report/ReportPrescriptions.cshtml

diff --git a/Hospital/HospitalRestApi/Controllers/ReportController.cs b/Hospital/HospitalRestApi/Controllers/ReportController.cs
new file mode 100644
index 0000000..0cdeb79
--- /dev/null
+++ b/Hospital/HospitalRestApi/Controllers/ReportController.cs
@@ -0,0 +1,87 @@
+using HospitalContracts.BindingModels;
+using HospitalContracts.BusinessLogicContracts;
+using HospitalContracts.ViewModels;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System.IO;
+
+namespace HospitalRestApi.Controllers
+{
+	[Route("api/[controller]/[action]")]
+	[ApiController]
+    [ApiExplorerSettings(IgnoreApi = true)]
+    public class ReportController : ControllerBase
+	{
+        private readonly ILogger _logger;
+        private readonly IReportLogic _logic;
+
+        public ReportController(ILogger<ReportController> logger, IReportLogic logic)
+        {
+            _logger = logger;
+            _logic = logic;
+        }
+
+        [HttpPost]
+        public ActionResult GetReportPatientsToExcelFile(ReportBindingModel model)
+        {
+            try
+            {
+                var stream = _logic.SavePatientsToExcelFile(model);
+                return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", model.FileName);
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка получения списка пациентов");
+                throw;
+            }
+        }
+
+        [HttpPost]
+        public ActionResult GetReportPatientsToWordFile(ReportBindingModel model)
+        {
+            try
+            {
+                var stream = _logic.SavePatientsToWordFile(model);
+                return File(stream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", model.FileName);
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка получения списка пациентов");
+                throw;
+            }
+        }
+
+        [HttpGet]
+        public List<ReportPrescriptionProcedureViewModel> GetReportPrescriptions(DateTime startDate, DateTime endDate)
+        {
+            try
+            {               
+                return _logic.GetPrescriptionProcedures(new ReportBindingModel { DateFrom = startDate, DateTo = endDate});
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка получения списка пациентов");
+                throw;
+            }
+        }
+        [HttpPost]
+        public ActionResult GetReportPrescriptionsPdf(DateTime startDate, DateTime endDate, ReportBindingModel model)
+        {
+            try
+            {
+                var stream = _logic.SavePrescriptionsToPdfFile(model);
+                return File(stream, "application/pdf", "pdf.pdf");
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка получения списка пациентов");
+                throw;
+            }
+        }
+
+    }
+}
diff --git a/Hospital/HospitalRestApi/Program.cs b/Hospital/HospitalRestApi/Program.cs
index 6d976d8..274fc68 100644
--- a/Hospital/HospitalRestApi/Program.cs
+++ b/Hospital/HospitalRestApi/Program.cs
@@ -1,4 +1,6 @@
 using HospitalBusinessLogic;
+using HospitalBusinessLogic.OfficePackage;
+using HospitalBusinessLogic.OfficePackage.Implements;
 using HospitalContracts.BusinessLogicContracts;
 using HospitalContracts.StorageContracts;
 using HospitalDatabaseImplement.Implements;
@@ -26,8 +28,9 @@ builder.Services.AddTransient<ITreatmentLogic, TreatmentLogic>();
 
 builder.Services.AddTransient<IReportLogic, ReportLogic>();
 
-//builder.Services.AddTransient<AbstractSaveToWord, SaveToWord>();
-//builder.Services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
+builder.Services.AddTransient<AbstractSaveToWord, SaveToWord>();
+builder.Services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
+builder.Services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
 //builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
 
 builder.Services.AddControllers().AddJsonOptions((option) =>
diff --git a/Hospital/HospitalWeb/APIClient.cs b/Hospital/HospitalWeb/APIClient.cs
index c19ace9..43bc143 100644
--- a/Hospital/HospitalWeb/APIClient.cs
+++ b/Hospital/HospitalWeb/APIClient.cs
@@ -41,5 +41,24 @@ namespace HospitalWeb
                 throw new Exception(result);
             }
         }
+
+        public static (Stream stream, string? contentType)? GetFileRequest<T>(string requestUrl, T model)
+        {
+            var json = JsonConvert.SerializeObject(model);
+            var data = new StringContent(json, Encoding.UTF8, "application/json");
+            var response = _client.PostAsync(requestUrl, data);
+            
+            var result = response.Result.Content.ReadAsStreamAsync().Result;
+            response.Result.Content.Headers.TryGetValues("content-type", out var type);
+            if (response.Result.IsSuccessStatusCode)
+            {
+                return (stream: result, contentType: type?.First());
+            }
+
+            else
+            {
+                throw new Exception($"Failed to retrieve file from {requestUrl}. StatusCode: {response.Result.StatusCode}");
+            }
+        }
     }
 }
diff --git a/Hospital/HospitalWeb/Controllers/RecipeController.cs b/Hospital/HospitalWeb/Controllers/RecipeController.cs
index 1d4624b..30bd07c 100644
--- a/Hospital/HospitalWeb/Controllers/RecipeController.cs
+++ b/Hospital/HospitalWeb/Controllers/RecipeController.cs
@@ -51,8 +51,6 @@ namespace HospitalWeb.Controllers
             model.ApothecaryId = APIClient.Apothecary.Id;
             if (model.Id != 0)
             {
-                // тут надо вытащить ключи, потом по ним сделать массовый запрос сущностей лекарств, а потом вставить как значения в словарь 
-                //model.RecipeMedicines =
                 APIClient.PostRequest("api/recipe/update", model);
             }
             else
diff --git a/Hospital/HospitalWeb/Controllers/ReportController.cs b/Hospital/HospitalWeb/Controllers/ReportController.cs
new file mode 100644
index 0000000..37e6186
--- /dev/null
+++ b/Hospital/HospitalWeb/Controllers/ReportController.cs
@@ -0,0 +1,62 @@
+using HospitalContracts.BindingModels;
+using HospitalContracts.ViewModels;
+using HospitalWeb.HelpModels;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Net;
+
+namespace HospitalWeb.Controllers
+{
+	public class ReportController : Controller
+	{
+
+        [HttpGet("/reports/patients")]
+        public IActionResult ReportPatients()
+        {
+            ViewBag.Medicines = APIClient.GetRequest<List<MedicineViewModel>>($"api/medicine/getmedicines");
+            return View();
+        }
+
+        [HttpGet("/reports/precriptions")]
+        public IActionResult ReportPrescriptions(List<ReportPrescriptionProcedureViewModel>? report)
+        {           
+            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<List<ReportPrescriptionProcedureViewModel>>($"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.");
+        }
+
+        [HttpGet("/reports/download")]
+        public IActionResult DownloadReport(ReportBindingModel model, string Format)
+        {
+            var format = Enum.Parse<FileFormat>(Format);
+            var (endpoint, extension) = format switch
+            {
+                FileFormat.Word => ("api/report/getreportpatientstowordfile/", ".docx"),
+                FileFormat.Excel => ("api/report/getreportpatientstoexcelfile/", ".xlsx"),
+                _ => throw new ArgumentException($"Invalid file format: {format}", nameof(Format))
+            };
+            model.FileName += extension;
+            var fileData = APIClient.GetFileRequest(endpoint, model);
+            if (fileData != null)
+                return File(fileData.Value.stream, fileData.Value.contentType!, model.FileName);
+            throw new Exception($"Failed to retrieve file from {endpoint}.");
+        }
+    }
+}
diff --git a/Hospital/HospitalWeb/HelpModels/FileFormat.cs b/Hospital/HospitalWeb/HelpModels/FileFormat.cs
new file mode 100644
index 0000000..bdce4b0
--- /dev/null
+++ b/Hospital/HospitalWeb/HelpModels/FileFormat.cs
@@ -0,0 +1,8 @@
+namespace HospitalWeb.HelpModels
+{
+	public enum FileFormat
+	{
+		Word = 0,
+		Excel = 1
+	}
+}
diff --git a/Hospital/HospitalWeb/Views/Report/ReportPatients.cshtml b/Hospital/HospitalWeb/Views/Report/ReportPatients.cshtml
new file mode 100644
index 0000000..ffb4fc2
--- /dev/null
+++ b/Hospital/HospitalWeb/Views/Report/ReportPatients.cshtml
@@ -0,0 +1,34 @@
+@using HospitalContracts.ViewModels;
+@using System.Globalization
+@model MedicineViewModel
+@{
+    ViewData["Title"] = "Отчет Пациенты";
+}
+
+<div class="text-center">
+    <h2 class="display-4">@ViewData["Title"]</h2>
+</div>
+<form id="reportForm" method="get" action="/reports/download">
+		<div class="row">
+			<div class="col-4">Выбор лекарств</div>
+			<div class="col-8">
+				<select id="medicines" name="Medicines" class="form-control" multiple asp-items="@(new SelectList(@ViewBag.Medicines,"Id", "Name"))"></select>
+				<small>Для выбора нескольких элементов удерживайте клавишу Ctrl.</small> 
+			</div>
+		</div>
+		<div class="row">
+			<div class="col-4">Название файла (без формата):</div>
+			<div class="col-8"><input type="text" name="FileName" required /></div>
+		</div> 
+		<div class="row">
+		<div class="col-4">Формат файла:</div>
+			<div class="col-8">
+				<select name="Format" required>
+					<option value="Word">Word</option>
+					<option value="Excel">Excel</option>
+				</select>
+			</div>
+		</div>
+		<button id="submitReport">Получить отчет</button>
+</form>
+
diff --git a/Hospital/HospitalWeb/Views/Report/ReportPrescriptions.cshtml b/Hospital/HospitalWeb/Views/Report/ReportPrescriptions.cshtml
new file mode 100644
index 0000000..b8ff787
--- /dev/null
+++ b/Hospital/HospitalWeb/Views/Report/ReportPrescriptions.cshtml
@@ -0,0 +1,51 @@
+@using HospitalContracts.ViewModels;
+@model List<ReportPrescriptionProcedureViewModel>
+
+@{
+    ViewData["Title"] = "Отчет Поступления";
+}
+
+<div class="text-center">
+    <h2 class="display-4">@ViewData["Title"]</h2>
+</div>
+
+<form method="get" class="form-inline" action="/report/getprescriptions">
+    <div class="form-group mx-sm-3 mb-2">
+        <label for="startDate" class="sr-only">Начальная дата:</label>
+        <input type="date" class="form-control" id="startDate" name="startDate" required />
+    </div>
+    <div class="form-group mx-sm-3 mb-2">
+        <label for="endDate" class="sr-only">Конечная дата:</label>
+        <input type="date" class="form-control" id="endDate" name="endDate" required />
+    </div>
+    <div class="form-group mx-sm-3 mb-2">
+        <button type="submit" class="btn btn-primary" name="type" value="getReport">Получить отчет</button>
+    </div>
+    <div class="form-group mx-sm-3 mb-2">
+        <button type="submit" class="btn btn-secondary" name="type" value="sendPdf">Отправить pdf на почту</button>
+    </div>
+</form>
+@if (Model != null && Model.Any())
+{
+        <table class="table">
+            <thead>
+                <tr>                
+                    <th>Дата поступления</th>
+                    <th>Лекарство</th>
+                    <th>Количество</th>
+                    <th>Название процедуры</th>
+                </tr>
+            </thead>
+            <tbody>
+            @foreach (var report in Model)
+            {
+                        <tr>
+                            <td>@report.DateCreate.ToShortDateString()</td>
+                            <td>@report.MedicineName</td>
+                            <td>@report.Number</td>
+                            <td>@report.ProcedureName</td>
+                        </tr>
+            }
+            </tbody>
+        </table>
+}
\ No newline at end of file
diff --git a/Hospital/HospitalWeb/Views/Shared/_Layout.cshtml b/Hospital/HospitalWeb/Views/Shared/_Layout.cshtml
index 01d7c15..e4da1da 100644
--- a/Hospital/HospitalWeb/Views/Shared/_Layout.cshtml
+++ b/Hospital/HospitalWeb/Views/Shared/_Layout.cshtml
@@ -28,6 +28,15 @@
                          <li class="nav-item">
                             <a class="nav-link text-dark" asp-area="" asp-controller="Recipe" asp-action="Recipes">Рецепты</a>
                         </li>
+                       <li class="nav-item dropdown">
+                          <a class="nav-link text-dark dropdown-toggle" href="#" id="reportDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                            Отчеты
+                          </a>
+                          <div class="dropdown-menu" aria-labelledby="reportDropdown">
+                            <a class="dropdown-item" asp-area="" asp-controller="Report" asp-action="ReportPatients">Отчет Пациенты</a>
+                            <a class="dropdown-item" asp-area="" asp-controller="Report" asp-action="ReportPrescriptions">Отчет Поступления</a>
+                          </div>
+                        </li>
                         <li class="nav-item">
                             <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Профиль</a>
                         </li>