графики и фикс сохранения файлов
This commit is contained in:
parent
c0af868126
commit
18c56ffab0
@ -117,7 +117,7 @@ namespace TravelAgencyBusinessLogic.BusinessLogics
|
|||||||
{
|
{
|
||||||
_saveToWord.CreateDoc(new WordInfo
|
_saveToWord.CreateDoc(new WordInfo
|
||||||
{
|
{
|
||||||
FileName = model.FileName,
|
FileStream = model.FileStream,
|
||||||
Title = "Список мест для посещения по выбранным турам.",
|
Title = "Список мест для посещения по выбранным турам.",
|
||||||
TourPlaces = GetTourPlaces(model)
|
TourPlaces = GetTourPlaces(model)
|
||||||
});
|
});
|
||||||
@ -127,7 +127,7 @@ namespace TravelAgencyBusinessLogic.BusinessLogics
|
|||||||
{
|
{
|
||||||
_saveToExcel.CreateReport(new ExcelInfo
|
_saveToExcel.CreateReport(new ExcelInfo
|
||||||
{
|
{
|
||||||
FileName = model.FileName,
|
FileStream = model.FileStream,
|
||||||
Title = "Список мест",
|
Title = "Список мест",
|
||||||
TourPlaces = GetTourPlaces(model)
|
TourPlaces = GetTourPlaces(model)
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.HelperModels
|
|||||||
{
|
{
|
||||||
public class ExcelInfo
|
public class ExcelInfo
|
||||||
{
|
{
|
||||||
public string FileName { get; set; } = string.Empty;
|
public Stream FileStream { get; set; } = new MemoryStream();
|
||||||
|
|
||||||
public string Title { get; set; } = string.Empty;
|
public string Title { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.HelperModels
|
|||||||
{
|
{
|
||||||
public class WordInfo
|
public class WordInfo
|
||||||
{
|
{
|
||||||
public string FileName { get; set; } = string.Empty;
|
public Stream FileStream { get; set; } = new MemoryStream();
|
||||||
|
|
||||||
public string Title { get; set; } = string.Empty;
|
public string Title { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.Implements
|
|||||||
|
|
||||||
protected override void CreateExcel(ExcelInfo info)
|
protected override void CreateExcel(ExcelInfo info)
|
||||||
{
|
{
|
||||||
_spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, SpreadsheetDocumentType.Workbook);
|
_spreadsheetDocument = SpreadsheetDocument.Create(info.FileStream, SpreadsheetDocumentType.Workbook);
|
||||||
// Создаем книгу (в ней хранятся листы)
|
// Создаем книгу (в ней хранятся листы)
|
||||||
var workbookpart = _spreadsheetDocument.AddWorkbookPart();
|
var workbookpart = _spreadsheetDocument.AddWorkbookPart();
|
||||||
workbookpart.Workbook = new Workbook();
|
workbookpart.Workbook = new Workbook();
|
||||||
|
@ -83,7 +83,7 @@ namespace TravelAgencyBusinessLogic.OfficePackage.Implements
|
|||||||
|
|
||||||
protected override void CreateWord(WordInfo info)
|
protected override void CreateWord(WordInfo info)
|
||||||
{
|
{
|
||||||
_wordDocument = WordprocessingDocument.Create(info.FileName, WordprocessingDocumentType.Document);
|
_wordDocument = WordprocessingDocument.Create(info.FileStream, WordprocessingDocumentType.Document);
|
||||||
MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart();
|
MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart();
|
||||||
mainPart.Document = new Document();
|
mainPart.Document = new Document();
|
||||||
_docBody = mainPart.Document.AppendChild(new Body());
|
_docBody = mainPart.Document.AppendChild(new Body());
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public class ReportBindingModel
|
public class ReportBindingModel
|
||||||
{
|
{
|
||||||
public string FileName { get; set; } = string.Empty;
|
public Stream FileStream { get; set; } = new MemoryStream();
|
||||||
|
|
||||||
public DateTime? DateFrom { get; set; }
|
public DateTime? DateFrom { get; set; }
|
||||||
|
|
||||||
|
@ -44,6 +44,12 @@ namespace TravelAgencyDatabaseImplement.Implements
|
|||||||
.FirstOrDefault(x => x.Email.Equals(model.Email) && x.Password.Equals(model.Password))
|
.FirstOrDefault(x => x.Email.Equals(model.Email) && x.Password.Equals(model.Password))
|
||||||
?.GetViewModel;
|
?.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))
|
if (!string.IsNullOrEmpty(model.Email))
|
||||||
{
|
{
|
||||||
return context.Users
|
return context.Users
|
||||||
|
@ -26,17 +26,20 @@ namespace TravelAgencyWebApp.Controllers
|
|||||||
|
|
||||||
private readonly IGuideLogic _guideLogic;
|
private readonly IGuideLogic _guideLogic;
|
||||||
|
|
||||||
|
private readonly IExcursionGroupLogic _excursionGroupLogic;
|
||||||
|
|
||||||
private readonly AbstractSaveToPdf _pdfLogic;
|
private readonly AbstractSaveToPdf _pdfLogic;
|
||||||
|
|
||||||
private readonly AbstractMailWorker _mailLogic;
|
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;
|
_logger = logger;
|
||||||
_userLogic = userLogic;
|
_userLogic = userLogic;
|
||||||
_reportLogic = reportLogic;
|
_reportLogic = reportLogic;
|
||||||
_tourLogic = tourLogic;
|
_tourLogic = tourLogic;
|
||||||
_guideLogic = guideLogic;
|
_guideLogic = guideLogic;
|
||||||
|
_excursionGroupLogic = excursionGroupLogic;
|
||||||
_pdfLogic = pdfLogic;
|
_pdfLogic = pdfLogic;
|
||||||
_mailLogic = mailLogic;
|
_mailLogic = mailLogic;
|
||||||
}
|
}
|
||||||
@ -246,20 +249,31 @@ namespace TravelAgencyWebApp.Controllers
|
|||||||
|
|
||||||
if (type.Equals("docx"))
|
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",
|
_reportLogic.SaveTourPlacesToWordFile(new ReportBindingModel
|
||||||
UserId = LoggedinUser.User.Id,
|
{
|
||||||
Tours = tours
|
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"))
|
} 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",
|
_reportLogic.SaveTourPlacesToExcelFile(new ReportBindingModel
|
||||||
UserId = LoggedinUser.User.Id,
|
{
|
||||||
Tours = tours
|
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
|
ViewBag.Tours = _tourLogic.ReadList(new TourSearchModel
|
||||||
@ -313,5 +327,69 @@ namespace TravelAgencyWebApp.Controllers
|
|||||||
byte[] report = stream.GetBuffer();
|
byte[] report = stream.GetBuffer();
|
||||||
_mailLogic.MailSendAsync(new() { MailAddress = LoggedinUser.User.Email, Subject = "Отчет", FileName = "PdfReport.pdf", Pdf = report });
|
_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>
|
<h2 class="display-4">Вход в приложение</h2>
|
||||||
</div>
|
</div>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">Логин:</div>
|
<div class="col-2">Логин:</div>
|
||||||
<div class="col-8"><input type="text" name="email" /></div>
|
<div class="col-4"><input type="text" name="email" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">Пароль:</div>
|
<div class="col-2">Пароль:</div>
|
||||||
<div class="col-8"><input type="password" name="password" /></div>
|
<div class="col-4"><input type="password" name="password" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center p-3">
|
||||||
<div class="col-8"></div>
|
<input type="submit" value="Вход" class="btn btn-primary col-2" />
|
||||||
<div class="col-4"><input type="submit" value="Вход" class="btn btn-primary" /></div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
@ -6,24 +6,23 @@
|
|||||||
<h2 class="display-4">Регистрация</h2>
|
<h2 class="display-4">Регистрация</h2>
|
||||||
</div>
|
</div>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">Логин:</div>
|
<div class="col-2">Логин:</div>
|
||||||
<div class="col-8"><input type="text" name="email" /></div>
|
<div class="col-4"><input type="text" name="email" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">Пароль:</div>
|
<div class="col-2">Пароль:</div>
|
||||||
<div class="col-8"><input type="password" name="password" /></div>
|
<div class="col-4"><input type="password" name="password" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">Номер телефона:</div>
|
<div class="col-2">Номер телефона:</div>
|
||||||
<div class="col-8"><input type="text" name="phone" /></div>
|
<div class="col-4"><input type="text" name="phone" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-4">ФИО:</div>
|
<div class="col-2">ФИО:</div>
|
||||||
<div class="col-8"><input type="text" name="fio" /></div>
|
<div class="col-4"><input type="text" name="fio" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center p-3">
|
||||||
<div class="col-8"></div>
|
<input type="submit" value="Регистрация" class="btn btn-primary col-2" />
|
||||||
<div class="col-4"><input type="submit" value="Регистрация" class="btn btn-primary" /></div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
@ -21,9 +21,6 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
|
<div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
|
||||||
<ul class="navbar-nav flex-grow-1">
|
<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">
|
<li class="nav-item">
|
||||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
|
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
|
||||||
</li>
|
</li>
|
||||||
@ -48,6 +45,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="ReportMenu">Отчеты</a>
|
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="ReportMenu">Отчеты</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Diagrams">Диаграммы</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user