This commit is contained in:
Viltskaa 2023-05-19 20:55:43 +04:00
parent 76e6ec8bc5
commit 4205b0c052
23 changed files with 448 additions and 73 deletions

View File

@ -50,7 +50,7 @@ public class CleaningLogic : ICleaningLogic
public bool Update(CleaningBindingModel model)
{
CheckModel(model);
CheckModel(model, false);
if (_cleaningStorage.Update(model) != null) return true;
_logger.LogWarning("Update operation failed");
return false;

View File

@ -40,9 +40,10 @@ public class ReportLogic : IReportLogic
_saveToPdf = saveToPdf;
}
public List<ReportListCleaningModel> GetListCleaning()
public List<ReportListCleaningModel> GetListCleaning(List<int> reservationsId)
{
var reservations = _reservationStorage.GetFullList();
var reservations = _reservationStorage.GetFullList()
.Where(x => reservationsId.Contains(x.Id));
List<ReportListCleaningModel> list = new();
foreach (var reservation in reservations)
@ -127,7 +128,7 @@ public class ReportLogic : IReportLogic
{
FileName = model.FileName,
Title = "Комплекты для уборки",
ListCleaningModels = GetListCleaning()
ListCleaningModels = GetListCleaning(model.Reservations)
});
}
@ -137,7 +138,7 @@ public class ReportLogic : IReportLogic
{
FileName = model.FileName,
Title = "Комплекты для уборки",
ListCleaningModels = GetListCleaning()
ListCleaningModels = GetListCleaning(model.Reservations)
});
}

View File

@ -5,4 +5,5 @@ public class ReportBindingModel
public string FileName { get; set; } = string.Empty;
public DateTime? From { get; set; }
public DateTime? To { get; set; }
public List<int>? Reservations { get; set; }
}

View File

@ -5,7 +5,7 @@ namespace HotelContracts.BusinessLogicsContracts;
public interface IReportLogic
{
List<ReportListCleaningModel> GetListCleaning();
List<ReportListCleaningModel> GetListCleaning(List<int> reservationsId);
List<ReportGuestViewModel> GetGuests(ReportBindingModel model);
void SaveListCleaningToWordFile(ReportBindingModel model);
void SaveListCleaningToExcelFile(ReportBindingModel model);

View File

@ -9,4 +9,9 @@ public class ReportGuestViewModel
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public Dictionary<int, CleaningInstrumentsViewModel> CleaningInstruments;
public string GetCleaningInstruments()
{
return string.Join(", ", CleaningInstruments.Values.Select(x => x.Type));
}
}

View File

