графики и фикс сохранения файлов
This commit is contained in:
parent
c0af868126
commit
18c56ffab0
@ -117,7 +117,7 @@ namespace TravelAgencyBusinessLogic.BusinessLogics
|
||||
{
|
||||
_saveToWord.CreateDoc(new WordInfo
|
||||
{
|
||||
FileName = model.FileName,
|
||||
FileStream = model.FileStream,
|
||||
Title = "Список мест для посещения по выбранным турам.",
|
||||
TourPlaces = GetTourPlaces(model)
|
||||
});
|
||||
@ -127,7 +127,7 @@ namespace TravelAgencyBusinessLogic.BusinessLogics
|
||||
{
|
||||
_saveToExcel.CreateReport(new ExcelInfo
|
||||
{
|
||||
FileName = model.FileName,
|
||||
FileStream = model.FileStream,
|
||||
Title = "Список мест",
|
||||
TourPlaces = GetTourPlaces(model)
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.HelperModels
|
||||
{
|
||||
public class ExcelInfo
|
||||
{
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public Stream FileStream { get; set; } = new MemoryStream();
|
||||
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.HelperModels
|
||||
{
|
||||
public class WordInfo
|
||||
{
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public Stream FileStream { get; set; } = new MemoryStream();
|
||||
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
|
@ -152,7 +152,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.Implements
|
||||
|
||||
protected override void CreateExcel(ExcelInfo info)
|
||||
{
|
||||
_spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, SpreadsheetDocumentType.Workbook);
|
||||
_spreadsheetDocument = SpreadsheetDocument.Create(info.FileStream, SpreadsheetDocumentType.Workbook);
|
||||
// Создаем книгу (в ней хранятся листы)
|
||||
var workbookpart = _spreadsheetDocument.AddWorkbookPart();
|
||||
workbookpart.Workbook = new Workbook();
|
||||
|
@ -83,7 +83,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.Implements
|
||||
|
||||
protected override void CreateWord(WordInfo info)
|
||||
{
|
||||
_wordDocument = WordprocessingDocument.Create(info.FileName, WordprocessingDocumentType.Document);
|
||||
_wordDocument = WordprocessingDocument.Create(info.FileStream, WordprocessingDocumentType.Document);
|
||||
MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart();
|
||||
mainPart.Document = new Document();
|
||||
_docBody = mainPart.Document.AppendChild(new Body());
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
public class ReportBindingModel
|
||||
{
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public Stream FileStream { get; set; } = new MemoryStream();
|
||||
|
||||
public DateTime? DateFrom { get; set; }
|
||||
|
||||
|
@ -44,6 +44,12 @@ namespace TravelAgencyDatabaseImplement.Implements
|
||||
.FirstOrDefault(x => x.Email.Equals(model.Email) && x.Password.Equals(model.Password))
|
||||
?.GetViewModel;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.PhoneNumber))
|
||||
{
|
||||
return context.Users
|
||||
.FirstOrDefault(x => x.Email.Equals(model.Email) || x.PhoneNumber.Equals(model.PhoneNumber))
|
||||
?.GetViewModel;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(model.Email))
|
||||
{
|
||||
return context.Users
|
||||
|
@ -26,17 +26,20 @@ namespace TravelAgencyWebApp.Controllers
|
||||
|
||||
private readonly IGuideLogic _guideLogic;
|
||||
|
||||
private readonly IExcursionGroupLogic _excursionGroupLogic;
|
||||
|
||||
private readonly AbstractSaveToPdf _pdfLogic;
|
||||
|
||||
private readonly AbstractMailWorker _mailLogic;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger, IUserLogic userLogic, IReportLogic reportLogic, ITourLogic tourLogic, IGuideLogic guideLogic, AbstractSaveToPdf pdfLogic, AbstractMailWorker mailLogic)
|
||||
public HomeController(ILogger<HomeController> logger, IUserLogic userLogic, IReportLogic reportLogic, ITourLogic tourLogic, IGuideLogic guideLogic, IExcursionGroupLogic excursionGroupLogic, AbstractSaveToPdf pdfLogic, AbstractMailWorker mailLogic)
|
||||
{
|
||||
_logger = logger;
|
||||
_userLogic = userLogic;
|
||||
_reportLogic = reportLogic;
|
||||
_tourLogic = tourLogic;
|
||||
_guideLogic = guideLogic;
|
||||
_excursionGroupLogic = excursionGroupLogic;
|
||||
_pdfLogic = pdfLogic;
|
||||
_mailLogic = mailLogic;
|
||||
}
|
||||
@ -246,20 +249,31 @@ namespace TravelAgencyWebApp.Controllers
|
||||
|
||||
if (type.Equals("docx"))
|
||||
{
|
||||
_reportLogic.SaveTourPlacesToWordFile(new ReportBindingModel
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
FileName = $@"C:\Users\User\Downloads\Список мест по турам{DateTime.Now.ToString("dd-MM-yyyy HH-mm-ss")}.docx",
|
||||
UserId = LoggedinUser.User.Id,
|
||||
Tours = tours
|
||||
});
|
||||
_reportLogic.SaveTourPlacesToWordFile(new ReportBindingModel
|
||||
{
|
||||
FileStream = stream,
|
||||
UserId = LoggedinUser.User.Id,
|
||||
Tours = tours
|
||||
});
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "wordfile.docx");
|
||||
}
|
||||
} else if (type.Equals("xlsx"))
|
||||
{
|
||||
_reportLogic.SaveTourPlacesToExcelFile(new ReportBindingModel
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
FileName = $@"C:\Users\User\Downloads\Список мест по турам{DateTime.Now.ToString("dd-MM-yyyy HH-mm-ss")}.xlsx",
|
||||
UserId = LoggedinUser.User.Id,
|
||||
Tours = tours
|
||||
});
|
||||
_reportLogic.SaveTourPlacesToExcelFile(new ReportBindingModel
|
||||
{
|
||||
FileStream = stream,
|
||||
UserId = LoggedinUser.User.Id,
|
||||
Tours = tours
|
||||
});
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "excelfile.xlsx");
|
||||
}
|
||||
}
|
||||
|
||||
ViewBag.Tours = _tourLogic.ReadList(new TourSearchModel
|
||||
@ -313,5 +327,69 @@ namespace TravelAgencyWebApp.Controllers
|
||||
byte[] report = stream.GetBuffer();
|
||||
_mailLogic.MailSendAsync(new() { MailAddress = LoggedinUser.User.Email, Subject = "Отчет", FileName = "PdfReport.pdf", Pdf = report });
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Diagrams()
|
||||
{
|
||||
if (LoggedinUser.User == null)
|
||||
{
|
||||
throw new Exception("Необходимо авторизоваться!");
|
||||
}
|
||||
|
||||
ViewBag.RevenuePerMonth = Newtonsoft.Json.JsonConvert.SerializeObject(getRevenues());
|
||||
|
||||
ViewBag.TourPopularity = Newtonsoft.Json.JsonConvert.SerializeObject(getTourPopularity());
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
private Dictionary<int, double> getRevenues()
|
||||
{
|
||||
var tours = _tourLogic.ReadList(new TourSearchModel { UserId = LoggedinUser.User.Id, DateFrom = new DateTime(DateTime.Today.Year, 1, 1), DateTo = DateTime.Today });
|
||||
var excursionGroups = _excursionGroupLogic.ReadList(new ExcursionGroupSearchModel { UserId = LoggedinUser.User.Id });
|
||||
|
||||
var revenuePerMonth = new Dictionary<int, double>();
|
||||
|
||||
foreach (var tour in tours)
|
||||
{
|
||||
var month = tour.TourDate.Month;
|
||||
if (!revenuePerMonth.ContainsKey(month))
|
||||
{
|
||||
revenuePerMonth[month] = 0;
|
||||
}
|
||||
foreach (var eg in excursionGroups)
|
||||
{
|
||||
if (eg.ExcursionGroupTours.ContainsKey(tour.Id))
|
||||
{
|
||||
revenuePerMonth[month] += tour.Price * eg.ParticipantsAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return revenuePerMonth;
|
||||
}
|
||||
|
||||
private Dictionary<string, int> getTourPopularity()
|
||||
{
|
||||
var tours = _tourLogic.ReadList(new TourSearchModel { UserId = LoggedinUser.User.Id });
|
||||
var excursionGroups = _excursionGroupLogic.ReadList(new ExcursionGroupSearchModel { UserId = LoggedinUser.User.Id });
|
||||
|
||||
var participantsPerTour = new Dictionary<string, int>();
|
||||
|
||||
foreach (var tour in tours)
|
||||
{
|
||||
if (!participantsPerTour.ContainsKey(tour.TourName))
|
||||
{
|
||||
participantsPerTour[tour.TourName] = 0;
|
||||
}
|
||||
foreach (var eg in excursionGroups)
|
||||
{
|
||||
if (eg.ExcursionGroupTours.ContainsKey(tour.Id))
|
||||
{
|
||||
participantsPerTour[tour.TourName] += eg.ParticipantsAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return participantsPerTour;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
98
TravelAgency/TravelAgencyWebApp/Views/Home/Diagrams.cshtml
Normal file
98
TravelAgency/TravelAgencyWebApp/Views/Home/Diagrams.cshtml
Normal file
@ -0,0 +1,98 @@
|
||||
@{
|
||||
ViewData["Title"] = "Diagrams";
|
||||
var revenuePerMonthJson = ViewBag.RevenuePerMonth;
|
||||
var tourPopularityJson = ViewBag.TourPopularity;
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h2 class="display-4">Диаграммы</h2>
|
||||
<h2 class="display-5 text-start">Прибыль</h2>
|
||||
<canvas id="revenueChart"></canvas>
|
||||
<h2 class="display-5 text-start">Популярность туров</h2>
|
||||
<canvas id="popularityChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
|
||||
// Получение данных из Razor переменной
|
||||
var revenuePerMonth = @Html.Raw(revenuePerMonthJson);
|
||||
|
||||
// Преобразуем объект в массивы для Chart.js
|
||||
var labels = Object.keys(revenuePerMonth).map(month => new Date(0, month - 1).toLocaleString('default', { month: 'long' }));
|
||||
var dataPoints = Object.values(revenuePerMonth);
|
||||
|
||||
var ctx = document.getElementById('revenueChart').getContext('2d');
|
||||
var data = {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: 'Доход по месяцам',
|
||||
data: dataPoints,
|
||||
fill: false,
|
||||
borderColor: 'blue',
|
||||
pointRadius: 5,
|
||||
pointHoverRadius: 10,
|
||||
pointHoverBackgroundColor: 'red',
|
||||
pointHoverBorderColor: 'orange'
|
||||
}]
|
||||
};
|
||||
|
||||
var options = {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Доход по месяцам'
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var revenueChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
|
||||
// Вторая диаграмма
|
||||
var tourPopularity = @Html.Raw(tourPopularityJson);
|
||||
var tourLabels = Object.keys(tourPopularity).map(tourName => `${tourName}`);
|
||||
var participantsData = Object.values(tourPopularity);
|
||||
|
||||
var ctx2 = document.getElementById('popularityChart').getContext('2d');
|
||||
var data2 = {
|
||||
labels: tourLabels,
|
||||
datasets: [{
|
||||
label: 'Количество участников по турам',
|
||||
data: participantsData,
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
};
|
||||
|
||||
var options2 = {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Количество участников по турам'
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var popularityChart = new Chart(ctx2, {
|
||||
type: 'bar',
|
||||
data: data2,
|
||||
options: options2
|
||||
});
|
||||
});
|
||||
</script>
|
@ -6,16 +6,15 @@
|
||||
<h2 class="display-4">Вход в приложение</h2>
|
||||
</div>
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="col-4">Логин:</div>
|
||||
<div class="col-8"><input type="text" name="email" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">Логин:</div>
|
||||
<div class="col-4"><input type="text" name="email" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">Пароль:</div>
|
||||
<div class="col-8"><input type="password" name="password" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">Пароль:</div>
|
||||
<div class="col-4"><input type="password" name="password" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8"></div>
|
||||
<div class="col-4"><input type="submit" value="Вход" class="btn btn-primary" /></div>
|
||||
<div class="row d-flex justify-content-center p-3">
|
||||
<input type="submit" value="Вход" class="btn btn-primary col-2" />
|
||||
</div>
|
||||
</form>
|
@ -6,24 +6,23 @@
|
||||
<h2 class="display-4">Регистрация</h2>
|
||||
</div>
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="col-4">Логин:</div>
|
||||
<div class="col-8"><input type="text" name="email" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">Логин:</div>
|
||||
<div class="col-4"><input type="text" name="email" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">Пароль:</div>
|
||||
<div class="col-8"><input type="password" name="password" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">Пароль:</div>
|
||||
<div class="col-4"><input type="password" name="password" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">Номер телефона:</div>
|
||||
<div class="col-8"><input type="text" name="phone" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">Номер телефона:</div>
|
||||
<div class="col-4"><input type="text" name="phone" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">ФИО:</div>
|
||||
<div class="col-8"><input type="text" name="fio" /></div>
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-2">ФИО:</div>
|
||||
<div class="col-4"><input type="text" name="fio" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8"></div>
|
||||
<div class="col-4"><input type="submit" value="Регистрация" class="btn btn-primary" /></div>
|
||||
<div class="row d-flex justify-content-center p-3">
|
||||
<input type="submit" value="Регистрация" class="btn btn-primary col-2" />
|
||||
</div>
|
||||
</form>
|
@ -21,9 +21,6 @@
|
||||
</button>
|
||||
<div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
|
||||
<ul class="navbar-nav flex-grow-1">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
|
||||
</li>
|
||||
@ -48,6 +45,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="ReportMenu">Отчеты</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Diagrams">Диаграммы</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user