Files
Pibd-21_Semin_D.A._SmallSof…/SmallSoftwareProject/SmallSoftwareBusinessLogic/Implementations/ReportContract.cs
2025-04-24 00:06:05 +04:00

173 lines
8.0 KiB
C#

using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using SmallSoftwareBusinessLogic.OfficePackage;
using SmallSoftwareContracts.BusinessLogicsContracts;
using SmallSoftwareContracts.DataModels;
using SmallSoftwareContracts.Exceptions;
using SmallSoftwareContracts.Extensions;
using SmallSoftwareContracts.Resources;
using SmallSoftwareContracts.StoragesContracts;
namespace SmallSoftwareBusinessLogic.Implementations;
internal class ReportContract : IReportContract
{
private readonly ISoftwareStorageContract _softwareStorageContract;
private readonly IRequestStorageContract _requestStorageContract;
private readonly ISalaryStorageContract _salaryStorageContract;
private readonly BaseWordBuilder _baseWordBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder;
private readonly BasePdfBuilder _basePdfBuilder;
private readonly IStringLocalizer<Messages> _localizer ;
private readonly ILogger _logger;
internal readonly string[] tableHeader;
internal readonly string[] documentHeader;
public ReportContract(ISoftwareStorageContract softwareStorageContract,
IRequestStorageContract requestStorageContract,
ISalaryStorageContract salaryStorageContract,
BaseWordBuilder baseWordBuilder,
BaseExcelBuilder baseExcelBuilder,
BasePdfBuilder basePdfBuilder, IStringLocalizer<Messages> localizer, ILogger logger)
{
_softwareStorageContract = softwareStorageContract;
_requestStorageContract = requestStorageContract;
_salaryStorageContract = salaryStorageContract;
_baseWordBuilder = baseWordBuilder;
_baseExcelBuilder = baseExcelBuilder;
_basePdfBuilder = basePdfBuilder;
_localizer = localizer;
_logger = logger;
tableHeader = [_localizer["DocumentExcelCaptionDate"], _localizer["DocumentExcelCaptionSum"], _localizer["DocumentExcelCaptionSoftware"], _localizer["DocumentExcelCaptionCount"]];
documentHeader = [_localizer["DocumentDocCaptionSoftware"], _localizer["DocumentDocCaptionOldPrice"], _localizer["DocumentDocCaptionData"]];
}
public Task<List<HistoryOfSoftwareDataModel>> GetDataSoftwaresByHistoryAsync(CancellationToken ct)
{
_logger.LogInformation("Get data SoftwaresByManufacturer");
return GetDataBySoftwaresAsync(ct);
}
private async Task<List<HistoryOfSoftwareDataModel>> GetDataBySoftwaresAsync(CancellationToken ct)
=> [.. (await _softwareStorageContract.GetListAsync(ct)).GroupBy(x => x.SoftwareName).Select(x => new HistoryOfSoftwareDataModel {
SoftwareName = x.Key, Histories = [.. x.Select(y => y.OldPrice.ToString())], Data = [.. x.Select(y => y.ChangeDate.ToString())] })];
public async Task<Stream> CreateDocumentSoftwaresByHistoryAsync(CancellationToken ct)
{
_logger.LogInformation("Create report HistoryBySoftware");
var data = await GetDataBySoftwaresAsync(ct) ?? throw new InvalidOperationException("No found data");
var tableData = new List<string[]>
{
documentHeader
};
foreach (var software in data)
{
tableData.Add(new string[] { software.SoftwareName, "", "" });
var pairs = software.Histories.Zip(software.Data,
(price, date) => new string[] { "", price, date });
tableData.AddRange(pairs);
}
return _baseWordBuilder
.AddHeader(_localizer["DocumentDocHeader"])
.AddParagraph(string.Format(_localizer["DocumentDocSubHeader"], DateTime.Now))
.AddTable(
widths: new[] { 3000, 3000, 3000 },
data: tableData
)
.Build();
}
public Task<List<RequestDataModel>> GetDataRequestByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Get data RequestsByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
return GetDataByRequestsAsync(dateStart, dateFinish, ct);
}
private async Task<List<RequestDataModel>> GetDataByRequestsAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
return [.. (await _requestStorageContract.GetListAsync(dateStart, dateFinish, ct)).OrderBy(x => x.RequestDate)];
}
public async Task<Stream> CreateDocumentRequestsByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Create report RequestsByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
var data = await GetDataByRequestsAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
var tableHeader = new string[] { "Дата", "Email", "Сумма", "ПО", "Количество" };
return _baseExcelBuilder
.AddHeader(_localizer["DocumentExcelHeader"], 0, 5)
.AddParagraph($"c {dateStart.ToShortDateString()} по {dateFinish.ToShortDateString()}", 2)
.AddTable(
[10, 10, 10, 10, 10],
[.. new List<string[]>() { tableHeader }
.Union(data.SelectMany(x =>
(new List<string[]>() {
new string[] {
x.RequestDate.ToShortDateString(),
x.Email,
x.Sum.ToString("N2"),
"",
""
}
})
.Union(x.Softwares!.Select(y => new string[] {
"",
"",
"",
y.SoftwareName,
y.Count.ToString("N2")
}))
.ToArray()
)
.Union([[
_localizer["DocumentExcelCaptionTotal"],
"",
data.Sum(x => x.Sum).ToString("N2"),
"",
""
]]))
])
.Build();
}
public Task<List<WorkerSalaryByPeriodDataModel>> 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<WorkerSalaryByPeriodDataModel>> 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.WorkerFIO).Select(x => new
WorkerSalaryByPeriodDataModel { WorkerFIO = x.Key, TotalSalary = x.Sum(y => y.Salary),
FromPeriod = x.Min(y => y.SalaryDate), ToPeriod = x.Max(y => y.SalaryDate) }).OrderBy(x => x.WorkerFIO)];
}
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(_localizer["DocumentPdfHeader"])
.AddParagraph(string.Format(_localizer["DocumentPdfSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()))
.AddPieChart(_localizer["DocumentPdfDiagramCaption"], [.. data.Select(x => (x.WorkerFIO, x.TotalSalary))]).Build();
}
}