forked from slavaxom9k/PIBD-23_Fomichev_V.S._MagicCarpet
180 lines
8.1 KiB
C#
180 lines
8.1 KiB
C#
using DocumentFormat.OpenXml.Wordprocessing;
|
||
using MagicCarpetBusinessLogic.OfficePackage;
|
||
using MagicCarpetContracts.BusinessLogicContracts;
|
||
using MagicCarpetContracts.DataModels;
|
||
using MagicCarpetContracts.Exceptions;
|
||
using MagicCarpetContracts.Extensions;
|
||
using MagicCarpetContracts.Resources;
|
||
using MagicCarpetContracts.StoragesContracts;
|
||
using Microsoft.Extensions.Localization;
|
||
using Microsoft.Extensions.Logging;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
namespace MagicCarpetBusinessLogic.Implementations;
|
||
|
||
internal class ReportContract : IReportContract
|
||
{
|
||
private readonly ITourStorageContract _tourStorageContract;
|
||
private readonly ISalaryStorageContract _salaryStorageContract;
|
||
private readonly ISaleStorageContract _saleStorageContract;
|
||
private readonly BaseWordBuilder _baseWordBuilder;
|
||
private readonly BaseExcelBuilder _baseExcelBuilder;
|
||
private readonly BasePdfBuilder _basePdfBuilder;
|
||
private readonly ILogger _logger;
|
||
private readonly IStringLocalizer<Messages> _localizer;
|
||
|
||
internal readonly string[] _documentHeader;
|
||
internal readonly string[] _tableHeader;
|
||
|
||
public ReportContract(ITourStorageContract tourStorageContract, ISalaryStorageContract salaryStorageContract,
|
||
ISaleStorageContract saleStorageContract, BaseWordBuilder baseWordBuilder, BaseExcelBuilder baseExcelBuilder,
|
||
BasePdfBuilder basePdfBuilder, ILogger logger, IStringLocalizer<Messages> localizer)
|
||
{
|
||
_tourStorageContract = tourStorageContract;
|
||
_saleStorageContract = saleStorageContract;
|
||
_salaryStorageContract = salaryStorageContract;
|
||
_baseWordBuilder = baseWordBuilder;
|
||
_baseExcelBuilder = baseExcelBuilder;
|
||
_basePdfBuilder = basePdfBuilder;
|
||
_logger = logger;
|
||
_localizer = localizer;
|
||
|
||
_documentHeader = [_localizer["DocumentDocCaptionTour"], _localizer["DocumentDocCaptionPreviousNames"], _localizer["DocumentDocCaptionData"]];
|
||
_tableHeader = [_localizer["DocumentExcelCaptionDate"], _localizer["DocumentExcelCaptionSum"], _localizer["DocumentExcelCaptionDiscount"], _localizer["DocumentExcelCaptionTour"], _localizer["DocumentExcelCaptionCount"]];
|
||
}
|
||
|
||
|
||
public Task<List<TourAndTourHistoryDataModel>> GetDataToursHistoryAsync(CancellationToken ct)
|
||
{
|
||
_logger.LogInformation("Get data PostHistory");
|
||
return GetToursHistoriesAsync(ct);
|
||
}
|
||
|
||
public async Task<Stream> CreateDocumentToursHistoryAsync(CancellationToken ct)
|
||
{
|
||
_logger.LogInformation("Create report TourHistory");
|
||
var data = await GetToursHistoriesAsync(ct) ?? throw new InvalidOperationException(_localizer["NotFoundDataMessage"]);
|
||
|
||
return _baseWordBuilder
|
||
.AddHeader(_localizer["DocumentDocHeader"])
|
||
.AddParagraph(string.Format(_localizer["DocumentDocSubHeader"], DateTime.Now))
|
||
.AddTable(
|
||
new[] { 3000, 3000, 3000 },
|
||
new List<string[]> { _documentHeader }
|
||
.Concat(data.SelectMany(x =>
|
||
new[] { new[] { x.TourName, "", "" } }
|
||
.Concat(x.Histories.Zip(x.Data, (price, date) => new[] { "", price, date }))
|
||
))
|
||
.ToList())
|
||
.Build();
|
||
}
|
||
|
||
private async Task<List<TourAndTourHistoryDataModel>> GetToursHistoriesAsync(CancellationToken ct) =>
|
||
[.. (await _tourStorageContract.GetHistoriesListAsync(ct)).GroupBy(x => x.TourName).Select(x => new TourAndTourHistoryDataModel {
|
||
TourName = x.Key, Histories = [.. x.Select(y => y.OldPrice.ToString())], Data = [.. x.Select(y => y.ChangeDate.ToString())] })];
|
||
|
||
public async Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
var tableHeader1 = new string[]
|
||
{
|
||
_localizer["DocumentExcelHeaderEmployee"],
|
||
_localizer["DocumentExcelCaptionDate"],
|
||
_localizer["DocumentExcelCaptionSum"],
|
||
_localizer["DocumentExcelCaptionDiscount"],
|
||
_localizer["DocumentExcelCaptionCocktail"],
|
||
_localizer["DocumentExcelCaptionCount"]
|
||
};
|
||
|
||
_logger.LogInformation("Create report SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
|
||
var data = await GetDataBySalesAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException(_localizer["NotFoundDataMessage"]);
|
||
|
||
var tableRows = new List<string[]>
|
||
{
|
||
tableHeader1
|
||
};
|
||
|
||
foreach (var sale in data)
|
||
{
|
||
tableRows.Add(new string[]
|
||
{
|
||
sale.EmployeeFIO ?? "",
|
||
sale.SaleDate.ToShortDateString(),
|
||
sale.Sum.ToString("N2"),
|
||
sale.Discount.ToString("N2"),
|
||
"", ""
|
||
});
|
||
|
||
foreach (var cocktail in sale.Tours ?? Enumerable.Empty<SaleTourDataModel>())
|
||
{
|
||
tableRows.Add(new string[]
|
||
{
|
||
"", "", "", "", cocktail.TourName, cocktail.Count.ToString("N2")
|
||
});
|
||
}
|
||
}
|
||
|
||
tableRows.Add(new string[]
|
||
{
|
||
_localizer["DocumentExcelCaptionTotal"], "", data.Sum(x => x.Sum).ToString("N2"), data.Sum(x => x.Discount).ToString("N2"), "", ""
|
||
});
|
||
|
||
return _baseExcelBuilder
|
||
.AddHeader(_localizer["DocumentExcelHeader"], 0, 6)
|
||
.AddParagraph(string.Format(_localizer["DocumentExcelSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()), 2)
|
||
.AddTable([15, 15, 10, 10, 25, 10], tableRows)
|
||
.Build();
|
||
}
|
||
|
||
public async Task<List<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
if (dateStart.IsDateNotOlder(dateFinish))
|
||
{
|
||
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
|
||
}
|
||
return [.. (await _saleStorageContract.GetListAsync(dateStart,
|
||
dateFinish, ct)).OrderBy(x => x.SaleDate)];
|
||
}
|
||
public Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
_logger.LogInformation("Get data SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
|
||
return GetDataBySalesAsync(dateStart, dateFinish, ct);
|
||
}
|
||
|
||
public Task<List<EmployeeSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
_logger.LogInformation("Get data SalaryByPeriod from {dateStart} to { dateFinish}", dateStart, dateFinish);
|
||
return GetDataBySalaryAsync(dateStart, dateFinish, ct);
|
||
}
|
||
|
||
private async Task<List<EmployeeSalaryByPeriodDataModel>> GetDataBySalaryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
if (dateStart.IsDateNotOlder(dateFinish))
|
||
{
|
||
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
|
||
}
|
||
return [.. (await _salaryStorageContract.GetListAsync(dateStart, dateFinish, ct))
|
||
.GroupBy(x => x.EmployeeId)
|
||
.Select(x => new EmployeeSalaryByPeriodDataModel {
|
||
EmployeeFIO = x.First().EmployeeFIO,
|
||
TotalSalary = x.Sum(y => y.Salary),
|
||
FromPeriod = x.Min(y => y.SalaryDate),
|
||
ToPeriod = x.Max(y => y.SalaryDate)
|
||
})
|
||
.OrderBy(x => x.EmployeeFIO)];
|
||
}
|
||
|
||
public async Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||
{
|
||
_logger.LogInformation("Create report SalaryByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
|
||
var data = await GetDataBySalaryAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
|
||
return _basePdfBuilder
|
||
.AddHeader("Зарплатная ведомость")
|
||
.AddParagraph($"за период с {dateStart.ToShortDateString()} по {dateFinish.ToShortDateString()}")
|
||
.AddPieChart("Начисления", [.. data.Select(x => (x.EmployeeFIO, x.TotalSalary))])
|
||
.Build();
|
||
}
|
||
}
|