@ -3,7 +3,6 @@ using HotelBusinessLogic.MailWorker;
using HotelContracts.BindingModels;
using HotelContracts.BusinessLogicsContracts;
using HotelContracts.SearchModels;
using HotelContracts.StoragesContracts;
using HotelContracts.ViewModels;
namespace HotelView;
@ -74,33 +73,34 @@ public class Api
Maitre.Fio.Replace(" ", "_") + "_" +
DateTime.Now.ToShortDateString() + "." + ext;
public void SendReportWord()
public string SendReportWord(List<int> reservations)
{
var fileName = GenerateFileName();
_reportLogic.SaveListCleaningToWordFile(new ReportBindingModel
{
FileName = fileName
});
_mailWorker.MailSendAsync(new MailSendInfoBindingModel
{
MailAddress = Maitre.Login,
Subject = "Список составляющих комплектов для подготовки номеров",
AttachmentMail = new Attachment(fileName)
FileName = fileName,
Reservations = reservations
});
return fileName;
}
public void SendReportExcel()
public string SendReportExcel(List<int> reservations)
{
var filename = GenerateFileName("xlsx");
_reportLogic.SaveListCleaningToExcelFile(new ReportBindingModel
{
FileName = filename
FileName = filename,
Reservations = reservations
});
_mailWorker.MailSendAsync(new MailSendInfoBindingModel
return filename;
}
public List<ReportGuestViewModel> GetPreRenderReport(DateTime from, DateTime to)
{
MailAddress = Maitre.Login,
Subject = "Список составляющих комплектов для подготовки номеров",
AttachmentMail = new Attachment(filename)
return _reportLogic.GetGuests(new ReportBindingModel
{
From = from,
To = to
});
}

View File

@ -4,10 +4,8 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using HotelContracts.BindingModels;
using HotelContracts.SearchModels;
using HotelContracts.ViewModels;
using HotelDataModels.Models;
using HotelView.Utils;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace HotelView.Controllers;
@ -44,11 +42,11 @@ public class HomeController : Controller
ViewBag.GuestLiving = Math.Round((double)ViewBag.GuestLivingCount / guests.Count * 100);
ViewBag.MaxDay = reservations.Max(x => x.EndDate - x.StartDate).Days;
ViewBag.AverageDay = reservations.Select(x => x.EndDate - x.StartDate)
.Select(x => x.Days).Average();
ViewBag.AverageDay = Math.Round(reservations.Select(x => x.EndDate - x.StartDate)
.Select(x => x.Days).Average());
ViewBag.MaxCost = reservations.Max(x => x.GetCost());
ViewBag.AverageCost = reservations.Select(x => x.GetCost()).Average();
ViewBag.AverageCost = Math.Round(reservations.Select(x => x.GetCost()).Average());
ViewBag.LastReservation = reservations.Last();
ViewBag.LastReservationRooms = string.Join(",", reservations.Last().ReservationsRooms
@ -124,6 +122,34 @@ public class HomeController : Controller
return View(_api.GetRoomLogic.ReadList(null));
}
[HttpGet]
public IActionResult EditRoom(int id)
{
ViewBag.Maitre = _api.Maitre;
var item = _api.GetRoomLogic.ReadElement(new RoomSearchModel
{
Id = id
});
return View(item);
}
[HttpPost]
public void EditRoom(int id, string type, double cost)
{
if (string.IsNullOrEmpty(type) || cost == 0)
{
throw new Exception("Invalid arguments");
}
_api.GetRoomLogic.Update(new RoomBindingModel
{
Id = id,
Cost = cost,
Type = type
});
Response.Redirect("Rooms");
}
[HttpPost]
public void CreateRoom(string type, double cost)
{
@ -163,6 +189,38 @@ public class HomeController : Controller
Response.Redirect("Guests");
}
[HttpGet]
public IActionResult EditGuest(int id)
{
ViewBag.Maitre = _api.Maitre;
var guest = _api.GetGuestLogic.ReadElement(new GuestSearchModel
{
Id = id
});
return View(guest);
}
[HttpPost]
public void EditGuest(int id, string name, string secondName, string lastName)
{
if (string.IsNullOrEmpty(name) ||
string.IsNullOrEmpty(secondName) ||
string.IsNullOrEmpty(lastName) ||
id == 0)
{
throw new Exception("Invalid arguments");
}
_api.GetGuestLogic.Update(new GuestBindingModel
{
Id = id,
Name = name.FirstCharToUpper(),
SecondName = secondName.FirstCharToUpper(),
LastName = lastName.FirstCharToUpper()
});
Response.Redirect("Guests");
}
[SuppressMessage("ReSharper.DPA", "DPA0000: DPA issues")]
public IActionResult Reservations()
{
@ -212,12 +270,75 @@ public class HomeController : Controller
Response.Redirect("Reservations");
}
[HttpGet]
public IActionResult EditReservation(int id)
{
ViewBag.Maitre = _api.Maitre;
var item = _api.GetReservationLogic.ReadElement(new ReservationSearchModel()
{
Id = id
});
ViewBag.Guests = _api.GetGuestLogic.ReadList(null);
ViewBag.RoomsModel = item.ReservationsRooms.Select(x => x.Key).ToList();
ViewBag.Rooms = _api.GetRoomLogic.ReadList(new RoomSearchModel
{
IsReserved = false
});
ViewBag.StartDate = item.StartDate.ToString("MM/dd/yyyy").Replace(".", "/");
ViewBag.EndDate = item.EndDate.ToString("MM/dd/yyyy").Replace(".", "/");
return View(item);
}
[HttpPost]
public void EditReservation(int id,
DateTime dateStart,
DateTime dateEnd)
{
if (dateEnd < dateStart || dateStart < DateTime.Now)
{
throw new Exception("Invalid arguments");
}
_api.GetReservationLogic.Update(new ReservationBindingModel
{
Id = id,
MaitreId = _api.Maitre.Id,
StartDate = dateStart,
EndDate = dateEnd
});
Response.Redirect("Reservations");
}
public IActionResult CleaningInstruments()
{
ViewBag.Maitre = _api.Maitre;
return View(_api.GetCleaningInstrumentsLogic.ReadList(null));
}
[HttpGet]
public IActionResult EditCleaningInstrument(int id)
{
ViewBag.Maitre = _api.Maitre;
var item = _api.GetCleaningInstrumentsLogic.ReadElement(new()
{
Id = id
});
return View(item);
}
[HttpPost]
public void EditCleaningInstrument(int id, string type)
{
if (string.IsNullOrEmpty(type))
throw new ArgumentException("Type must be not null");
_api.GetCleaningInstrumentsLogic.Update(new CleaningInstrumentsBindingModel
{
Id = id,
Type = type
});
Response.Redirect("CleaningInstruments");
}
[HttpPost]
public void CreateCleaningInstrument(string type)
{
@ -257,6 +378,24 @@ public class HomeController : Controller
Response.Redirect("Cleaning");
}
[HttpGet]
public IActionResult EditCleaning(int id)
{
ViewBag.Maitre = _api.Maitre;
return View();
}
[HttpPost]
public void EditCleaning(int id, DateTime dateTime)
{
_api.GetCleaningLogic.Update(new CleaningBindingModel
{
Id = id,
Date = dateTime
});
Response.Redirect("Cleaning");
}
[HttpGet]
public void DeleteReservation(int id)
{
@ -315,28 +454,40 @@ public class HomeController : Controller
public IActionResult Report()
{
ViewBag.Maitre = _api.Maitre;
ViewBag.Reservations = _api.GetReservationLogic.ReadList(null);
return View();
}
[HttpGet]
public void CreateWordReport()
[HttpPost]
public IActionResult CreateReport(List<int> reservations, string options)
{
_api.SendReportWord();
Response.Redirect("Report");
switch (options)
{
case "word":
{
var file = _api.SendReportWord(reservations);
return new PhysicalFileResult(file,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document");
}
[HttpGet]
public void CreateExcelReport()
case "excel":
{
_api.SendReportExcel();
Response.Redirect("Report");
var file = _api.SendReportExcel(reservations);
return new PhysicalFileResult(file,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
default:
return null;
}
}
[HttpPost]
public void CreatePdfReport(DateTime from, DateTime to)
public IActionResult Report(DateTime from, DateTime to)
{
_api.SendReportPdf(from, to);
Response.Redirect("Report");
ViewBag.Maitre = _api.Maitre;
ViewBag.Reservations = _api.GetReservationLogic.ReadList(null);
ViewBag.PreRender = _api.GetPreRenderReport(from, to);
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

View File

@ -39,6 +39,11 @@
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Удалить
</a>
<a
href="/Home/EditCleaning?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
Изменить
</a>
</div>
</div>
</li>

View File

@ -22,6 +22,11 @@
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Удалить
</a>
<a
href="/Home/EditCleaningInstrument?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
Изменить
</a>
</li>
}
</ul>

View File

@ -0,0 +1,22 @@
@{
ViewData["Title"] = "Уборки";
Layout = "_Layout";
}
<div class="">
<dialog class="mdl-dialog" open>
<h4 class="mdl-dialog__title">Изменение уборки</h4>
<form method="post">
<div class="mdl-dialog__content">
<span>Дата уборки</span>
<div class="mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="date" id="date" name="dateTime">
</div>
</div>
<div class="mdl-dialog__actions">
<button type="submit" class="mdl-button">Изменить</button>
<a asp-action="Cleaning" class="mdl-button close">Отмена</a>
</div>
</form>
</dialog>
</div>

View File

@ -0,0 +1,23 @@
@model HotelContracts.ViewModels.CleaningInstrumentsViewModel
@{
ViewData["Title"] = "Инструменты для уборки";
Layout = "_Layout";
}
<div class="">
<dialog class="mdl-dialog" open>
<h4 class="mdl-dialog__title">Изменение иструмента</h4>
<form method="post">
<div class="mdl-dialog__content">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="secondName" name="type" value="@Model.Type">
<label class="mdl-textfield__label" for="secondName">Название</label>
</div>
</div>
<div class="mdl-dialog__actions">
<button type="submit" class="mdl-button">Изменить</button>
<a asp-action="CleaningInstruments" class="mdl-button close">Отмена</a>
</div>
</form>
</dialog>
</div>

View File

@ -0,0 +1,31 @@
@model HotelContracts.ViewModels.GuestViewModel
@{
ViewData["Title"] = "Гости";
Layout = "_Layout";
}
<div class="">
<dialog class="mdl-dialog" open>
<h4 class="mdl-dialog__title">Изменить постояльца</h4>
<form method="post">
<div class="mdl-dialog__content">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="secondName" name="secondName" value="@Model.SecondName">
<label class="mdl-textfield__label" for="secondName">Фамилия</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="name" name="name" value="@Model.Name">
<label class="mdl-textfield__label" for="name">Имя</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="LastName" name="LastName" value="@Model.LastName">
<label class="mdl-textfield__label" for="LastName">Отчество</label>
</div>
</div>
<div class="mdl-dialog__actions">
<button type="submit" class="mdl-button">Изменить</button>
<a asp-controller="Home" asp-action="Guests" class="mdl-button close">Отмена</a>
</div>
</form>
</dialog>
</div>

View File

@ -0,0 +1,27 @@
@model HotelContracts.ViewModels.ReservationViewModel
@{
ViewData["Title"] = "Бронирования";
Layout = "_Layout";
}
<div class="">
<dialog class="mdl-dialog" open>
<h4 class="mdl-dialog__title">Изменить бронирование</h4>
<form method="post">
<div class="mdl-dialog__content">
<span>Дата заселения</span>
<div class="mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="date" id="dateStart" name="dateStart" value="@ViewBag.StartDate">
</div>
<span>Дата выселения</span>
<div class="mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="date" id="dateEnd" name="dateEnd" value="<%=@ViewBag.EndDate%>">
</div>
</div>
<div class="mdl-dialog__actions">
<button type="submit" class="mdl-button">Изменить</button>
<a asp-action="Reservations" class="mdl-button close">Отмена</a>
</div>
</form>
</dialog>
</div>

View File

@ -0,0 +1,35 @@
@model HotelContracts.ViewModels.RoomViewModel
@{
ViewData["Title"] = "Home Page";
Layout = "_Layout";
}
<div class="">
<dialog class="mdl-dialog" open>
<h4 class="mdl-dialog__title">Изменение номера</h4>
<form method="post">
<div class="mdl-dialog__content">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="number" id="cost" name="cost" value="@Model.Cost">
<label class="mdl-textfield__label" for="cost">Стоимость</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<select class="mdl-textfield__input" name="type" id="type" value="@Model.Type">
<option value="standard">Стандартный</option>
<option value="superior">Улучшенный</option>
<option value="bedroom">Со спальной комнатой</option>
<option value="apartment">Апартаменты/квартира</option>
<option value="studio">Студия</option>
<option value="suite">Люкс</option>
</select>
<label class="mdl-textfield__label" for="type">Вид номера</label>
</div>
</div>
<div class="mdl-dialog__actions">
<button type="submit" class="mdl-button">Изменить</button>
<a asp-action="Rooms" class="mdl-button close">Отмена</a>
</div>
</form>
</dialog>
</div>

View File

@ -22,6 +22,11 @@
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Удалить
</a>
<a
href="/Home/EditGuest?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
Изменить
</a>
</li>
}
</ul>

View File

@ -13,7 +13,7 @@
<h6>Постояльцев проживает (@ViewBag.GuestLivingCount из @ViewBag.GuestCount)</h6>
</div>
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
<div class="line" style="--value:@Math.Round(ViewBag.AverageDay);--max: @ViewBag.MaxDay">
<div class="line" style="--value:@ViewBag.AverageDay;--max: @ViewBag.MaxDay">
<div class="line_min">0</div>
<div class="line_value">@ViewBag.AverageDay</div>
<div class="line_max">@ViewBag.MaxDay</div>

View File

@ -1,4 +1,5 @@
@model List<HotelContracts.ViewModels.RoomViewModel>
@using HotelContracts.ViewModels
@model List<HotelContracts.ViewModels.RoomViewModel>
@{
ViewData["Title"] = "Отчеты";
Layout = "_Layout";
@ -7,37 +8,48 @@
<div class="">
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
display: flex;
justify-content: space-between;
justify-content: center;
flex-direction: column;
align-items: center;">
<h6>Создать отчет в формате (.docx) и отправить его на почту @ViewBag.Maitre.Login</h6>
<a asp-controller="Home"
asp-action="CreateWordReport"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Отправить
</a>
<h6>Создать отчет в формате (.xlsx|.docx) и скачать его @ViewBag.Maitre.Login</h6>
<form asp-controller="Home" asp-action="CreateReport">
<div style="display: flex; flex-direction: column;">
<span>Бронирования</span>
<div class="mdl-textfield mdl-js-textfield">
<select name="reservations" id="" class="mdl-textfield__input" multiple="multiple">
@{
@foreach (var item in ViewBag.Reservations)
{
<option value="@item.Id">#@item.Id</option>
}
}
</select>
</div>
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;">
<h6>Создать отчет в формате (.xlsx) и отправить его на почту @ViewBag.Maitre.Login</h6>
<a asp-controller="Home"
asp-action="CreateExcelReport"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Отправить
</a>
<label class="mdl-radio mdl-js-radio mdl-js-ripple-effect" for="option-1">
<input type="radio" id="option-1" class="mdl-radio__button" name="options" value="excel" checked>
<span class="mdl-radio__label">Excel</span>
</label>
<label class="mdl-radio mdl-js-radio mdl-js-ripple-effect" for="option-2">
<input type="radio" id="option-2" class="mdl-radio__button" name="options" value="word">
<span class="mdl-radio__label">Word</span>
</label>
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Создать
</button>
</div>
</form>
</div>
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
display: flex;
justify-content: center;
align-items: center;">
<h6 class="line_label">Создать отчет в формате (.pdf) и отправить его на почту @ViewBag.Maitre.Login</h6>
<form asp-controller="Home" asp-action="CreatePdfReport" method="post">
<span>Начальная дата</span>
<form asp-controller="Home" asp-action="Report" method="post">
<span><b>Начальная дата</b></span>
<div class="mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="date" name="from">
</div>
<span>Конечная дата</span>
<span><b>Конечная дата</b></span>
<div class="mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="date" name="to">
</div>
@ -46,4 +58,44 @@
</button>
</form>
</div>
@{
if (ViewBag.PreRender != null)
{
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
display: flex;
justify-content: center;
align-items: center;">
<h6 class="line_label">Данный отчет отправлен на почту @ViewBag.Maitre.Login</h6>
<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp" style="width: 100%;">
<thead>
<tr>
<th class="mdl-data-table__cell--non-numeric">Фамилия</th>
<th class="mdl-data-table__cell--non-numeric">Имя</th>
<th class="mdl-data-table__cell--non-numeric">Отчество</th>
<th class="mdl-data-table__cell--non-numeric">Заселение</th>
<th class="mdl-data-table__cell--non-numeric">Выселение</th>
<th class="mdl-data-table__cell--non-numeric">Набор</th>
</tr>
</thead>
<tbody>
@{
@foreach (var item in ViewBag.PreRender)
{
<tr>
<td class="mdl-data-table__cell--non-numeric">@item.SecondName</td>
<td class="mdl-data-table__cell--non-numeric">@item.Name</td>
<td class="mdl-data-table__cell--non-numeric">@item.LastName</td>
<td class="mdl-data-table__cell--non-numeric">@item.StartDate.ToShortDateString()</td>
<td class="mdl-data-table__cell--non-numeric">@item.EndDate.ToShortDateString()</td>
<td class="mdl-data-table__cell--non-numeric">
@item.GetCleaningInstruments()
</td>
</tr>
}
}
</tbody>
</table>
</div>
}
}
</div>

View File

@ -42,6 +42,11 @@
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Удалить
</a>
<a
href="/Home/EditReservation?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
Изменить
</a>
</div>
</div>
</li>

View File

@ -1,4 +1,5 @@
@model List<HotelContracts.ViewModels.RoomViewModel>
@{
ViewData["Title"] = "Home Page";
Layout = "_Layout";
@ -46,14 +47,20 @@
<span>Забронирована</span>
}
}
<span class="mdl-list__item-secondary-content">
<span class="mdl-list__item-secondary-content" style="margin: 0 15px;">
<span class="mdl-list__item-secondary-info">@item.GetTypeRoom()</span>
</span>
<a
href="/Home/DeleteRoom?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Удалить
</a>
</span>
<a
href="/Home/EditRoom?id=@item.Id"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
Изменить
</a>
</li>
}
</ul>

View File

@ -249,8 +249,8 @@ body {
dialog {
position: absolute;
top: 30%;
left: 20px;
top: 50px;
left: 40%;
}
.mdl-list__item-avatar {