14 Commits

Author SHA1 Message Date
52c8343003 Corrections 2025-05-28 15:11:27 +04:00
21ab6ed0eb CreateDocumentSalaryByPeriod 2025-05-27 23:48:15 +04:00
abbd84abc1 GetDataSalaryByPeriod 2025-05-27 22:53:10 +04:00
8a9d8727fe CreateDocumentSalesByPeriod 2025-05-27 22:08:13 +04:00
b06e0018d6 GetDataSaleByPeriod 2025-05-27 20:54:32 +04:00
a433ac5c79 CreateDocumentProductsByRestaurant 2025-05-27 19:09:06 +04:00
47cc5397a9 Reapply "MVC и тесты для Report"
This reverts commit 167bb1f2c5.
2025-05-27 15:19:32 +04:00
167bb1f2c5 Revert "MVC и тесты для Report"
This reverts commit a3726e4fab.
2025-05-27 15:17:21 +04:00
a3726e4fab MVC и тесты для Report 2025-05-27 15:16:46 +04:00
d206ca265c Prepare 2025-05-21 20:35:00 +04:00
1099d8c922 Сделана миграция на изменение в схеме таблицы Работник 2025-04-23 23:33:49 +04:00
5ef0ef450f Расчёт зарплаты 2025-04-23 23:28:58 +04:00
5c4f82e7b2 Изменения в должности 2025-04-23 19:06:31 +04:00
44ec32fe0f Первая миграция 2025-04-22 22:39:41 +04:00
84 changed files with 4401 additions and 256 deletions

View File

@@ -20,6 +20,20 @@ internal class ProductBuisnessLogicContract(IProductStorageContract productStora
return _productStorageContract.GetList(onlyActive) ?? throw new NullListException();
}
public List<ProductDataModel> GetAllProductsByRestaurant(string restaurantId, bool onlyActive = true)
{
if (restaurantId.IsEmpty())
{
throw new ArgumentNullException(nameof(restaurantId));
}
if (!restaurantId.IsGuid())
{
throw new ValidationException("The value in the field restaurantId is not a unique identifier.");
}
_logger.LogInformation("GetAllProducts params: {restaurantId}, {onlyActive}", restaurantId, onlyActive);
return _productStorageContract.GetList(onlyActive, restaurantId) ?? throw new NullListException();
}
public List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId)
{
_logger.LogInformation("GetProductHistoryByProduct for {productId}", productId);

View File

@@ -0,0 +1,101 @@
using Microsoft.Extensions.Logging;
using SPiluSZharuBuisnessLogic.OfficePackage;
using SPiluSZharuContracts.BuisnessLogicContracts;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.Extensions;
using SPiluSZharuContracts.StorageContracts;
namespace SPiluSZharuBuisnessLogic.Implementations;
internal class ReportContract(IProductStorageContract productStorageContract, ISaleStorageContract saleStorageContract, ISalaryStorageContract salaryStorageContract, BaseWordBuilder baseWordBuilder, BaseExcelBuilder baseExcelBuilder, BasePdfBuilder basePdfBuilder, ILogger logger) : IReportContract
{
private readonly IProductStorageContract _productStorageContract = productStorageContract;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly BaseWordBuilder _baseWordBuilder = baseWordBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder = baseExcelBuilder;
private readonly BasePdfBuilder _basePdfBuilder = basePdfBuilder;
private readonly ILogger _logger = logger;
internal static readonly string[] documentHeader = ["Ресторан", "Товар"];
internal static readonly string[] tableHeader = ["Дата", "Сумма", "Товар", "Кол-во"];
public async Task<Stream> CreateDocumentProductsByRestaurantAsync(CancellationToken ct)
{
_logger.LogInformation("Create report ProductsByRestaurant");
var data = await GetDataByProductsAsync(ct);
return _baseWordBuilder
.AddHeader("Продукты по ресторанам")
.AddParagraph($"Сформировано на дату {DateTime.Now}")
.AddTable([3000, 5000], [.. new List<string[]>() { documentHeader }.Union([.. data.SelectMany(x => (new List<string[]>() { new string[] { x.RestaurantName, "" } }).Union(x.Products.Select(y => new string[] { "", y })))])])
.Build();
}
public async Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Create report SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
var data = await GetDataBySalesAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
return _baseExcelBuilder
.AddHeader("Продажи за период", 0, 4)
.AddParagraph($"c {dateStart.ToShortDateString()} по {dateFinish.ToShortDateString()}", 2)
.AddTable([10, 10, 10, 10], [.. new List<string[]>() { tableHeader }.Union(data.SelectMany(x => (new List<string[]>() { new string[] { x.SaleDate.ToShortDateString(), x.Sum.ToString("N2"), "", "" } }).Union(x.Products!.Select(y => new string[] { "", "", y.ProductName, y.Count.ToString("N2") })).ToArray())).Union([["Всего", data.Sum(x => x.Sum).ToString("N2"), "", ""]])])
.Build();
}
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.WorkerFIO, x.TotalSalary))])
.Build();
}
public Task<List<RestaurantProductDataModel>> GetDataProductsByRestaurantAsync(CancellationToken ct)
{
_logger.LogInformation("Get data ProductsByRestaurant");
return GetDataByProductsAsync(ct);
}
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<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<RestaurantProductDataModel>> GetDataByProductsAsync(CancellationToken ct) => [.. (await _productStorageContract.GetListAsync(ct)).GroupBy(x => x.RestaurantName).Select(x => new RestaurantProductDataModel { RestaurantName = x.Key, Products = [.. x.Select(y => y.ProductName)] })];
private async Task<List<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish);
}
return [.. (await _saleStorageContract.GetListAsync(dateStart, dateFinish, ct)).OrderBy(x => x.SaleDate)];
}
private async Task<List<WorkerSalaryByPeriodDataModel>> GetDataBySalaryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish);
}
return [.. (await _salaryStorageContract.GetListAsync(dateStart, dateFinish, ct)).GroupBy(x => x.WorkerId).Select(x => new WorkerSalaryByPeriodDataModel { WorkerFIO = x.First().WorkerName, TotalSalary = x.Sum(y => y.Salary), FromPeriod = x.Min(y => y.SalaryDate), ToPeriod = x.Max(y => y.SalaryDate) }).OrderBy(x => x.WorkerFIO)];
}
}

View File

@@ -3,18 +3,22 @@ using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.Extensions;
using SPiluSZharuContracts.StorageContracts;
using SPiluSZharuContracts.Infrastructure;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
using Microsoft.Extensions.Logging;
namespace SPiluSZharuBuisnessLogic.Implementations;
internal class SalaryBuisnessLogicContract(ISalaryStorageContract salaryStorageContract, ISaleStorageContract saleStorageContract,
IPostStorageContract postStorageContract, IWorkerStorageContract workerStorageContract, ILogger logger) : ISalaryBuisnessLogicContract
IPostStorageContract postStorageContract, IWorkerStorageContract workerStorageContract, ILogger logger, IConfigurationSalary сonfiguration) : ISalaryBuisnessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
private readonly Lock _lockObject = new();
public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate)
{
@@ -52,13 +56,68 @@ internal class SalaryBuisnessLogicContract(ISalaryStorageContract salaryStorageC
var workers = _workerStorageContract.GetList() ?? throw new NullListException();
foreach (var worker in workers)
{
var sales = _saleStorageContract.GetList(startDate, finishDate, workerId: worker.Id)?.Sum(x => x.Sum) ??
throw new NullListException();
var post = _postStorageContract.GetElementById(worker.PostId) ??
throw new NullListException();
var salary = post.Salary + sales * 0.1;
var sales = _saleStorageContract.GetList(startDate, finishDate, workerId: worker.Id) ?? throw new NullListException();
var post = _postStorageContract.GetElementById(worker.PostId) ?? throw new NullListException();
var salary = post.ConfigurationModel switch
{
null => 0,
DeliveryManPostConfiguration dpc => CalculateSalaryForDeliveryMan(sales, startDate, finishDate, dpc),
OperatorPostConfiguration opc => CalculateSalaryForOperator(startDate, finishDate, opc),
PostConfiguration pc => pc.Rate,
};
_logger.LogDebug("The employee {workerId} was paid a salary of {salary}", worker.Id, salary);
_salaryStorageContract.AddElement(new SalaryDataModel(worker.Id, DateTime.SpecifyKind(finishDate, DateTimeKind.Utc), salary));
_salaryStorageContract.AddElement(new SalaryDataModel(worker.Id, finishDate, salary));
}
}
private double CalculateSalaryForDeliveryMan(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, DeliveryManPostConfiguration config)
{
var calcPercent = 0.0;
var dates = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
dates.Add(date);
}
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = _salaryConfiguration.MaxConcurrentThreads
};
Parallel.ForEach(dates, parallelOptions, date =>
{
var salesInDay = sales.Where(x => x.SaleDate.Date == date.Date).ToArray();
if (salesInDay.Length > 0)
{
lock (_lockObject)
{
calcPercent += (salesInDay.Sum(x => x.Sum) / salesInDay.Length) * config.SalePercent;
}
}
});
double calcBonusTask = 0;
try
{
calcBonusTask = sales.Where(x => x.Sum > _salaryConfiguration.ExtraSaleSum).Sum(x => x.Sum) * config.BonusForExtraSales;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in bonus calculation");
}
return config.Rate + calcPercent + calcBonusTask;
}
private double CalculateSalaryForOperator(DateTime startDate, DateTime finishDate, OperatorPostConfiguration config)
{
try
{
return config.Rate + config.PersonalCountTrendPremium * _workerStorageContract.GetWorkerTrend(startDate, finishDate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in the operator payroll process");
return 0;
}
}
}

View File

@@ -0,0 +1,12 @@
namespace SPiluSZharuBuisnessLogic.OfficePackage;
public abstract class BaseExcelBuilder
{
public abstract BaseExcelBuilder AddHeader(string header, int startIndex, int count);
public abstract BaseExcelBuilder AddParagraph(string text, int columnIndex);
public abstract BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,12 @@
namespace SPiluSZharuBuisnessLogic.OfficePackage;
public abstract class BasePdfBuilder
{
public abstract BasePdfBuilder AddHeader(string header);
public abstract BasePdfBuilder AddParagraph(string text);
public abstract BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,12 @@
namespace SPiluSZharuBuisnessLogic.OfficePackage;
public abstract class BaseWordBuilder
{
public abstract BaseWordBuilder AddHeader(string header);
public abstract BaseWordBuilder AddParagraph(string text);
public abstract BaseWordBuilder AddTable(int[] widths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,85 @@
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
using System.Text;
namespace SPiluSZharuBuisnessLogic.OfficePackage;
internal class MigraDocPdfBuilder : BasePdfBuilder
{
private readonly Document _document;
public MigraDocPdfBuilder()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
_document = new Document();
DefineStyles();
}
public override BasePdfBuilder AddHeader(string header)
{
_document.AddSection().AddParagraph(header, "NormalBold");
return this;
}
public override BasePdfBuilder AddParagraph(string text)
{
_document.LastSection.AddParagraph(text, "Normal");
return this;
}
public override BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var chart = new Chart(ChartType.Pie2D);
var series = chart.SeriesCollection.AddSeries();
series.Add(data.Select(x => x.Value).ToArray());
var xseries = chart.XValues.AddXSeries();
xseries.Add(data.Select(x => x.Caption).ToArray());
chart.DataLabel.Type = DataLabelType.Percent;
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
chart.Width = Unit.FromCentimeter(16);
chart.Height = Unit.FromCentimeter(12);
chart.TopArea.AddParagraph(title);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.TopArea.AddLegend();
_document.LastSection.Add(chart);
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(stream);
return stream;
}
private void DefineStyles()
{
var style = _document.Styles.AddStyle("NormalBold", "Normal");
style.Font.Bold = true;
}
}

View File

@@ -0,0 +1,303 @@
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
namespace SPiluSZharuBuisnessLogic.OfficePackage;
internal class OpenXmlExcelBuilder : BaseExcelBuilder
{
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public OpenXmlExcelBuilder()
{
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public override BaseExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "", StyleIndex.SimpleTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference =
new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
});
_rowIndex++;
return this;
}
public override BaseExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public override BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells, worksheetPart.Worksheet.Elements<SheetData>().First());
}
return stream;
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts() { Count = 2, KnownFonts = BooleanValue.FromBoolean(true) };
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) }
});
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) },
Bold = new Bold()
});
workbookStylesPart.Stylesheet.Append(fonts);
// Default Fill
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill() { PatternType = new EnumValue<PatternValues>(PatternValues.None) }
});
workbookStylesPart.Stylesheet.Append(fills);
// Default Border
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
borders.Append(new Border
{
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin }
});
workbookStylesPart.Stylesheet.Append(borders);
// Default cell format and a date cell format
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
SimpleTextWithoutBorder = 0,
SimpleTextWithBorder = 1,
BoldTextWithoutBorder = 2,
BoldTextWithBorder = 3
}
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>()
.FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@@ -0,0 +1,94 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace SPiluSZharuBuisnessLogic.OfficePackage;
internal class OpenXmlWordBuilder : BaseWordBuilder
{
private readonly Document _document;
private readonly Body _body;
public OpenXmlWordBuilder()
{
_document = new Document();
_body = _document.AppendChild(new Body());
}
public override BaseWordBuilder AddHeader(string header)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new RunProperties(new Bold()));
run.AppendChild(new Text(header));
return this;
}
public override BaseWordBuilder AddParagraph(string text)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new Text(text));
return this;
}
public override BaseWordBuilder AddTable(int[] widths, List<string[]> data)
{
if (widths == null || widths.Length == 0)
{
throw new ArgumentNullException(nameof(widths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != widths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
var table = new Table();
table.AppendChild(new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
)
));
// Заголовок
var tr = new TableRow();
for (var j = 0; j < widths.Length; ++j)
{
tr.Append(new TableCell(
new TableCellProperties(new TableCellWidth() { Width = widths[j].ToString() }),
new Paragraph(new Run(new RunProperties(new Bold()), new Text(data.First()[j])))));
}
table.Append(tr);
// Данные
table.Append(data.Skip(1).Select(x =>
new TableRow(x.Select(y => new TableCell(new Paragraph(new Run(new Text(y))))))));
_body.Append(table);
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var wordDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);
var mainPart = wordDocument.AddMainDocumentPart();
mainPart.Document = _document;
return stream;
}
}

View File

@@ -13,8 +13,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup>
<ItemGroup>

View File

@@ -7,6 +7,8 @@ public interface IProductAdapter
{
ProductOperationResponse GetList(bool includeDeleted);
ProductOperationResponse GetRestaurantList(string id, bool includeDeleted);
ProductOperationResponse GetHistory(string id);
ProductOperationResponse GetElement(string data);

View File

@@ -0,0 +1,18 @@
using SPiluSZharuContracts.AdapterContracts.OperationResponses;
namespace SPiluSZharuContracts.AdapterContracts;
public interface IReportAdapter
{
Task<ReportOperationResponse> GetDataProductsByRestaurantAsync(CancellationToken ct);
Task<ReportOperationResponse> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentProductsByRestaurantAsync(CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
}

View File

@@ -0,0 +1,19 @@
using SPiluSZharuContracts.Infrastructure;
using SPiluSZharuContracts.ViewModels;
namespace SPiluSZharuContracts.AdapterContracts.OperationResponses;
public class ReportOperationResponse : OperationResponse
{
public static ReportOperationResponse OK(List<RestaurantProductViewModel> data) => OK<ReportOperationResponse, List<RestaurantProductViewModel>>(data);
public static ReportOperationResponse OK(List<SaleViewModel> data) => OK<ReportOperationResponse, List<SaleViewModel>>(data);
public static ReportOperationResponse OK(List<WorkerSalaryByPeriodViewModel> data) => OK<ReportOperationResponse, List<WorkerSalaryByPeriodViewModel>>(data);
public static ReportOperationResponse OK(Stream data, string fileName) => OK<ReportOperationResponse, Stream>(data, fileName);
public static ReportOperationResponse BadRequest(string message) => BadRequest<ReportOperationResponse>(message);
public static ReportOperationResponse InternalServerError(string message) => InternalServerError<ReportOperationResponse>(message);
}

View File

@@ -10,5 +10,5 @@ public class PostBindingModel
public string? PostType { get; set; }
public double Salary { get; set; }
public string? ConfigurationJson { get; set; }
}

View File

@@ -8,5 +8,7 @@ public class ProductBindingModel
public string? ProductType { get; set; }
public string? RestaurantId { get; set; }
public double Price { get; set; }
}

View File

@@ -6,6 +6,8 @@ public interface IProductBuisnessLogicContract
{
List<ProductDataModel> GetAllProducts(bool onlyActive = true);
List<ProductDataModel> GetAllProductsByRestaurant(string restaurantId, bool onlyActive = true);
List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId);
ProductDataModel GetProductByData(string data);

View File

@@ -0,0 +1,18 @@
using SPiluSZharuContracts.DataModels;
namespace SPiluSZharuContracts.BuisnessLogicContracts;
public interface IReportContract
{
Task<List<RestaurantProductDataModel>> GetDataProductsByRestaurantAsync(CancellationToken ct);
Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<List<WorkerSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentProductsByRestaurantAsync(CancellationToken ct);
Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
}

View File

@@ -1,11 +1,14 @@
using SPiluSZharuContracts.Enums;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.Extensions;
using SPiluSZharuContracts.Infrastructure;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
namespace SPiluSZharuContracts.DataModels;
public class PostDataModel(string postId, string postName, PostType postType, double salary) : IValidation
public class PostDataModel(string postId, string postName, PostType postType, PostConfiguration configuration) : IValidation
{
public string Id { get; private set; } = postId;
@@ -13,7 +16,21 @@ public class PostDataModel(string postId, string postName, PostType postType, do
public PostType PostType { get; private set; } = postType;
public double Salary { get; private set; } = salary;
public PostConfiguration ConfigurationModel { get; private set; } = configuration;
public PostDataModel(string postId, string postName, PostType postType, string configurationJson) : this(postId, postName, postType, (PostConfiguration)null)
{
var obj = JToken.Parse(configurationJson);
if (obj is not null)
{
ConfigurationModel = obj.Value<string>("Type") switch
{
nameof(OperatorPostConfiguration) => JsonConvert.DeserializeObject<OperatorPostConfiguration>(configurationJson)!,
nameof(DeliveryManPostConfiguration) => JsonConvert.DeserializeObject<DeliveryManPostConfiguration>(configurationJson)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(configurationJson)!,
};
}
}
public void Validate()
{
@@ -29,7 +46,10 @@ public class PostDataModel(string postId, string postName, PostType postType, do
if (PostType == PostType.None)
throw new ValidationException("Field PostType is empty");
if (Salary <= 0)
throw new ValidationException("Field Salary is empty");
if (ConfigurationModel is null)
throw new ValidationException("Field ConfigurationModel is not initialized");
if (ConfigurationModel!.Rate <= 0)
throw new ValidationException("Field Rate is less or equal zero");
}
}

View File

@@ -5,19 +5,30 @@ using SPiluSZharuContracts.Infrastructure;
namespace SPiluSZharuContracts.DataModels;
public class ProductDataModel(string id, string productName, ProductType productType, double price, bool isDeleted) : IValidation
public class ProductDataModel(string id, string productName, ProductType productType, string restaurantId, double price, bool isDeleted) : IValidation
{
private readonly RestaurantDataModel? _restaurant;
public string Id { get; private set; } = id;
public string ProductName { get; private set; } = productName;
public ProductType ProductType { get; private set; } = productType;
public string RestaurantId { get; private set; } = restaurantId;
public double Price { get; private set; } = price;
public bool IsDeleted { get; private set; } = isDeleted;
public ProductDataModel(string id, string productName, ProductType productType, double price) : this(id, productName, productType, price, false) { }
public string RestaurantName => _restaurant?.RestaurantName ?? string.Empty;
public ProductDataModel(string id, string productName, ProductType productType, string restaurantId, double price, bool isDeleted, RestaurantDataModel restaurant) : this(id, productName, productType, restaurantId, price, isDeleted)
{
_restaurant = restaurant;
}
public ProductDataModel(string id, string productName, ProductType productType, string restaurantId, double price) : this(id, productName, productType, restaurantId, price, false) { }
public void Validate()
{
@@ -33,6 +44,12 @@ public class ProductDataModel(string id, string productName, ProductType product
if (ProductType == ProductType.None)
throw new ValidationException("Field ProductType is empty");
if (RestaurantId.IsEmpty())
throw new ValidationException("Field RestaurantId is empty");
if (!RestaurantId.IsGuid())
throw new ValidationException("The value in the field RestaurantId is not a unique identifier");
if (Price <= 0)
throw new ValidationException("Field Price is less than or equal to 0");
}

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuContracts.DataModels;
public class RestaurantProductDataModel
{
public required string RestaurantName { get; set; }
public required List<string> Products { get; set; }
}

View File

@@ -16,7 +16,7 @@ public class SaleDataModel : IValidation
public string? RestaurantId { get; private set; }
public DateTime SaleDate { get; private set; }
public DateTime SaleDate { get; private set; } = DateTime.UtcNow;
public double Sum { get; private set; }

View File

@@ -0,0 +1,12 @@
namespace SPiluSZharuContracts.DataModels;
public class WorkerSalaryByPeriodDataModel
{
public required string WorkerFIO { get; set; }
public double TotalSalary { get; set; }
public DateTime FromPeriod { get; set; }
public DateTime ToPeriod { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuContracts.Infrastructure;
public interface IConfigurationSalary
{
double ExtraSaleSum { get; }
int MaxConcurrentThreads { get; }
}

View File

@@ -10,6 +10,8 @@ public class OperationResponse
protected object? Result { get; set; }
protected string? FileName { get; set; }
public IActionResult GetResponse(HttpRequest request, HttpResponse response)
{
ArgumentNullException.ThrowIfNull(request);
@@ -21,12 +23,21 @@ public class OperationResponse
{
return new StatusCodeResult((int)StatusCode);
}
if (Result is Stream stream)
{
return new FileStreamResult(stream, "application/octet-stream")
{
FileDownloadName = FileName
};
}
return new ObjectResult(Result);
}
protected static TResult OK<TResult, TData>(TData data) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.OK, Result = data };
protected static TResult OK<TResult, TData>(TData data, string fileName) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.OK, Result = data, FileName = fileName };
protected static TResult NoContent<TResult>() where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.NoContent };
protected static TResult BadRequest<TResult>(string? errorMessage = null) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.BadRequest, Result = errorMessage };

View File

@@ -0,0 +1,10 @@
namespace SPiluSZharuContracts.Infrastructure.PostConfiguration;
public class DeliveryManPostConfiguration : PostConfiguration
{
public override string Type => nameof(DeliveryManPostConfiguration);
public double SalePercent { get; set; }
public double BonusForExtraSales { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuContracts.Infrastructure.PostConfiguration;
public class OperatorPostConfiguration : PostConfiguration
{
public override string Type => nameof(OperatorPostConfiguration);
public double PersonalCountTrendPremium { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuContracts.Infrastructure.PostConfiguration;
public class PostConfiguration
{
public virtual string Type => nameof(PostConfiguration);
public double Rate { get; set; }
}

View File

@@ -4,7 +4,9 @@ namespace SPiluSZharuContracts.StorageContracts;
public interface IProductStorageContract
{
List<ProductDataModel> GetList(bool onlyActive = true);
List<ProductDataModel> GetList(bool onlyActive = true, string? restaurantId = null);
Task<List<ProductDataModel>> GetListAsync(CancellationToken ct);
List<ProductHistoryDataModel> GetHistoryByProductId(string productId);

View File

@@ -6,5 +6,7 @@ public interface ISalaryStorageContract
{
List<SalaryDataModel> GetList(DateTime? startDate, DateTime? endDate, string? workerId = null);
Task<List<SalaryDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
void AddElement(SalaryDataModel salaryDataModel);
}

View File

@@ -7,6 +7,8 @@ public interface ISaleStorageContract
List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null,
string? workerId = null, string? restaurantId = null, string? productId = null);
Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
SaleDataModel? GetElementById(string id);
void AddElement(SaleDataModel saleDataModel);

View File

@@ -18,4 +18,6 @@ public interface IWorkerStorageContract
void UpdElement(WorkerDataModel workerDataModel);
void DelElement(string id);
int GetWorkerTrend(DateTime fromPeriod, DateTime toPeriod);
}

View File

@@ -8,5 +8,5 @@ public class PostViewModel
public required string PostType { get; set; }
public double Salary { get; set; }
public required string Configuration { get; set; }
}

View File

@@ -6,6 +6,10 @@ public class ProductViewModel
public required string ProductName { get; set; }
public required string RestaurantId { get; set; }
public required string RestaurantName { get; set; }
public required string ProductType { get; set; }
public double Price { get; set; }

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuContracts.ViewModels;
public class RestaurantProductViewModel
{
public required string RestaurantName { get; set; }
public required List<string> Products { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace SPiluSZharuContracts.ViewModels;
public class WorkerSalaryByPeriodViewModel
{
public required string WorkerFIO { get; set; }
public double TotalSalary { get; set; }
public DateTime FromPeriod { get; set; }
public DateTime ToPeriod { get; set; }
}

View File

@@ -0,0 +1,8 @@
using SPiluSZharuContracts.Infrastructure;
namespace SPiluSZharuDatabase;
class DefaultConfigurationDatabase : IConfigurationDatabase
{
public string ConnectionString => "";
}

View File

@@ -24,7 +24,8 @@ internal class PostStorageContract : IPostStorageContract
.ForMember(x => x.Id, x => x.Ignore())
.ForMember(x => x.PostId, x => x.MapFrom(src => src.Id))
.ForMember(x => x.IsActual, x => x.MapFrom(src => true))
.ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow));
.ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow))
.ForMember(x => x.Configuration, x => x.MapFrom(src => src.ConfigurationModel));
});
_mapper = new Mapper(config);
}

View File

@@ -18,6 +18,7 @@ internal class ProductStorageContract : IProductStorageContract
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Restaurant, RestaurantDataModel>();
cfg.CreateMap<Product, ProductDataModel>();
cfg.CreateMap<ProductDataModel, Product>()
.ForMember(x => x.IsDeleted, x => x.MapFrom(src => false));
@@ -26,15 +27,19 @@ internal class ProductStorageContract : IProductStorageContract
_mapper = new Mapper(config);
}
public List<ProductDataModel> GetList(bool onlyActive = true)
public List<ProductDataModel> GetList(bool onlyActive = true, string? restaurantId = null)
{
try
{
var query = _dbContext.Products.AsQueryable();
var query = _dbContext.Products.Include(x => x.Restaurant).AsQueryable();
if (onlyActive)
{
query = query.Where(x => !x.IsDeleted);
}
if (restaurantId is not null)
{
query = query.Where(x => x.RestaurantId == restaurantId);
}
return [.. query.Select(x => _mapper.Map<ProductDataModel>(x))];
}
catch (Exception ex)
@@ -44,6 +49,19 @@ internal class ProductStorageContract : IProductStorageContract
}
}
public async Task<List<ProductDataModel>> GetListAsync(CancellationToken ct)
{
try
{
return [.. await _dbContext.Products.Include(x => x.Restaurant).Select(x => _mapper.Map<ProductDataModel>(x)).ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<ProductHistoryDataModel> GetHistoryByProductId(string productId)
{
try
@@ -74,7 +92,7 @@ internal class ProductStorageContract : IProductStorageContract
{
try
{
return _mapper.Map<ProductDataModel>(_dbContext.Products.FirstOrDefault(x => x.ProductName == name && !x.IsDeleted));
return _mapper.Map<ProductDataModel>(_dbContext.Products.Include(x => x.Restaurant).FirstOrDefault(x => x.ProductName == name && !x.IsDeleted));
}
catch (Exception ex)
{
@@ -167,5 +185,5 @@ internal class ProductStorageContract : IProductStorageContract
}
}
private Product? GetProductById(string id) => _dbContext.Products.FirstOrDefault(x => x.Id == id && !x.IsDeleted);
private Product? GetProductById(string id) => _dbContext.Products.Include(x => x.Restaurant).FirstOrDefault(x => x.Id == id && !x.IsDeleted);
}

View File

@@ -45,6 +45,19 @@ internal class SalaryStorageContract : ISalaryStorageContract
}
}
public async Task<List<SalaryDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
return [.. await _dbContext.Salaries.Include(x => x.Worker).Where(x => x.SalaryDate >= startDate && x.SalaryDate <= endDate).Select(x => _mapper.Map<SalaryDataModel>(x)).ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void AddElement(SalaryDataModel salaryDataModel)
{
try

View File

@@ -61,6 +61,19 @@ internal class SaleStorageContract : ISaleStorageContract
}
}
public async Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
return [.. await _dbContext.Sales.Include(x => x.SaleProducts)!.ThenInclude(x => x.Product).Where(x => x.SaleDate >= startDate && x.SaleDate < endDate).Select(x => _mapper.Map<SaleDataModel>(x)).ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public SaleDataModel? GetElementById(string id)
{
try

View File

@@ -137,6 +137,7 @@ internal class WorkerStorageContract : IWorkerStorageContract
{
var element = GetWorkerById(id) ?? throw new ElementNotFoundException(id);
element.IsDeleted = true;
element.DateOfDelete = DateTime.UtcNow;
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
@@ -151,6 +152,21 @@ internal class WorkerStorageContract : IWorkerStorageContract
}
}
public int GetWorkerTrend(DateTime fromPeriod, DateTime toPeriod)
{
try
{
var countWorkersOnBegining = _dbContext.Workers.Count(x => x.EmploymentDate < fromPeriod && (!x.IsDeleted || x.DateOfDelete > fromPeriod));
var countWorkersOnEnding = _dbContext.Workers.Count(x => x.EmploymentDate < toPeriod && (!x.IsDeleted || x.DateOfDelete > toPeriod));
return countWorkersOnEnding - countWorkersOnBegining;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Worker? GetWorkerById(string id) => AddPost(_dbContext.Workers.FirstOrDefault(x => x.Id == id && !x.IsDeleted));
private IQueryable<Worker> JoinPost(IQueryable<Worker> query)

View File

@@ -0,0 +1,324 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using SPiluSZharuDatabase;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
[DbContext(typeof(SPiluSZharuDbContext))]
[Migration("20250422183326_FirstMigration")]
partial class FirstMigration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("SPiluSZharuDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.Property<double>("Salary")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ProductType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ProductName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductHistories");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Restaurant", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("PrevPrevRestaurantName")
.HasColumnType("text");
b.Property<string>("PrevRestaurantName")
.HasColumnType("text");
b.Property<string>("RestaurantName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantName")
.IsUnique();
b.ToTable("Restaurants");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("WorkerSalary")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("WorkerId");
b.ToTable("Salaries");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
b.Property<string>("RestaurantId")
.HasColumnType("text");
b.Property<DateTime>("SaleDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantId");
b.HasIndex("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.Property<string>("SaleId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("SaleId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("PhoneNumber")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Restaurant", "Restaurant")
.WithMany()
.HasForeignKey("RestaurantId");
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Restaurant");
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("SaleProducts")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SPiluSZharuDatabase.Models.Sale", "Sale")
.WithMany("SaleProducts")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,257 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
/// <inheritdoc />
public partial class FirstMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Posts",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
PostId = table.Column<string>(type: "text", nullable: false),
PostName = table.Column<string>(type: "text", nullable: false),
PostType = table.Column<int>(type: "integer", nullable: false),
Salary = table.Column<double>(type: "double precision", nullable: false),
IsActual = table.Column<bool>(type: "boolean", nullable: false),
ChangeDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Posts", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ProductName = table.Column<string>(type: "text", nullable: false),
ProductType = table.Column<int>(type: "integer", nullable: false),
Price = table.Column<double>(type: "double precision", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Restaurants",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
RestaurantName = table.Column<string>(type: "text", nullable: false),
PrevRestaurantName = table.Column<string>(type: "text", nullable: true),
PrevPrevRestaurantName = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Restaurants", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Workers",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
FIO = table.Column<string>(type: "text", nullable: false),
PostId = table.Column<string>(type: "text", nullable: false),
PhoneNumber = table.Column<string>(type: "text", nullable: false),
BirthDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
EmploymentDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Workers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductHistories",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ProductId = table.Column<string>(type: "text", nullable: false),
OldPrice = table.Column<double>(type: "double precision", nullable: false),
ChangeDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductHistories", x => x.Id);
table.ForeignKey(
name: "FK_ProductHistories_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Salaries",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
WorkerId = table.Column<string>(type: "text", nullable: false),
SalaryDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
WorkerSalary = table.Column<double>(type: "double precision", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Salaries", x => x.Id);
table.ForeignKey(
name: "FK_Salaries_Workers_WorkerId",
column: x => x.WorkerId,
principalTable: "Workers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sales",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
WorkerId = table.Column<string>(type: "text", nullable: false),
RestaurantId = table.Column<string>(type: "text", nullable: true),
SaleDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
Sum = table.Column<double>(type: "double precision", nullable: false),
IsCancel = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Sales", x => x.Id);
table.ForeignKey(
name: "FK_Sales_Restaurants_RestaurantId",
column: x => x.RestaurantId,
principalTable: "Restaurants",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Sales_Workers_WorkerId",
column: x => x.WorkerId,
principalTable: "Workers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "SaleProducts",
columns: table => new
{
SaleId = table.Column<string>(type: "text", nullable: false),
ProductId = table.Column<string>(type: "text", nullable: false),
Count = table.Column<int>(type: "integer", nullable: false),
Price = table.Column<double>(type: "double precision", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_SaleProducts", x => new { x.SaleId, x.ProductId });
table.ForeignKey(
name: "FK_SaleProducts_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_SaleProducts_Sales_SaleId",
column: x => x.SaleId,
principalTable: "Sales",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Posts_PostId_IsActual",
table: "Posts",
columns: new[] { "PostId", "IsActual" },
unique: true,
filter: "\"IsActual\" = TRUE");
migrationBuilder.CreateIndex(
name: "IX_Posts_PostName_IsActual",
table: "Posts",
columns: new[] { "PostName", "IsActual" },
unique: true,
filter: "\"IsActual\" = TRUE");
migrationBuilder.CreateIndex(
name: "IX_ProductHistories_ProductId",
table: "ProductHistories",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Products_ProductName_IsDeleted",
table: "Products",
columns: new[] { "ProductName", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
migrationBuilder.CreateIndex(
name: "IX_Restaurants_RestaurantName",
table: "Restaurants",
column: "RestaurantName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Salaries_WorkerId",
table: "Salaries",
column: "WorkerId");
migrationBuilder.CreateIndex(
name: "IX_SaleProducts_ProductId",
table: "SaleProducts",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Sales_RestaurantId",
table: "Sales",
column: "RestaurantId");
migrationBuilder.CreateIndex(
name: "IX_Sales_WorkerId",
table: "Sales",
column: "WorkerId");
migrationBuilder.CreateIndex(
name: "IX_Workers_PhoneNumber",
table: "Workers",
column: "PhoneNumber",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Posts");
migrationBuilder.DropTable(
name: "ProductHistories");
migrationBuilder.DropTable(
name: "Salaries");
migrationBuilder.DropTable(
name: "SaleProducts");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Sales");
migrationBuilder.DropTable(
name: "Restaurants");
migrationBuilder.DropTable(
name: "Workers");
}
}
}

View File

@@ -0,0 +1,325 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using SPiluSZharuDatabase;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
[DbContext(typeof(SPiluSZharuDbContext))]
[Migration("20250423150347_ChangeFieldsInPost")]
partial class ChangeFieldsInPost
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("SPiluSZharuDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ProductType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ProductName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductHistories");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Restaurant", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("PrevPrevRestaurantName")
.HasColumnType("text");
b.Property<string>("PrevRestaurantName")
.HasColumnType("text");
b.Property<string>("RestaurantName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantName")
.IsUnique();
b.ToTable("Restaurants");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("WorkerSalary")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("WorkerId");
b.ToTable("Salaries");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
b.Property<string>("RestaurantId")
.HasColumnType("text");
b.Property<DateTime>("SaleDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantId");
b.HasIndex("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.Property<string>("SaleId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("SaleId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("PhoneNumber")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Restaurant", "Restaurant")
.WithMany()
.HasForeignKey("RestaurantId");
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Restaurant");
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("SaleProducts")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SPiluSZharuDatabase.Models.Sale", "Sale")
.WithMany("SaleProducts")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
/// <inheritdoc />
public partial class ChangeFieldsInPost : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Salary",
table: "Posts");
migrationBuilder.AddColumn<string>(
name: "Configuration",
table: "Posts",
type: "jsonb",
nullable: false,
defaultValue: "{\"Rate\": 0, \"Type\": \"PostConfiguration\"}");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Configuration",
table: "Posts");
migrationBuilder.AddColumn<double>(
name: "Salary",
table: "Posts",
type: "double precision",
nullable: false,
defaultValue: 0.0);
}
}
}

View File

@@ -0,0 +1,328 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using SPiluSZharuDatabase;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
[DbContext(typeof(SPiluSZharuDbContext))]
[Migration("20250423193249_AddDateOfDeleteInWorker")]
partial class AddDateOfDeleteInWorker
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("SPiluSZharuDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ProductType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ProductName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductHistories");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Restaurant", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("PrevPrevRestaurantName")
.HasColumnType("text");
b.Property<string>("PrevRestaurantName")
.HasColumnType("text");
b.Property<string>("RestaurantName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantName")
.IsUnique();
b.ToTable("Restaurants");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("WorkerSalary")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("WorkerId");
b.ToTable("Salaries");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
b.Property<string>("RestaurantId")
.HasColumnType("text");
b.Property<DateTime>("SaleDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantId");
b.HasIndex("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.Property<string>("SaleId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("SaleId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<DateTime?>("DateOfDelete")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("PhoneNumber")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Restaurant", "Restaurant")
.WithMany()
.HasForeignKey("RestaurantId");
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Restaurant");
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("SaleProducts")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SPiluSZharuDatabase.Models.Sale", "Sale")
.WithMany("SaleProducts")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
/// <inheritdoc />
public partial class AddDateOfDeleteInWorker : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "DateOfDelete",
table: "Workers",
type: "timestamp without time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DateOfDelete",
table: "Workers");
}
}
}

View File

@@ -0,0 +1,325 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using SPiluSZharuDatabase;
#nullable disable
namespace SPiluSZharuDatabase.Migrations
{
[DbContext(typeof(SPiluSZharuDbContext))]
partial class SPiluSZharuDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("SPiluSZharuDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ProductType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ProductName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductHistories");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Restaurant", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("PrevPrevRestaurantName")
.HasColumnType("text");
b.Property<string>("PrevRestaurantName")
.HasColumnType("text");
b.Property<string>("RestaurantName")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantName")
.IsUnique();
b.ToTable("Restaurants");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("WorkerSalary")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("WorkerId");
b.ToTable("Salaries");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
b.Property<string>("RestaurantId")
.HasColumnType("text");
b.Property<DateTime>("SaleDate")
.HasColumnType("timestamp without time zone");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.Property<string>("WorkerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RestaurantId");
b.HasIndex("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.Property<string>("SaleId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("SaleId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<DateTime?>("DateOfDelete")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("PhoneNumber")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.ProductHistory", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Salary", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Restaurant", "Restaurant")
.WithMany()
.HasForeignKey("RestaurantId");
b.HasOne("SPiluSZharuDatabase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Restaurant");
b.Navigation("Worker");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.SaleProduct", b =>
{
b.HasOne("SPiluSZharuDatabase.Models.Product", "Product")
.WithMany("SaleProducts")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SPiluSZharuDatabase.Models.Sale", "Sale")
.WithMany("SaleProducts")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Sale", b =>
{
b.Navigation("SaleProducts");
});
modelBuilder.Entity("SPiluSZharuDatabase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,4 +1,5 @@
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
namespace SPiluSZharuDatabase.Models;
@@ -12,7 +13,7 @@ internal class Post
public PostType PostType { get; set; }
public double Salary { get; set; }
public required PostConfiguration Configuration { get; set; }
public bool IsActual { get; set; }

View File

@@ -11,10 +11,14 @@ internal class Product
public ProductType ProductType { get; set; }
public required string RestaurantId { get; set; }
public double Price { get; set; }
public bool IsDeleted { get; set; }
public Restaurant? Restaurant { get; set; }
[ForeignKey("ProductId")]
public List<ProductHistory>? ProductHistories { get; set; }

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using SPiluSZharuContracts.DataModels;
using System.ComponentModel.DataAnnotations.Schema;
namespace SPiluSZharuDatabase.Models;
@@ -13,4 +14,7 @@ internal class Restaurant
public string? PrevRestaurantName { get; set; }
public string? PrevPrevRestaurantName { get; set; }
[ForeignKey("ManufacturerId")]
public List<Product>? Products { get; set; }
}

View File

@@ -20,6 +20,8 @@ internal class Worker
public bool IsDeleted { get; set; }
public DateTime? DateOfDelete { get; set; }
[NotMapped]
public Post? Post { get; set; }

View File

@@ -9,6 +9,11 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>

View File

@@ -1,7 +1,9 @@
using SPiluSZharuContracts.Infrastructure;
using Microsoft.EntityFrameworkCore;
using SPiluSZharuDatabase.Models;
using System;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace SPiluSZharuDatabase;
@@ -43,9 +45,23 @@ internal class SPiluSZharuDbContext : DbContext
.IsUnique()
.HasFilter($"\"{nameof(Product.IsDeleted)}\" = FALSE");
modelBuilder
.Entity<Product>()
.HasOne(e => e.Restaurant)
.WithMany(e => e.Products)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<SaleProduct>().HasKey(x => new { x.SaleId, x.ProductId });
modelBuilder.Entity<Worker>().HasIndex(x => x.PhoneNumber).IsUnique();
modelBuilder.Entity<Post>()
.Property(x => x.Configuration)
.HasColumnType("jsonb")
.HasConversion(
x => SerializePostConfiguration(x),
x => DeserialzePostConfiguration(x)
);
}
public DbSet<Restaurant> Restaurants { get; set; }
@@ -63,4 +79,13 @@ internal class SPiluSZharuDbContext : DbContext
public DbSet<SaleProduct> SaleProducts { get; set; }
public DbSet<Worker> Workers { get; set; }
private static string SerializePostConfiguration(PostConfiguration postConfiguration) => JsonConvert.SerializeObject(postConfiguration);
private static PostConfiguration DeserialzePostConfiguration(string jsonString) => JToken.Parse(jsonString).Value<string>("Type") switch
{
nameof(OperatorPostConfiguration) => JsonConvert.DeserializeObject<OperatorPostConfiguration>(jsonString)!,
nameof(DeliveryManPostConfiguration) => JsonConvert.DeserializeObject<DeliveryManPostConfiguration>(jsonString)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(jsonString)!,
};
}

View File

@@ -0,0 +1,11 @@
using Microsoft.EntityFrameworkCore.Design;
namespace SPiluSZharuDatabase;
internal class SampleContextFactory : IDesignTimeDbContextFactory<SPiluSZharuDbContext>
{
public SPiluSZharuDbContext CreateDbContext(string[] args)
{
return new SPiluSZharuDbContext(new DefaultConfigurationDatabase());
}
}

View File

@@ -5,6 +5,7 @@ using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.StorageContracts;
using Microsoft.Extensions.Logging;
using Moq;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
namespace SPiluSZharuTests.BuisnessLogicContractsTests;
@@ -33,9 +34,9 @@ internal class PostBuisnessLogicContractTests
//Arrange
var listOriginal = new List<PostDataModel>()
{
new(Guid.NewGuid().ToString(),"name 1", PostType.Operator, 10),
new(Guid.NewGuid().ToString(), "name 2", PostType.Operator, 10),
new(Guid.NewGuid().ToString(), "name 3", PostType.Operator, 10),
new(Guid.NewGuid().ToString(),"name 1", PostType.Operator, new PostConfiguration() { Rate = 10 }),
new(Guid.NewGuid().ToString(), "name 2", PostType.Operator, new PostConfiguration() { Rate = 10 }),
new(Guid.NewGuid().ToString(), "name 3", PostType.Operator, new PostConfiguration() { Rate = 10 }),
};
_postStorageContract.Setup(x => x.GetList()).Returns(listOriginal);
//Act
@@ -89,8 +90,8 @@ internal class PostBuisnessLogicContractTests
var postId = Guid.NewGuid().ToString();
var listOriginal = new List<PostDataModel>()
{
new(postId, "name 1", PostType.Operator, 10),
new(postId, "name 2", PostType.Operator, 10)
new(postId, "name 1", PostType.Operator, new PostConfiguration() { Rate = 10 }),
new(postId, "name 2", PostType.Operator, new PostConfiguration() { Rate = 10 })
};
_postStorageContract.Setup(x => x.GetPostWithHistory(It.IsAny<string>())).Returns(listOriginal);
//Act
@@ -154,7 +155,7 @@ internal class PostBuisnessLogicContractTests
{
//Arrange
var id = Guid.NewGuid().ToString();
var record = new PostDataModel(id, "name", PostType.Operator, 10);
var record = new PostDataModel(id, "name", PostType.Operator, new PostConfiguration() { Rate = 10 });
_postStorageContract.Setup(x => x.GetElementById(id)).Returns(record);
//Act
var element = _postBuisnessLogicContract.GetPostByData(id);
@@ -169,7 +170,7 @@ internal class PostBuisnessLogicContractTests
{
//Arrange
var postName = "name";
var record = new PostDataModel(Guid.NewGuid().ToString(), postName, PostType.Operator, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), postName, PostType.Operator, new PostConfiguration() { Rate = 10 });
_postStorageContract.Setup(x => x.GetElementByName(postName)).Returns(record);
//Act
var element = _postBuisnessLogicContract.GetPostByData(postName);
@@ -225,11 +226,11 @@ internal class PostBuisnessLogicContractTests
{
//Arrange
var flag = false;
var record = new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 });
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>()))
.Callback((PostDataModel x) =>
{
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.Salary == record.Salary;
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.ConfigurationModel.Rate == record.ConfigurationModel.Rate;
});
//Act
_postBuisnessLogicContract.InsertPost(record);
@@ -244,7 +245,7 @@ internal class PostBuisnessLogicContractTests
//Arrange
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data"));
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _postBuisnessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<ElementExistsException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -260,7 +261,7 @@ internal class PostBuisnessLogicContractTests
public void InsertPost_InvalidRecord_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.InsertPost(new PostDataModel("id", "name", PostType.OrderPicker, 10)), Throws.TypeOf<ValidationException>());
Assert.That(() => _postBuisnessLogicContract.InsertPost(new PostDataModel("id", "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<ValidationException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Never);
}
@@ -270,7 +271,7 @@ internal class PostBuisnessLogicContractTests
//Arrange
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10)), Throws.TypeOf<StorageException>());
Assert.That(() => _postBuisnessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<StorageException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -279,11 +280,11 @@ internal class PostBuisnessLogicContractTests
{
//Arrange
var flag = false;
var record = new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 });
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>()))
.Callback((PostDataModel x) =>
{
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.Salary == record.Salary;
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.ConfigurationModel.Rate == record.ConfigurationModel.Rate;
});
//Act
_postBuisnessLogicContract.UpdatePost(record);
@@ -298,7 +299,7 @@ internal class PostBuisnessLogicContractTests
//Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementNotFoundException(""));
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10)), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<ElementNotFoundException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -308,7 +309,7 @@ internal class PostBuisnessLogicContractTests
//Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data"));
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "anme", PostType.OrderPicker, 10)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "anme", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<ElementExistsException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -324,7 +325,7 @@ internal class PostBuisnessLogicContractTests
public void UpdatePost_InvalidRecord_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new PostDataModel("id", "name", PostType.OrderPicker, 10)), Throws.TypeOf<ValidationException>());
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new PostDataModel("id", "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<ValidationException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Never);
}
@@ -334,7 +335,7 @@ internal class PostBuisnessLogicContractTests
//Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, 10)), Throws.TypeOf<StorageException>());
Assert.That(() => _postBuisnessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 10 })), Throws.TypeOf<StorageException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}

View File

@@ -5,6 +5,7 @@ using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.StorageContracts;
using Microsoft.Extensions.Logging;
using Moq;
using SPiluSZharuContracts.BuisnessLogicContracts;
namespace SPiluSZharuTests.BuisnessLogicContractsTests;
@@ -33,11 +34,11 @@ internal class ProductBuisnessLogicContractTests
//Arrange
var listOriginal = new List<ProductDataModel>()
{
new(Guid.NewGuid().ToString(), "name 1", ProductType.Pizza, 10, false),
new(Guid.NewGuid().ToString(), "name 2", ProductType.Pizza, 10, true),
new(Guid.NewGuid().ToString(), "name 3", ProductType.Pizza, 10, false),
new(Guid.NewGuid().ToString(), "name 1", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false),
new(Guid.NewGuid().ToString(), "name 2", ProductType.Pizza, Guid.NewGuid().ToString(), 10, true),
new(Guid.NewGuid().ToString(), "name 3", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false),
};
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>())).Returns(listOriginal);
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Returns(listOriginal);
//Act
var listOnlyActive = _productBuisnessLogicContract.GetAllProducts(true);
var list = _productBuisnessLogicContract.GetAllProducts(false);
@@ -49,15 +50,15 @@ internal class ProductBuisnessLogicContractTests
Assert.That(listOnlyActive, Is.EquivalentTo(listOriginal));
Assert.That(list, Is.EquivalentTo(listOriginal));
});
_productStorageContract.Verify(x => x.GetList(true), Times.Once);
_productStorageContract.Verify(x => x.GetList(false), Times.Once);
_productStorageContract.Verify(x => x.GetList(true, null), Times.Once);
_productStorageContract.Verify(x => x.GetList(false, null), Times.Once);
}
[Test]
public void GetAllProducts_ReturnEmptyList_Test()
{
//Arrange
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>())).Returns([]);
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Returns([]);
//Act
var listOnlyActive = _productBuisnessLogicContract.GetAllProducts(true);
var list = _productBuisnessLogicContract.GetAllProducts(false);
@@ -69,7 +70,7 @@ internal class ProductBuisnessLogicContractTests
Assert.That(listOnlyActive, Has.Count.EqualTo(0));
Assert.That(list, Has.Count.EqualTo(0));
});
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>()), Times.Exactly(2));
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), null), Times.Exactly(2));
}
[Test]
@@ -77,17 +78,99 @@ internal class ProductBuisnessLogicContractTests
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProducts(It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>()), Times.Once);
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Once);
}
[Test]
public void GetAllProducts_StorageThrowError_ThrowException_Test()
{
//Arrange
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>())).Throws(new StorageException(new InvalidOperationException()));
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProducts(It.IsAny<bool>()), Throws.TypeOf<StorageException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>()), Times.Once);
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Once);
}
[Test]
public void GetAllProductsByRestaurant_ReturnListOfRecords_Test()
{
//Arrange
var restaurantId = Guid.NewGuid().ToString();
var listOriginal = new List<ProductDataModel>()
{
new(Guid.NewGuid().ToString(), "name 1",ProductType.Pizza, Guid.NewGuid().ToString(), 10, false),
new(Guid.NewGuid().ToString(), "name 2", ProductType.Pizza, Guid.NewGuid().ToString(), 10, true),
new(Guid.NewGuid().ToString(), "name 3", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false),
};
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Returns(listOriginal);
//Act
var listOnlyActive = _productBuisnessLogicContract.GetAllProductsByRestaurant(restaurantId, true);
var list = _productBuisnessLogicContract.GetAllProductsByRestaurant(restaurantId, false);
//Assert
Assert.Multiple(() =>
{
Assert.That(listOnlyActive, Is.Not.Null);
Assert.That(list, Is.Not.Null);
Assert.That(listOnlyActive, Is.EquivalentTo(listOriginal));
Assert.That(list, Is.EquivalentTo(listOriginal));
});
_productStorageContract.Verify(x => x.GetList(true, restaurantId), Times.Once);
_productStorageContract.Verify(x => x.GetList(false, restaurantId), Times.Once);
}
[Test]
public void GetAllProductsByRestaurant_ReturnEmptyList_Test()
{
//Arrange
var restaurantId = Guid.NewGuid().ToString();
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Returns([]);
//Act
var listOnlyActive = _productBuisnessLogicContract.GetAllProductsByRestaurant(restaurantId, true);
var list = _productBuisnessLogicContract.GetAllProductsByRestaurant(restaurantId, false);
//Assert
Assert.Multiple(() =>
{
Assert.That(listOnlyActive, Is.Not.Null);
Assert.That(list, Is.Not.Null);
Assert.That(listOnlyActive, Has.Count.EqualTo(0));
Assert.That(list, Has.Count.EqualTo(0));
});
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), restaurantId), Times.Exactly(2));
}
[Test]
public void GetAllProductsByRestaurant_RestaurantIdIsNullOrEmpty_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProductsByRestaurant(null, It.IsAny<bool>()), Throws.TypeOf<ArgumentNullException>());
Assert.That(() => _productBuisnessLogicContract.GetAllProductsByRestaurant(string.Empty, It.IsAny<bool>()), Throws.TypeOf<ArgumentNullException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Never);
}
[Test]
public void GetAllProductsByRestaurant_RestaurantIdIsNotGuid_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProductsByRestaurant("restaurantId", It.IsAny<bool>()), Throws.TypeOf<ValidationException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Never);
}
[Test]
public void GetAllProductsByRestaurant_ReturnNull_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProductsByRestaurant(Guid.NewGuid().ToString(), It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Once);
}
[Test]
public void GetAllProductsByRestaurant_StorageThrowError_ThrowException_Test()
{
//Arrange
_productStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.GetAllProductsByRestaurant(Guid.NewGuid().ToString(), It.IsAny<bool>()), Throws.TypeOf<StorageException>());
_productStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>()), Times.Once);
}
[Test]
@@ -163,7 +246,7 @@ internal class ProductBuisnessLogicContractTests
{
//Arrange
var id = Guid.NewGuid().ToString();
var record = new ProductDataModel(id, "name", ProductType.Pizza, 10, false);
var record = new ProductDataModel(id, "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false);
_productStorageContract.Setup(x => x.GetElementById(id)).Returns(record);
//Act
var element = _productBuisnessLogicContract.GetProductByData(id);
@@ -178,7 +261,7 @@ internal class ProductBuisnessLogicContractTests
{
//Arrange
var name = "name";
var record = new ProductDataModel(Guid.NewGuid().ToString(), name, ProductType.Pizza, 10, false);
var record = new ProductDataModel(Guid.NewGuid().ToString(), name, ProductType.Pizza, Guid.NewGuid().ToString(), 10, false);
_productStorageContract.Setup(x => x.GetElementByName(name)).Returns(record);
//Act
var element = _productBuisnessLogicContract.GetProductByData(name);
@@ -232,7 +315,7 @@ internal class ProductBuisnessLogicContractTests
{
//Arrange
var flag = false;
var record = new ProductDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false);
var record = new ProductDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false);
_productStorageContract.Setup(x => x.AddElement(It.IsAny<ProductDataModel>()))
.Callback((ProductDataModel x) =>
{
@@ -252,7 +335,7 @@ internal class ProductBuisnessLogicContractTests
//Arrange
_productStorageContract.Setup(x => x.AddElement(It.IsAny<ProductDataModel>())).Throws(new ElementExistsException("Data", "Data"));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<ElementExistsException>());
_productStorageContract.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Once);
}
@@ -268,7 +351,7 @@ internal class ProductBuisnessLogicContractTests
public void InsertProduct_InvalidRecord_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new ProductDataModel("id", "name", ProductType.Pizza, 10, false)), Throws.TypeOf<ValidationException>());
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new ProductDataModel("id", "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<ValidationException>());
_productStorageContract.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Never);
}
@@ -278,7 +361,7 @@ internal class ProductBuisnessLogicContractTests
//Arrange
_productStorageContract.Setup(x => x.AddElement(It.IsAny<ProductDataModel>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false)), Throws.TypeOf<StorageException>());
Assert.That(() => _productBuisnessLogicContract.InsertProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<StorageException>());
_productStorageContract.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Once);
}
@@ -287,7 +370,7 @@ internal class ProductBuisnessLogicContractTests
{
//Arrange
var flag = false;
var record = new ProductDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false);
var record = new ProductDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false);
_productStorageContract.Setup(x => x.UpdElement(It.IsAny<ProductDataModel>()))
.Callback((ProductDataModel x) =>
{
@@ -307,7 +390,7 @@ internal class ProductBuisnessLogicContractTests
//Arrange
_productStorageContract.Setup(x => x.UpdElement(It.IsAny<ProductDataModel>())).Throws(new ElementNotFoundException(""));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false)), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<ElementNotFoundException>());
_productStorageContract.Verify(x => x.UpdElement(It.IsAny<ProductDataModel>()), Times.Once);
}
@@ -317,7 +400,7 @@ internal class ProductBuisnessLogicContractTests
//Arrange
_productStorageContract.Setup(x => x.UpdElement(It.IsAny<ProductDataModel>())).Throws(new ElementExistsException("Data", "Data"));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<ElementExistsException>());
_productStorageContract.Verify(x => x.UpdElement(It.IsAny<ProductDataModel>()), Times.Once);
}
@@ -333,7 +416,7 @@ internal class ProductBuisnessLogicContractTests
public void UpdateProduct_InvalidRecord_ThrowException_Test()
{
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new ProductDataModel("id", "name", ProductType.Pizza, 10, false)), Throws.TypeOf<ValidationException>());
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new ProductDataModel("id", "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<ValidationException>());
_productStorageContract.Verify(x => x.UpdElement(It.IsAny<ProductDataModel>()), Times.Never);
}
@@ -343,7 +426,7 @@ internal class ProductBuisnessLogicContractTests
//Arrange
_productStorageContract.Setup(x => x.UpdElement(It.IsAny<ProductDataModel>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, 10, false)), Throws.TypeOf<StorageException>());
Assert.That(() => _productBuisnessLogicContract.UpdateProduct(new(Guid.NewGuid().ToString(), "name", ProductType.Pizza, Guid.NewGuid().ToString(), 10, false)), Throws.TypeOf<StorageException>());
_productStorageContract.Verify(x => x.UpdElement(It.IsAny<ProductDataModel>()), Times.Once);
}

View File

@@ -0,0 +1,378 @@
using Microsoft.Extensions.Logging;
using Moq;
using SPiluSZharuBuisnessLogic.Implementations;
using SPiluSZharuBuisnessLogic.OfficePackage;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.StorageContracts;
namespace SPiluSZharuTests.BuisnessLogicContractsTests;
[TestFixture]
internal class ReportContractTests
{
private ReportContract _reportContract;
private Mock<IProductStorageContract> _productStorageContract;
private Mock<ISaleStorageContract> _saleStorageContract;
private Mock<ISalaryStorageContract> _salaryStorageContract;
private Mock<BaseWordBuilder> _baseWordBuilder;
private Mock<BaseExcelBuilder> _baseExcelBuilder;
private Mock<BasePdfBuilder> _basePdfBuilder;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_productStorageContract = new Mock<IProductStorageContract>();
_saleStorageContract = new Mock<ISaleStorageContract>();
_salaryStorageContract = new Mock<ISalaryStorageContract>();
_baseWordBuilder = new Mock<BaseWordBuilder>();
_baseExcelBuilder = new Mock<BaseExcelBuilder>();
_basePdfBuilder = new Mock<BasePdfBuilder>();
_reportContract = new ReportContract(_productStorageContract.Object, _saleStorageContract.Object, _salaryStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object);
}
[SetUp]
public void SetUp()
{
_productStorageContract.Reset();
_saleStorageContract.Reset();
_salaryStorageContract.Reset();
}
[Test]
public async Task GetDataProductsByRestaurant_ShouldSuccess_Test()
{
//Arrange
var restaurant1 = new RestaurantDataModel(Guid.NewGuid().ToString(), "name1");
var restaurant2 = new RestaurantDataModel(Guid.NewGuid().ToString(), "name2");
_productStorageContract.Setup(x => x.GetListAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<ProductDataModel>()
{
new(Guid.NewGuid().ToString(), "name 1.1", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 2.1", ProductType.Pizza, restaurant2.Id, 10, false, restaurant2),
new(Guid.NewGuid().ToString(), "name 1.2", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 1.3", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 2.2", ProductType.Pizza, restaurant2.Id, 10, false, restaurant2)
}));
//Act
var data = await _reportContract.GetDataProductsByRestaurantAsync(CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(2));
Assert.Multiple(() =>
{
Assert.That(data.First(x => x.RestaurantName == restaurant1.RestaurantName).Products, Has.Count.EqualTo(3));
Assert.That(data.First(x => x.RestaurantName == restaurant2.RestaurantName).Products, Has.Count.EqualTo(2));
});
_productStorageContract.Verify(x => x.GetListAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataProductsByRestaurant_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_productStorageContract.Setup(x => x.GetListAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<ProductDataModel>()));
//Act
var data = await _reportContract.GetDataProductsByRestaurantAsync(CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_productStorageContract.Verify(x => x.GetListAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public void GetDataProductsByRestaurant_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_productStorageContract.Setup(x => x.GetListAsync(It.IsAny<CancellationToken>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(async () => await _reportContract.GetDataProductsByRestaurantAsync(CancellationToken.None), Throws.TypeOf<StorageException>());
_productStorageContract.Verify(x => x.GetListAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataSalesByPeriod_ShouldSuccess_Test()
{
//Arrange
_saleStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SaleDataModel>()
{
new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, [new SaleProductDataModel("", Guid.NewGuid().ToString(), 10, 10)]),
new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, [new SaleProductDataModel("", Guid.NewGuid().ToString(), 10, 10)])
}));
//Act
var data = await _reportContract.GetDataSaleByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(2));
_saleStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataSalesByPeriod_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_saleStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SaleDataModel>()));
//Act
var data = await _reportContract.GetDataSaleByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_saleStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public void GetDataSalesByPeriod_WhenIncorrectDates_ShouldFail_Test()
{
//Arrange
var date = DateTime.UtcNow;
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSaleByPeriodAsync(date, date, CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
Assert.That(async () => await _reportContract.GetDataSaleByPeriodAsync(date, DateTime.UtcNow.AddDays(-1), CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
}
[Test]
public void GetDataBySalesByPeriod_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_saleStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSaleByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None), Throws.TypeOf<StorageException>());
_saleStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataSalaryByPeriod_ShouldSuccess_Test()
{
//Arrange
var startDate = DateTime.UtcNow.AddDays(-20);
var endDate = DateTime.UtcNow.AddDays(5);
var worker1 = new WorkerDataModel(Guid.NewGuid().ToString(), "fio 1", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow.AddYears(-20), DateTime.UtcNow.AddDays(-3));
var worker2 = new WorkerDataModel(Guid.NewGuid().ToString(), "fio 2", Guid.NewGuid().ToString(), "+7(999)999-99-99", DateTime.UtcNow.AddYears(-20), DateTime.UtcNow.AddDays(-3));
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SalaryDataModel>()
{
new(worker1.Id, DateTime.UtcNow.AddDays(-10), 100),
new(worker1.Id, endDate, 1000),
new(worker1.Id, startDate, 1000),
new(worker2.Id, DateTime.UtcNow.AddDays(-10), 100),
new(worker2.Id, DateTime.UtcNow.AddDays(-5), 200)
}));
//Act
var data = await _reportContract.GetDataSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(2));
var totalSalary = data.First();
Assert.Multiple(() =>
{
Assert.That(totalSalary, Is.Not.Null);
Assert.That(totalSalary.TotalSalary, Is.EqualTo(2100));
});
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataSalaryByPeriod_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SalaryDataModel>()));
//Act
var data = await _reportContract.GetDataSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public void GetDataSalaryByPeriod_WhenIncorrectDates_ShouldFail_Test()
{
//Arrange
var date = DateTime.UtcNow;
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(date, date, CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(date, DateTime.UtcNow.AddDays(-1), CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
}
[Test]
public void GetDataSalaryByPeriod_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None), Throws.TypeOf<StorageException>());
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task CreateDocumentProductsByRestaurant_ShouldSuccess_Test()
{
//Arrange
var restaurant1 = new RestaurantDataModel(Guid.NewGuid().ToString(), "name1");
var restaurant2 = new RestaurantDataModel(Guid.NewGuid().ToString(), "name2");
_productStorageContract.Setup(x => x.GetListAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<ProductDataModel>()
{
new(Guid.NewGuid().ToString(), "name 1.1", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 2.1", ProductType.Pizza, restaurant2.Id, 10, false, restaurant2),
new(Guid.NewGuid().ToString(), "name 1.2", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 1.3", ProductType.Pizza, restaurant1.Id, 10, false, restaurant1),
new(Guid.NewGuid().ToString(), "name 2.2", ProductType.Pizza, restaurant2.Id, 10, false, restaurant2)
}));
_baseWordBuilder.Setup(x => x.AddHeader(It.IsAny<string>())).Returns(_baseWordBuilder.Object);
_baseWordBuilder.Setup(x => x.AddParagraph(It.IsAny<string>())).Returns(_baseWordBuilder.Object);
var countRows = 0;
string[] firstRow = [];
string[] secondRow = [];
string[] thirdRow = [];
_baseWordBuilder.Setup(x => x.AddTable(It.IsAny<int[]>(), It.IsAny<List<string[]>>()))
.Callback((int[] widths, List<string[]> data) =>
{
countRows = data.Count;
firstRow = data[0];
secondRow = data[1];
thirdRow = data[2];
})
.Returns(_baseWordBuilder.Object);
//Act
var data = await _reportContract.CreateDocumentProductsByRestaurantAsync(CancellationToken.None);
//Assert
_productStorageContract.Verify(x => x.GetListAsync(It.IsAny<CancellationToken>()), Times.Once);
_baseWordBuilder.Verify(x => x.AddHeader(It.IsAny<string>()), Times.Once);
_baseWordBuilder.Verify(x => x.AddParagraph(It.IsAny<string>()), Times.Once);
_baseWordBuilder.Verify(x => x.AddTable(It.IsAny<int[]>(), It.IsAny<List<string[]>>()), Times.Once);
_baseWordBuilder.Verify(x => x.Build(), Times.Once);
Assert.Multiple(() =>
{
Assert.That(countRows, Is.EqualTo(8));
Assert.That(firstRow, Has.Length.EqualTo(2));
Assert.That(secondRow, Has.Length.EqualTo(2));
Assert.That(thirdRow, Has.Length.EqualTo(2));
});
Assert.Multiple(() =>
{
Assert.That(firstRow[0], Is.EqualTo("Ресторан"));
Assert.That(firstRow[1], Is.EqualTo("Товар"));
Assert.That(secondRow[0], Is.EqualTo("name1"));
Assert.That(secondRow[1], Is.Empty);
Assert.That(thirdRow[0], Is.Empty);
Assert.That(thirdRow[1], Is.EqualTo("name 1.1"));
});
}
[Test]
public async Task CreateDocumentSalesByPeriod_ShouldeSuccess_Test()
{
var product1 = new ProductDataModel(Guid.NewGuid().ToString(), "name 1", ProductType.Pizza, Guid.NewGuid().ToString(), 10);
var product2 = new ProductDataModel(Guid.NewGuid().ToString(), "name 2", ProductType.Pizza, Guid.NewGuid().ToString(), 10);
_saleStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SaleDataModel>()
{
new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, [new SaleProductDataModel("", product1.Id, 10, 10, product1), new SaleProductDataModel("", product2.Id, 10, 10, product2)]),
new(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), null, [new SaleProductDataModel("", product2.Id, 10, 10, product2)])
}));
_baseExcelBuilder.Setup(x => x.AddHeader(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>())).Returns(_baseExcelBuilder.Object);
_baseExcelBuilder.Setup(x => x.AddParagraph(It.IsAny<string>(), It.IsAny<int>())).Returns(_baseExcelBuilder.Object);
var countRows = 0;
string[] firstRow = [];
string[] secondRow = [];
string[] thirdRow = [];
_baseExcelBuilder.Setup(x => x.AddTable(It.IsAny<int[]>(), It.IsAny<List<string[]>>()))
.Callback((int[] widths, List<string[]> data) =>
{
countRows = data.Count;
firstRow = data[0];
secondRow = data[1];
thirdRow = data[2];
})
.Returns(_baseExcelBuilder.Object);
//Act
var data = await _reportContract.CreateDocumentSalesByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.Multiple(() =>
{
Assert.That(countRows, Is.EqualTo(7));
Assert.That(firstRow, Is.Not.EqualTo(default(string[])));
Assert.That(secondRow, Is.Not.EqualTo(default(string[])));
});
Assert.Multiple(() =>
{
Assert.That(firstRow[0], Is.EqualTo("Дата"));
Assert.That(firstRow[1], Is.EqualTo("Сумма"));
Assert.That(firstRow[2], Is.EqualTo("Товар"));
Assert.That(firstRow[3], Is.EqualTo("Кол-во"));
});
Assert.Multiple(() =>
{
Assert.That(secondRow[0], Is.Not.Empty);
Assert.That(secondRow[1], Is.EqualTo(200.ToString("N2")));
Assert.That(secondRow[2], Is.Empty);
Assert.That(secondRow[3], Is.Empty);
});
Assert.Multiple(() =>
{
Assert.That(thirdRow[0], Is.Empty);
Assert.That(thirdRow[1], Is.Empty);
Assert.That(thirdRow[2], Is.EqualTo(product1.ProductName));
Assert.That(thirdRow[3], Is.EqualTo(10.ToString("N2")));
});
_saleStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
_baseExcelBuilder.Verify(x => x.AddHeader(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once);
_baseExcelBuilder.Verify(x => x.AddParagraph(It.IsAny<string>(), It.IsAny<int>()), Times.Once);
_baseExcelBuilder.Verify(x => x.AddTable(It.IsAny<int[]>(), It.IsAny<List<string[]>>()), Times.Once);
_baseExcelBuilder.Verify(x => x.Build(), Times.Once);
}
[Test]
public async Task CreateDocumentSalaryByPeriod_ShouldSuccess_Test()
{
//Arrange
var startDate = DateTime.UtcNow.AddDays(-20);
var endDate = DateTime.UtcNow.AddDays(5);
var worker1 = new WorkerDataModel(Guid.NewGuid().ToString(), "fio 1", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow.AddYears(-20), DateTime.UtcNow.AddDays(-3));
var worker2 = new WorkerDataModel(Guid.NewGuid().ToString(), "fio 2", Guid.NewGuid().ToString(), "+7(999)999-99-99", DateTime.UtcNow.AddYears(-20), DateTime.UtcNow.AddDays(-3));
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SalaryDataModel>()
{
new(worker1.Id, DateTime.UtcNow.AddDays(-10), 100, worker1),
new(worker1.Id, endDate, 1000, worker1),
new(worker1.Id, startDate, 1000, worker1),
new(worker2.Id, DateTime.UtcNow.AddDays(-10), 100, worker2),
new(worker2.Id, DateTime.UtcNow.AddDays(-5), 200, worker2)
}));
_basePdfBuilder.Setup(x => x.AddHeader(It.IsAny<string>())).Returns(_basePdfBuilder.Object);
_basePdfBuilder.Setup(x => x.AddParagraph(It.IsAny<string>())).Returns(_basePdfBuilder.Object);
var countRows = 0;
(string, double) firstRow = default;
(string, double) secondRow = default;
_basePdfBuilder.Setup(x => x.AddPieChart(It.IsAny<string>(), It.IsAny<List<(string, double)>>()))
.Callback((string header, List<(string, double)> data) =>
{
countRows = data.Count;
firstRow = data[0];
secondRow = data[1];
})
.Returns(_basePdfBuilder.Object);
//Act
var data = await _reportContract.CreateDocumentSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.Multiple(() =>
{
Assert.That(countRows, Is.EqualTo(2));
Assert.That(firstRow, Is.Not.EqualTo(default((string, double))));
Assert.That(secondRow, Is.Not.EqualTo(default((string, double))));
});
Assert.Multiple(() =>
{
Assert.That(firstRow.Item1, Is.EqualTo(worker1.FIO));
Assert.That(firstRow.Item2, Is.EqualTo(2100));
Assert.That(secondRow.Item1, Is.EqualTo(worker2.FIO));
Assert.That(secondRow.Item2, Is.EqualTo(300));
});
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
_basePdfBuilder.Verify(x => x.AddHeader(It.IsAny<string>()), Times.Once);
_basePdfBuilder.Verify(x => x.AddParagraph(It.IsAny<string>()), Times.Once);
_basePdfBuilder.Verify(x => x.AddPieChart(It.IsAny<string>(), It.IsAny<List<(string, double)>>()), Times.Once);
_basePdfBuilder.Verify(x => x.Build(), Times.Once);
}
}

View File

@@ -1,10 +1,13 @@
using SPiluSZharuBuisnessLogic.Implementations;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.StorageContracts;
using SPiluSZharuTests.Infrastructure;
using Microsoft.Extensions.Logging;
using Moq;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.BuisnessLogicContracts;
namespace SPiluSZharuTests.BuisnessLogicContractsTests;
@@ -16,6 +19,7 @@ internal class SalaryBuisnessLogicContractTests
private Mock<ISaleStorageContract> _saleStorageContract;
private Mock<IPostStorageContract> _postStorageContract;
private Mock<IWorkerStorageContract> _workerStorageContract;
private readonly ConfigurationSalaryTest _salaryConfigurationTest = new();
[OneTimeSetUp]
public void OneTimeSetUp()
@@ -25,7 +29,7 @@ internal class SalaryBuisnessLogicContractTests
_postStorageContract = new Mock<IPostStorageContract>();
_workerStorageContract = new Mock<IWorkerStorageContract>();
_salaryBuisnessLogicContract = new SalaryBuisnessLogicContract(_salaryStorageContract.Object,
_saleStorageContract.Object, _postStorageContract.Object, _workerStorageContract.Object, new Mock<ILogger>().Object);
_saleStorageContract.Object, _postStorageContract.Object, _workerStorageContract.Object, new Mock<ILogger>().Object, _salaryConfigurationTest);
}
[SetUp]
@@ -186,16 +190,14 @@ internal class SalaryBuisnessLogicContractTests
{
//Arrange
var workerId = Guid.NewGuid().ToString();
var saleSum = 1.2 * 5;
var postSalary = 2000.0;
var rate = 2000.0;
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns([new SaleDataModel(Guid.NewGuid().ToString(), workerId, null, false, [new SaleProductDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5, 1.2)])]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, postSalary));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = rate }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
var sum = 0.0;
var expectedSum = postSalary + saleSum * 0.1;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) =>
{
@@ -204,7 +206,7 @@ internal class SalaryBuisnessLogicContractTests
//Act
_salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
Assert.That(sum, Is.EqualTo(rate));
}
[Test]
@@ -226,7 +228,7 @@ internal class SalaryBuisnessLogicContractTests
new SaleDataModel(Guid.NewGuid().ToString(), worker3Id, null, false, []),
new SaleDataModel(Guid.NewGuid().ToString(), worker3Id, null, false, [])]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 100 }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns(list);
//Act
@@ -236,19 +238,18 @@ internal class SalaryBuisnessLogicContractTests
}
[Test]
public void CalculateSalaryByMounth_WithoitSalesByWorker_Test()
public void CalculateSalaryByMounth_WithoutSalesByWorker_Test()
{
//Arrange
var postSalary = 2000.0;
var rate = 2000.0;
var workerId = Guid.NewGuid().ToString();
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns([]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, postSalary));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = rate }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
var sum = 0.0;
var expectedSum = postSalary;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) =>
{
@@ -257,7 +258,7 @@ internal class SalaryBuisnessLogicContractTests
//Act
_salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
Assert.That(sum, Is.EqualTo(rate));
}
[Test]
@@ -266,7 +267,7 @@ internal class SalaryBuisnessLogicContractTests
//Arrange
var workerId = Guid.NewGuid().ToString();
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 100 }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
//Act&Assert
@@ -294,7 +295,7 @@ internal class SalaryBuisnessLogicContractTests
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns([new SaleDataModel(Guid.NewGuid().ToString(), workerId, null, false, [])]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 100 }));
//Act&Assert
Assert.That(() => _salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow), Throws.TypeOf<NullListException>());
}
@@ -307,7 +308,7 @@ internal class SalaryBuisnessLogicContractTests
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 100 }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
//Act&Assert
@@ -337,10 +338,72 @@ internal class SalaryBuisnessLogicContractTests
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns([new SaleDataModel(Guid.NewGuid().ToString(), workerId, null, false, [])]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.OrderPicker, new PostConfiguration() { Rate = 100 }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Throws(new StorageException(new InvalidOperationException()));
//Act&Assert
Assert.That(() => _salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow), Throws.TypeOf<StorageException>());
}
[Test]
public void CalculateSalaryByMounth_WithDeliveryManPostConfiguration_CalculateSalary_Test()
{
//Arrange
var workerId = Guid.NewGuid().ToString();
var rate = 2000.0;
var percent = 0.1;
var bonus = 0.5;
var sales = new List<SaleDataModel>()
{
new(Guid.NewGuid().ToString(), workerId, null, false, [new SaleProductDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5, 1.2)]),
new(Guid.NewGuid().ToString(), workerId, null, false, [new SaleProductDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5, 1.2)]),
new(Guid.NewGuid().ToString(), workerId, null, false, [new SaleProductDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5000, 12)])
};
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(sales);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.DeliveryMan, new DeliveryManPostConfiguration() { Rate = rate, SalePercent = percent, BonusForExtraSales = bonus }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
var sum = 0.0;
var expectedSum = rate + percent * (sales.Sum(x => x.Sum) / sales.Count) + sales.Where(x => x.Sum > _salaryConfigurationTest.ExtraSaleSum).Sum(x => x.Sum) * bonus;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) =>
{
sum = x.Salary;
});
//Act
_salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
}
[Test]
public void CalculateSalaryByMounth_WithOperatorPostConfiguration_CalculateSalary_Test()
{
//Arrange
var workerId = Guid.NewGuid().ToString();
var rate = 2000.0;
var trend = 3;
var bonus = 100;
_saleStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns([new SaleDataModel(Guid.NewGuid().ToString(), workerId, null, false, [new SaleProductDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 5, 1.2)])]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, new OperatorPostConfiguration() { Rate = rate, PersonalCountTrendPremium = bonus }));
_workerStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([new WorkerDataModel(workerId, "Test", Guid.NewGuid().ToString(), "+7(777)777-77-77", DateTime.UtcNow, DateTime.UtcNow, false)]);
_workerStorageContract.Setup(x => x.GetWorkerTrend(It.IsAny<DateTime>(), It.IsAny<DateTime>()))
.Returns(trend);
var sum = 0.0;
var expectedSum = rate + trend * bonus;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) =>
{
sum = x.Salary;
});
//Act
_salaryBuisnessLogicContract.CalculateSalaryByMounth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
}
}

View File

@@ -1,6 +1,7 @@
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
namespace SPiluSZharuTests.DataModelTests;
@@ -10,41 +11,48 @@ internal class PostDataModelTests
[Test]
public void IdIsNullOrEmptyTest()
{
var post = CreateDataModel(null, "name", PostType.Operator, 10);
var post = CreateDataModel(null, "name", PostType.Operator, new PostConfiguration() { Rate = 10 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
post = CreateDataModel(string.Empty, "name", PostType.Operator, 10);
post = CreateDataModel(string.Empty, "name", PostType.Operator, new PostConfiguration() { Rate = 10 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var post = CreateDataModel("id", "name", PostType.Operator, 10);
var post = CreateDataModel("id", "name", PostType.Operator, new PostConfiguration() { Rate = 10 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void PostNameIsEmptyTest()
{
var restaurant = CreateDataModel(Guid.NewGuid().ToString(), null, PostType.Operator, 10);
var restaurant = CreateDataModel(Guid.NewGuid().ToString(), null, PostType.Operator, new PostConfiguration() { Rate = 10 });
Assert.That(() => restaurant.Validate(), Throws.TypeOf<ValidationException>());
restaurant = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, PostType.Operator, 10);
restaurant = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, PostType.Operator, new PostConfiguration() { Rate = 10 });
Assert.That(() => restaurant.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void PostTypeIsNoneTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.None, 10);
var post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.None, new PostConfiguration() { Rate = 10 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void SalaryIsLessOrZeroTest()
public void ConfigurationModelIsNullTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, 0);
var post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, null);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, -10);
}
[Test]
public void RateIsLessOrZeroTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, new PostConfiguration() { Rate = 0 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
post = CreateDataModel(Guid.NewGuid().ToString(), "name", PostType.Operator, new PostConfiguration() { Rate = -10 });
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
}
@@ -54,17 +62,19 @@ internal class PostDataModelTests
var postId = Guid.NewGuid().ToString();
var postName = "name";
var postType = PostType.Operator;
var salary = 10;
var post = CreateDataModel(postId, postName, postType, salary);
var configuration = new PostConfiguration() { Rate = 10 };
var post = CreateDataModel(postId, postName, postType, configuration);
Assert.That(() => post.Validate(), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(post.Id, Is.EqualTo(postId));
Assert.That(post.PostName, Is.EqualTo(postName));
Assert.That(post.PostType, Is.EqualTo(postType));
Assert.That(post.Salary, Is.EqualTo(salary));
Assert.That(post.ConfigurationModel, Is.EqualTo(configuration));
Assert.That(post.ConfigurationModel.Rate, Is.EqualTo(configuration.Rate));
});
}
private static PostDataModel CreateDataModel(string? id, string? postName, PostType postType, double salary) => new(id, postName, postType, salary);
private static PostDataModel CreateDataModel(string? id, string? postName, PostType postType, PostConfiguration configuration) =>
new(id, postName, postType, configuration);
}

View File

@@ -10,41 +10,57 @@ internal class ProductDataModelTests
[Test]
public void IdIsNullOrEmptyTest()
{
var product = CreateDataModel(null, "name", ProductType.Pizza, 500, false);
var product = CreateDataModel(null, "name", ProductType.Pizza, Guid.NewGuid().ToString(), 500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
product = CreateDataModel(string.Empty, "name", ProductType.Pizza, 500, false);
product = CreateDataModel(string.Empty, "name", ProductType.Pizza, Guid.NewGuid().ToString(), 500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var product = CreateDataModel("id", "name", ProductType.Pizza, 500, false);
var product = CreateDataModel("id", "name", ProductType.Pizza, Guid.NewGuid().ToString(), 500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void ProductNameIsNullOrEmptyTest()
{
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.Pizza, 500, false);
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.Pizza, Guid.NewGuid().ToString(), 500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
product = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, ProductType.Pizza, 500, false);
product = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, ProductType.Pizza, Guid.NewGuid().ToString(), 500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void ProductTypeIsNoneTest()
{
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.None, 0, false);
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.None, Guid.NewGuid().ToString(), 0, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void RestaurantIdIsNullOrEmptyTest()
{
var product = CreateDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, null, 10, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
product = CreateDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, string.Empty, 10, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void RestaurantIdIsNotGuidTest()
{
var product = CreateDataModel(Guid.NewGuid().ToString(), "name", ProductType.Pizza, "restaurantId", 10, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void PriceIsLessOrZeroTest()
{
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.Pizza, 0, false);
var product = CreateDataModel(Guid.NewGuid().ToString(), null, ProductType.Pizza, Guid.NewGuid().ToString(), 0, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
product = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, ProductType.Pizza, -500, false);
product = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, ProductType.Pizza, Guid.NewGuid().ToString(), -500, false);
Assert.That(() => product.Validate(), Throws.TypeOf<ValidationException>());
}
@@ -54,20 +70,22 @@ internal class ProductDataModelTests
var productId = Guid.NewGuid().ToString();
var productName = "name";
var productType = ProductType.Pizza;
var productRestaurantId = Guid.NewGuid().ToString();
var price = 500;
var productIsDeleted = false;
var product = CreateDataModel(productId, productName, productType, price, productIsDeleted);
var product = CreateDataModel(productId, productName, productType, productRestaurantId, price, productIsDeleted);
Assert.That(() => product.Validate(), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(product.Id, Is.EqualTo(productId));
Assert.That(product.ProductName, Is.EqualTo(productName));
Assert.That(product.ProductType, Is.EqualTo(productType));
Assert.That(product.RestaurantId, Is.EqualTo(productRestaurantId));
Assert.That(product.Price, Is.EqualTo(price));
Assert.That(product.IsDeleted, Is.EqualTo(productIsDeleted));
});
}
private static ProductDataModel CreateDataModel(string? id, string? productName, ProductType productType, double price, bool isDeleted) =>
new(id, productName, productType, price, isDeleted);
private static ProductDataModel CreateDataModel(string? id, string? productName, ProductType productType, string? restaurantId, double price, bool isDeleted) =>
new(id, productName, productType, restaurantId, price, isDeleted);
}

View File

@@ -0,0 +1,10 @@
using SPiluSZharuContracts.Infrastructure;
namespace SPiluSZharuTests.Infrastructure;
class ConfigurationSalaryTest : IConfigurationSalary
{
public double ExtraSaleSum => 10;
public int MaxConcurrentThreads => 4;
}

View File

@@ -2,6 +2,7 @@
using SPiluSZharuDatabase;
using SPiluSZharuDatabase.Models;
using Microsoft.EntityFrameworkCore;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
namespace SPiluSZharuTests.Infrastructure;
@@ -15,17 +16,18 @@ internal static class SPiluSZharuDbContextExtensions
return restaurant;
}
public static Post InsertPostToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string? id = null, string postName = "test", PostType postType = PostType.Operator, double salary = 10, bool isActual = true, DateTime? changeDate = null)
public static Post InsertPostToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string? id = null, string postName = "test", PostType postType = PostType.Operator, PostConfiguration? config = null, bool isActual = true, DateTime? changeDate = null)
{
var post = new Post() { Id = Guid.NewGuid().ToString(), PostId = id ?? Guid.NewGuid().ToString(), PostName = postName, PostType = postType, Salary = salary, IsActual = isActual, ChangeDate = changeDate ?? DateTime.UtcNow };
var post = new Post() { Id = Guid.NewGuid().ToString(), PostId = id ?? Guid.NewGuid().ToString(), PostName = postName, PostType = postType, Configuration = config ?? new PostConfiguration() { Rate = 100 }, IsActual = isActual, ChangeDate = changeDate ?? DateTime.UtcNow };
dbContext.Posts.Add(post);
dbContext.SaveChanges();
return post;
}
public static Product InsertProductToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string? id = null, string productName = "test", ProductType productType = ProductType.Pizza, double price = 1, bool isDeleted = false)
public static Product InsertProductToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string restaurantId, string? id = null, string productName = "test", ProductType productType = ProductType.Pizza, double price = 1, bool isDeleted = false)
{
var product = new Product() { Id = id ?? Guid.NewGuid().ToString(), ProductName = productName, ProductType = productType, Price = price, IsDeleted = isDeleted };
var product = new Product() { Id = id ?? Guid.NewGuid().ToString(), RestaurantId = restaurantId, ProductName = productName, ProductType = productType, Price = price, IsDeleted = isDeleted, Restaurant = dbContext.Restaurants.Find(restaurantId)
};
dbContext.Products.Add(product);
dbContext.SaveChanges();
return product;
@@ -62,9 +64,9 @@ internal static class SPiluSZharuDbContextExtensions
return sale;
}
public static Worker InsertWorkerToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string? id = null, string fio = "test", string? postId = null, string phoneNumber = "+7(777)777-77-77", DateTime? birthDate = null, DateTime? employmentDate = null, bool isDeleted = false)
public static Worker InsertWorkerToDatabaseAndReturn(this SPiluSZharuDbContext dbContext, string? id = null, string fio = "test", string? postId = null, string phoneNumber = "+7(777)777-77-77", DateTime? birthDate = null, DateTime? employmentDate = null, bool isDeleted = false, DateTime? dateDelete = null)
{
var worker = new Worker() { Id = id ?? Guid.NewGuid().ToString(), FIO = fio, PostId = postId ?? Guid.NewGuid().ToString(), PhoneNumber = phoneNumber, BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-20), EmploymentDate = employmentDate ?? DateTime.UtcNow, IsDeleted = isDeleted };
var worker = new Worker() { Id = id ?? Guid.NewGuid().ToString(), FIO = fio, PostId = postId ?? Guid.NewGuid().ToString(), PhoneNumber = phoneNumber, BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-20), EmploymentDate = employmentDate ?? DateTime.UtcNow, IsDeleted = isDeleted, DateOfDelete = dateDelete };
dbContext.Workers.Add(worker);
dbContext.SaveChanges();
return worker;

View File

@@ -1,17 +1,52 @@
using SPiluSZharuDatabase;
using SPiluSZharuTests.Infrastructure;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using System.Text;
using System.Text.Json;
namespace SPiluSZharuTests.StoragesContracts;
internal abstract class BaseStorageContractTest
internal class BaseStorageContractTest
{
private WebApplicationFactory<Program> _webApplication;
protected HttpClient HttpClient { get; private set; }
protected SPiluSZharuDbContext SPiluSZharuDbContext { get; private set; }
protected static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
[OneTimeSetUp]
public void OneTimeSetUp()
{
SPiluSZharuDbContext = new SPiluSZharuDbContext(new ConfigurationDatabaseTest());
_webApplication = new CustomWebApplicationFactory<Program>();
HttpClient = _webApplication
.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
using var loggerFactory = new LoggerFactory();
loggerFactory.AddSerilog(new LoggerConfiguration()
.ReadFrom.Configuration(new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build())
.CreateLogger());
services.AddSingleton(loggerFactory);
});
})
.CreateClient();
var request = HttpClient.GetAsync("/login/user").GetAwaiter().GetResult();
var data = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();
HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {data}");
SPiluSZharuDbContext = _webApplication.Services.GetRequiredService<SPiluSZharuDbContext>();
SPiluSZharuDbContext.Database.EnsureDeleted();
SPiluSZharuDbContext.Database.EnsureCreated();
}
@@ -19,7 +54,15 @@ internal abstract class BaseStorageContractTest
[OneTimeTearDown]
public void OneTimeTearDown()
{
SPiluSZharuDbContext.Database.EnsureDeleted();
SPiluSZharuDbContext.Dispose();
SPiluSZharuDbContext?.Database.EnsureDeleted();
SPiluSZharuDbContext?.Dispose();
HttpClient?.Dispose();
_webApplication?.Dispose();
}
protected static async Task<T?> GetModelFromResponseAsync<T>(HttpResponseMessage response) =>
JsonSerializer.Deserialize<T>(await response.Content.ReadAsStringAsync(), JsonSerializerOptions);
protected static StringContent MakeContent(object model) =>
new(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json");
}

View File

@@ -2,6 +2,7 @@
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
using SPiluSZharuDatabase.Implementations;
using SPiluSZharuDatabase.Models;
using SPiluSZharuTests.Infrastructure;
@@ -45,6 +46,19 @@ internal class PostStorageContractTests : BaseStorageContractTest
Assert.That(list, Is.Empty);
}
[Test]
public void Try_GetList_WhenDifferentConfigTypes_Test()
{
var postSimple = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(postName: "name 1");
var postCashier = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(postName: "name 2", config: new DeliveryManPostConfiguration() { SalePercent = 500 });
var postSupervisor = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(postName: "name 3", config: new OperatorPostConfiguration() { PersonalCountTrendPremium = 20 });
var list = _postStorageContract.GetList();
Assert.That(list, Is.Not.Null);
AssertElement(list.First(x => x.Id == postSimple.PostId), postSimple);
AssertElement(list.First(x => x.Id == postCashier.PostId), postCashier);
AssertElement(list.First(x => x.Id == postSupervisor.PostId), postSupervisor);
}
[Test]
public void Try_GetPostWithHistory_WhenHaveRecords_Test()
{
@@ -142,6 +156,37 @@ internal class PostStorageContractTests : BaseStorageContractTest
Assert.That(() => _postStorageContract.AddElement(post), Throws.TypeOf<ElementExistsException>());
}
[Test]
public void Try_AddElement_WithDeliveryManPostConfiguration_Test()
{
var salePercent = 10;
var post = CreateModel(Guid.NewGuid().ToString(), config: new DeliveryManPostConfiguration() { SalePercent = salePercent });
_postStorageContract.AddElement(post);
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(post.Id);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(DeliveryManPostConfiguration).Name));
Assert.That((element.Configuration as DeliveryManPostConfiguration)!.SalePercent, Is.EqualTo(salePercent));
});
}
[Test]
public void Try_AddElement_WithOperatorPostConfiguration_Test()
{
var personalCountTrendPremium = 50;
var post = CreateModel(Guid.NewGuid().ToString(), config: new OperatorPostConfiguration() { PersonalCountTrendPremium = personalCountTrendPremium });
_postStorageContract.AddElement(post);
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(post.Id);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(OperatorPostConfiguration).Name));
Assert.That((element.Configuration as OperatorPostConfiguration)!.PersonalCountTrendPremium, Is.EqualTo(personalCountTrendPremium));
});
}
[Test]
public void Try_UpdElement_Test()
{
@@ -178,6 +223,35 @@ internal class PostStorageContractTests : BaseStorageContractTest
Assert.That(() => _postStorageContract.UpdElement(post), Throws.TypeOf<ElementDeletedException>());
}
[Test]
public void Try_UpdElement_WithDeliveryManPostConfiguration_Test()
{
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var salePercent = 10;
_postStorageContract.UpdElement(CreateModel(post.PostId, config: new DeliveryManPostConfiguration() { SalePercent = salePercent }));
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(post.PostId);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(DeliveryManPostConfiguration).Name));
Assert.That((element.Configuration as DeliveryManPostConfiguration)!.SalePercent, Is.EqualTo(salePercent));
});
}
[Test]
public void Try_UpdElement_WithOperatorPostConfiguration_Test()
{
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var personalCountTrendPremium = 50;
_postStorageContract.UpdElement(CreateModel(post.PostId, config: new OperatorPostConfiguration() { PersonalCountTrendPremium = personalCountTrendPremium }));
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(post.PostId);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(OperatorPostConfiguration).Name));
Assert.That((element.Configuration as OperatorPostConfiguration)!.PersonalCountTrendPremium, Is.EqualTo(personalCountTrendPremium));
});
}
[Test]
public void Try_DelElement_Test()
{
@@ -233,12 +307,12 @@ internal class PostStorageContractTests : BaseStorageContractTest
Assert.That(actual.Id, Is.EqualTo(expected.PostId));
Assert.That(actual.PostName, Is.EqualTo(expected.PostName));
Assert.That(actual.PostType, Is.EqualTo(expected.PostType));
Assert.That(actual.Salary, Is.EqualTo(expected.Salary));
Assert.That(actual.ConfigurationModel.Rate, Is.EqualTo(expected.Configuration.Rate));
});
}
private static PostDataModel CreateModel(string postId, string postName = "test", PostType postType = PostType.Operator, double salary = 10)
=> new(postId, postName, postType, salary);
private static PostDataModel CreateModel(string postId, string postName = "test", PostType postType = PostType.Operator, PostConfiguration? config = null)
=> new(postId, postName, postType, config ?? new PostConfiguration() { Rate = 100 });
private static void AssertElement(Post? actual, PostDataModel expected)
{
@@ -248,7 +322,7 @@ internal class PostStorageContractTests : BaseStorageContractTest
Assert.That(actual.PostId, Is.EqualTo(expected.Id));
Assert.That(actual.PostName, Is.EqualTo(expected.PostName));
Assert.That(actual.PostType, Is.EqualTo(expected.PostType));
Assert.That(actual.Salary, Is.EqualTo(expected.Salary));
Assert.That(actual.Configuration.Rate, Is.EqualTo(expected.ConfigurationModel.Rate));
});
}
}

View File

@@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuDatabase.Implementations;
@@ -12,25 +11,28 @@ namespace SPiluSZharuTests.StoragesContracts;
internal class ProductStorageContractTests : BaseStorageContractTest
{
private ProductStorageContract _productStorageContract;
private Restaurant _restaurant;
[SetUp]
public void SetUp()
{
_productStorageContract = new ProductStorageContract(SPiluSZharuDbContext);
_restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn();
}
[TearDown]
public void TearDown()
{
SPiluSZharuDbContext.RemoveProductsFromDatabase();
SPiluSZharuDbContext.RemoveRestaurantsFromDatabase();
}
[Test]
public void Try_GetList_WhenHaveRecords_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 3");
var list = _productStorageContract.GetList();
Assert.That(list, Is.Not.Null);
Assert.That(list, Has.Count.EqualTo(3));
@@ -45,12 +47,32 @@ internal class ProductStorageContractTests : BaseStorageContractTest
Assert.That(list, Is.Empty);
}
[Test]
public async Task Try_GetListAsync_WhenHaveRecords_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 3");
var list = await _productStorageContract.GetListAsync(CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.That(list, Has.Count.EqualTo(3));
AssertElement(list.First(x => x.Id == product.Id), product);
}
[Test]
public async Task Try_GetListAsync_WhenNoRecords_Test()
{
var list = await _productStorageContract.GetListAsync(CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.That(list, Is.Empty);
}
[Test]
public void Try_GetList_OnlyActual_Test()
{
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 3", isDeleted: false);
var list = _productStorageContract.GetList(onlyActive: true);
Assert.That(list, Is.Not.Null);
Assert.Multiple(() =>
@@ -63,9 +85,9 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_GetList_IncludeNoActual_Test()
{
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 3", isDeleted: false);
var list = _productStorageContract.GetList(onlyActive: false);
Assert.That(list, Is.Not.Null);
Assert.Multiple(() =>
@@ -76,10 +98,42 @@ internal class ProductStorageContractTests : BaseStorageContractTest
});
}
[Test]
public void Try_GetList_ByRestaurant_Test()
{
var restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant.Id, productName: "name 3", isDeleted: false);
var list = _productStorageContract.GetList(restaurantId: _restaurant.Id, onlyActive: false);
Assert.That(list, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(list, Has.Count.EqualTo(2));
Assert.That(list.All(x => x.RestaurantId == _restaurant.Id));
});
}
[Test]
public void Try_GetList_ByRestaurantOnlyActual_Test()
{
var restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant.Id, productName: "name 3", isDeleted: false);
var list = _productStorageContract.GetList(restaurantId: _restaurant.Id, onlyActive: true);
Assert.That(list, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(list, Has.Count.EqualTo(1));
Assert.That(list.All(x => x.RestaurantId == _restaurant.Id && !x.IsDeleted));
});
}
[Test]
public void Try_GetHistoryByProductId_WhenHaveRecords_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1));
@@ -91,7 +145,7 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_GetHistoryByProductId_WhenNoRecords_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1));
@@ -103,49 +157,49 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_GetElementById_WhenHaveRecord_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
AssertElement(_productStorageContract.GetElementById(product.Id), product);
}
[Test]
public void Try_GetElementById_WhenNoRecord_Test()
{
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
Assert.That(() => _productStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null);
}
[Test]
public void Try_GetElementById_WhenRecordHasDeleted_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, isDeleted: true);
Assert.That(() => _productStorageContract.GetElementById(product.Id), Is.Null);
}
[Test]
public void Try_GetElementByName_WhenHaveRecord_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
AssertElement(_productStorageContract.GetElementByName(product.ProductName), product);
}
[Test]
public void Try_GetElementByName_WhenNoRecord_Test()
{
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
Assert.That(() => _productStorageContract.GetElementByName("name"), Is.Null);
}
[Test]
public void Try_GetElementByName_WhenRecordHasDeleted_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, isDeleted: true);
Assert.That(() => _productStorageContract.GetElementById(product.ProductName), Is.Null);
}
[Test]
public void Try_AddElement_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: false);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, isDeleted: false);
_productStorageContract.AddElement(product);
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), product);
}
@@ -153,40 +207,40 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_AddElement_WhenIsDeletedIsTrue_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: true);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, isDeleted: true);
Assert.That(() => _productStorageContract.AddElement(product), Throws.Nothing);
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), CreateModel(product.Id, isDeleted: false));
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), CreateModel(product.Id, _restaurant.Id, isDeleted: false));
}
[Test]
public void Try_AddElement_WhenHaveRecordWithSameId_Test()
{
var product = CreateModel(Guid.NewGuid().ToString());
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, productName: "name unique");
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, productName: "name unique");
Assert.That(() => _productStorageContract.AddElement(product), Throws.TypeOf<ElementExistsException>());
}
[Test]
public void Try_AddElement_WhenHaveRecordWithSameName_Test()
{
var product = CreateModel("name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: product.ProductName, isDeleted: false);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: product.ProductName, isDeleted: false);
Assert.That(() => _productStorageContract.AddElement(product), Throws.TypeOf<ElementExistsException>());
}
[Test]
public void Try_AddElement_WhenHaveRecordWithSameNameButOneWasDeleted_Test()
{
var product = CreateModel("name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: product.ProductName, isDeleted: true);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: product.ProductName, isDeleted: true);
Assert.That(() => _productStorageContract.AddElement(product), Throws.Nothing);
}
[Test]
public void Try_UpdElement_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, isDeleted: false);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, isDeleted: false);
_productStorageContract.UpdElement(product);
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), product);
}
@@ -194,48 +248,48 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_UpdElement_WhenIsDeletedIsTrue_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, isDeleted: false);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, isDeleted: false);
_productStorageContract.UpdElement(product);
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), CreateModel(product.Id, isDeleted: false));
AssertElement(SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id), CreateModel(product.Id, _restaurant.Id, isDeleted: false));
}
[Test]
public void Try_UpdElement_WhenNoRecordWithThisId_Test()
{
Assert.That(() => _productStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _productStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString(), _restaurant.Id)), Throws.TypeOf<ElementNotFoundException>());
}
[Test]
public void Try_UpdElement_WhenHaveRecordWithSameName_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, productName: "name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: product.ProductName);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, productName: "name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: product.ProductName);
Assert.That(() => _productStorageContract.UpdElement(product), Throws.TypeOf<ElementExistsException>());
}
[Test]
public void Try_UpdElement_WhenHaveRecordWithSameNameButOneWasDeleted_Test()
{
var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, productName: "name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), productName: product.ProductName, isDeleted: true);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id, "name unique", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, productName: "name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: product.ProductName, isDeleted: true);
Assert.That(() => _productStorageContract.UpdElement(product), Throws.Nothing);
}
[Test]
public void Try_UpdElement_WhenRecordWasDeleted_Test()
{
var product = CreateModel(Guid.NewGuid().ToString());
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(product.Id, isDeleted: true);
var product = CreateModel(Guid.NewGuid().ToString(), _restaurant.Id);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, product.Id, isDeleted: true);
Assert.That(() => _productStorageContract.UpdElement(product), Throws.TypeOf<ElementNotFoundException>());
}
[Test]
public void Try_DelElement_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: false);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, isDeleted: false);
_productStorageContract.DelElement(product.Id);
var element = SPiluSZharuDbContext.GetProductFromDatabaseById(product.Id);
Assert.Multiple(() =>
@@ -254,7 +308,7 @@ internal class ProductStorageContractTests : BaseStorageContractTest
[Test]
public void Try_DelElement_WhenRecordWasDeleted_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, isDeleted: true);
Assert.That(() => _productStorageContract.DelElement(product.Id), Throws.TypeOf<ElementNotFoundException>());
}
@@ -264,6 +318,7 @@ internal class ProductStorageContractTests : BaseStorageContractTest
Assert.Multiple(() =>
{
Assert.That(actual.Id, Is.EqualTo(expected.Id));
Assert.That(actual.RestaurantId, Is.EqualTo(expected.RestaurantId));
Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName));
Assert.That(actual.ProductType, Is.EqualTo(expected.ProductType));
Assert.That(actual.Price, Is.EqualTo(expected.Price));
@@ -271,8 +326,8 @@ internal class ProductStorageContractTests : BaseStorageContractTest
});
}
private static ProductDataModel CreateModel(string id, string productName = "test", ProductType productType = ProductType.Burgers, double price = 1, bool isDeleted = false)
=> new(id, productName, productType, price, isDeleted);
private static ProductDataModel CreateModel(string id, string restaurantId, string productName = "test", ProductType productType = ProductType.Burgers, double price = 1, bool isDeleted = false)
=> new(id, productName, productType, restaurantId, price, isDeleted);
private static void AssertElement(Product? actual, ProductDataModel expected)
{
@@ -280,6 +335,7 @@ internal class ProductStorageContractTests : BaseStorageContractTest
Assert.Multiple(() =>
{
Assert.That(actual.Id, Is.EqualTo(expected.Id));
Assert.That(actual.RestaurantId, Is.EqualTo(expected.RestaurantId));
Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName));
Assert.That(actual.ProductType, Is.EqualTo(expected.ProductType));
Assert.That(actual.Price, Is.EqualTo(expected.Price));

View File

@@ -98,6 +98,30 @@ internal class SalaryStorageContractTests : BaseStorageContractTest
});
}
[Test]
public async Task Try_GetListAsync_ByPeriod_Test()
{
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2));
var list = await _salaryStorageContract.GetListAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1), CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(list, Has.Count.EqualTo(2));
});
}
[Test]
public async Task Try_GetListAsync_WhenNoRecords_Test()
{
var list = await _salaryStorageContract.GetListAsync(DateTime.UtcNow.AddDays(-10), DateTime.UtcNow.AddDays(10), CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.That(list, Is.Empty);
}
[Test]
public void Try_AddElement_Test()
{

View File

@@ -2,6 +2,7 @@
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.StorageContracts;
using SPiluSZharuDatabase.Implementations;
using SPiluSZharuDatabase.Models;
using SPiluSZharuTests.Infrastructure;
@@ -22,7 +23,7 @@ internal class SaleStorageContractTests : BaseStorageContractTest
_saleStorageContract = new SaleStorageContract(SPiluSZharuDbContext);
_restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn();
_worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn();
_product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
_product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id);
}
[TearDown]
@@ -96,7 +97,7 @@ internal class SaleStorageContractTests : BaseStorageContractTest
[Test]
public void Try_GetList_ByProductId_Test()
{
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "Other name");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "Other name");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, _restaurant.Id, products: [(_product.Id, 5, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, _restaurant.Id, products: [(_product.Id, 1, 1.2), (product.Id, 4, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(product.Id, 1, 1.2)]);
@@ -112,7 +113,7 @@ internal class SaleStorageContractTests : BaseStorageContractTest
{
var worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "Other worker", phoneNumber: "+7(555)555-55-55");
var restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "Other restaurant");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "Other name");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurant.Id, productName: "Other name");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, _restaurant.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, _restaurant.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]);
@@ -125,6 +126,27 @@ internal class SaleStorageContractTests : BaseStorageContractTest
Assert.That(list, Has.Count.EqualTo(1));
}
[Test]
public async Task Try_GetListAsync_ByPeriod_Test()
{
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, _restaurant.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, _restaurant.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]);
var list = await _saleStorageContract.GetListAsync(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.That(list, Has.Count.EqualTo(2));
}
[Test]
public async Task Try_GetListAsync_WhenNoRecords_Test()
{
var list = await _saleStorageContract.GetListAsync(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), CancellationToken.None);
Assert.That(list, Is.Not.Null);
Assert.That(list, Is.Empty);
}
[Test]
public void Try_GetElementById_WhenHaveRecord_Test()
{

View File

@@ -197,6 +197,43 @@ internal class WorkerStorageContractTests : BaseStorageContractTest
Assert.That(() => _workerStorageContract.DelElement(worker.Id), Throws.TypeOf<ElementNotFoundException>());
}
[Test]
public void Try_GetWorkerTrend_WhenNoNewAndDeletedWorkers_Test()
{
var startDate = DateTime.UtcNow.AddDays(-5);
var endDate = DateTime.UtcNow.AddDays(-3);
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(employmentDate: DateTime.UtcNow.AddDays(-10));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(555)555-55-55", employmentDate: DateTime.UtcNow.AddDays(-10), isDeleted: true, dateDelete: DateTime.UtcNow.AddDays(-9));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(333)333-33-33", employmentDate: DateTime.UtcNow.AddDays(-10), isDeleted: true, dateDelete: DateTime.UtcNow.AddDays(-1));
var count = _workerStorageContract.GetWorkerTrend(startDate, endDate);
Assert.That(count, Is.EqualTo(0));
}
[Test]
public void Try_GetWorkerTrend_WhenHaveNewAndNoDeletedWorkers_Test()
{
var startDate = DateTime.UtcNow.AddDays(-5);
var endDate = DateTime.UtcNow.AddDays(-3);
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(employmentDate: DateTime.UtcNow.AddDays(-10));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(555)555-55-55", employmentDate: DateTime.UtcNow.AddDays(-4));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(333)333-33-33", employmentDate: DateTime.UtcNow.AddDays(-1));
var count = _workerStorageContract.GetWorkerTrend(startDate, endDate);
Assert.That(count, Is.EqualTo(1));
}
[Test]
public void Try_GetWorkerTrend_WhenNoNewAndHaveDeletedWorkers_Test()
{
var startDate = DateTime.UtcNow.AddDays(-5);
var endDate = DateTime.UtcNow.AddDays(-3);
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(employmentDate: DateTime.UtcNow.AddDays(-10), isDeleted: true, dateDelete: DateTime.UtcNow.AddDays(-9));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(555)555-55-55", employmentDate: DateTime.UtcNow.AddDays(-10), isDeleted: true, dateDelete: DateTime.UtcNow.AddDays(-4));
SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(phoneNumber: "+7(333)333-33-33", employmentDate: DateTime.UtcNow.AddDays(-10), isDeleted: true, dateDelete: DateTime.UtcNow.AddDays(-1));
var count = _workerStorageContract.GetWorkerTrend(startDate, endDate);
Assert.That(count, Is.EqualTo(-1));
}
private static void AssertElement(WorkerDataModel? actual, Worker expected)
{
Assert.That(actual, Is.Not.Null);
@@ -227,6 +264,7 @@ internal class WorkerStorageContractTests : BaseStorageContractTest
Assert.That(actual.BirthDate, Is.EqualTo(expected.BirthDate));
Assert.That(actual.EmploymentDate, Is.EqualTo(expected.EmploymentDate));
Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted));
Assert.That(actual.DateOfDelete.HasValue, Is.EqualTo(expected.IsDeleted));
});
}
}

View File

@@ -1,9 +1,12 @@
using SPiluSZharuContracts.BindingModels;
using SPiluSZharuContracts.Enums;
using SPiluSZharuContracts.Infrastructure.PostConfiguration;
using SPiluSZharuContracts.ViewModels;
using SPiluSZharuDatabase.Models;
using SPiluSZharuTests.Infrastructure;
using System.Net;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace SPiluSZharuTests.WebApiControllersTests;
@@ -210,10 +213,10 @@ internal class PostControllerTests : BaseWebApiControllerTest
public async Task Post_WhenDataIsIncorrect_ShouldBadRequest_Test()
{
//Arrange
var postModelWithIdIncorrect = new PostBindingModel { Id = "Id", PostName = "name", PostType = PostType.DeliveryMan.ToString(), Salary = 10 };
var postModelWithNameIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), Salary = 10 };
var postModelWithPostTypeIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = string.Empty, Salary = 10 };
var postModelWithSalaryIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), Salary = -10 };
var postModelWithIdIncorrect = new PostBindingModel { Id = "Id", PostName = "name", PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithNameIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithPostTypeIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = string.Empty, ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithSalaryIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = null };
//Act
var responseWithIdIncorrect = await HttpClient.PostAsync($"/api/posts", MakeContent(postModelWithIdIncorrect));
var responseWithNameIncorrect = await HttpClient.PostAsync($"/api/posts", MakeContent(postModelWithNameIncorrect));
@@ -247,6 +250,44 @@ internal class PostControllerTests : BaseWebApiControllerTest
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task Post_WithDeliveryManPostConfiguration_ShouldSuccess_Test()
{
//Arrange
var salePercent = 10;
var postModel = CreateModel(configuration: JsonSerializer.Serialize(new DeliveryManPostConfiguration() { SalePercent = salePercent, Rate = 10 }));
//Act
var response = await HttpClient.PostAsync($"/api/posts", MakeContent(postModel));
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(postModel.Id!);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(DeliveryManPostConfiguration).Name));
Assert.That((element.Configuration as DeliveryManPostConfiguration)!.SalePercent, Is.EqualTo(salePercent));
});
}
[Test]
public async Task Post_WithOperatorPostConfiguration_ShouldSuccess_Test()
{
//Arrange
var personalCountTrendPremium = 50;
var postModel = CreateModel(configuration: JsonSerializer.Serialize(new OperatorPostConfiguration() { PersonalCountTrendPremium = personalCountTrendPremium, Rate = 10 }));
//Act
var response = await HttpClient.PostAsync($"/api/posts", MakeContent(postModel));
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(postModel.Id!);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(OperatorPostConfiguration).Name));
Assert.That((element.Configuration as OperatorPostConfiguration)!.PersonalCountTrendPremium, Is.EqualTo(personalCountTrendPremium));
});
}
[Test]
public async Task Put_ShouldSuccess_Test()
{
@@ -302,10 +343,10 @@ internal class PostControllerTests : BaseWebApiControllerTest
public async Task Put_WhenDataIsIncorrect_ShouldBadRequest_Test()
{
//Arrange
var postModelWithIdIncorrect = new PostBindingModel { Id = "Id", PostName = "name", PostType = PostType.DeliveryMan.ToString(), Salary = 10 };
var postModelWithNameIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), Salary = 10 };
var postModelWithPostTypeIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = string.Empty, Salary = 10 };
var postModelWithSalaryIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), Salary = -10 };
var postModelWithIdIncorrect = new PostBindingModel { Id = "Id", PostName = "name", PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithNameIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithPostTypeIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = string.Empty, ConfigurationJson = JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) };
var postModelWithSalaryIncorrect = new PostBindingModel { Id = Guid.NewGuid().ToString(), PostName = string.Empty, PostType = PostType.DeliveryMan.ToString(), ConfigurationJson = null };
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/posts", MakeContent(postModelWithIdIncorrect));
var responseWithNameIncorrect = await HttpClient.PutAsync($"/api/posts", MakeContent(postModelWithNameIncorrect));
@@ -339,6 +380,47 @@ internal class PostControllerTests : BaseWebApiControllerTest
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task Put_WithDeliveryManPostConfiguration_ShouldSuccess_Test()
{
//Arrange
var salePercent = 10;
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var postModel = CreateModel(post.PostId, configuration: JsonSerializer.Serialize(new DeliveryManPostConfiguration() { SalePercent = salePercent, Rate = 10 }));
//Act
var response = await HttpClient.PutAsync($"/api/posts", MakeContent(postModel));
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
SPiluSZharuDbContext.ChangeTracker.Clear();
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(postModel.Id!);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(DeliveryManPostConfiguration).Name));
Assert.That((element.Configuration as DeliveryManPostConfiguration)!.SalePercent, Is.EqualTo(salePercent));
});
}
[Test]
public async Task Put_WithOperatorPostConfiguration_ShouldSuccess_Test()
{
//Arrange
var personalCountTrendPremium = 50;
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var postModel = CreateModel(post.PostId, configuration: JsonSerializer.Serialize(new OperatorPostConfiguration() { PersonalCountTrendPremium = personalCountTrendPremium, Rate = 10 }));
//Act
var response = await HttpClient.PutAsync($"/api/posts", MakeContent(postModel));
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
SPiluSZharuDbContext.ChangeTracker.Clear();
var element = SPiluSZharuDbContext.GetPostFromDatabaseByPostId(postModel.Id!);
Assert.That(element, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(element.Configuration.Type, Is.EqualTo(typeof(OperatorPostConfiguration).Name));
Assert.That((element.Configuration as OperatorPostConfiguration)!.PersonalCountTrendPremium, Is.EqualTo(personalCountTrendPremium));
});
}
[Test]
public async Task Delete_ShouldSuccess_Test()
{
@@ -443,17 +525,17 @@ internal class PostControllerTests : BaseWebApiControllerTest
Assert.That(actual.Id, Is.EqualTo(expected.PostId));
Assert.That(actual.PostName, Is.EqualTo(expected.PostName));
Assert.That(actual.PostType, Is.EqualTo(expected.PostType.ToString()));
Assert.That(actual.Salary, Is.EqualTo(expected.Salary));
Assert.That(JsonNode.Parse(actual.Configuration)!["Type"]!.GetValue<string>(), Is.EqualTo(expected.Configuration.Type));
});
}
private static PostBindingModel CreateModel(string? postId = null, string postName = "name", PostType postType = PostType.DeliveryMan, double salary = 10)
private static PostBindingModel CreateModel(string? postId = null, string postName = "name", PostType postType = PostType.DeliveryMan, string? configuration = null)
=> new()
{
Id = postId ?? Guid.NewGuid().ToString(),
PostName = postName,
PostType = postType.ToString(),
Salary = salary
ConfigurationJson = configuration ?? JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 })
};
private static void AssertElement(Post? actual, PostBindingModel expected)
@@ -464,7 +546,7 @@ internal class PostControllerTests : BaseWebApiControllerTest
Assert.That(actual.PostId, Is.EqualTo(expected.Id));
Assert.That(actual.PostName, Is.EqualTo(expected.PostName));
Assert.That(actual.PostType.ToString(), Is.EqualTo(expected.PostType));
Assert.That(actual.Salary, Is.EqualTo(expected.Salary));
Assert.That(actual.Configuration.Type, Is.EqualTo(JsonNode.Parse(expected.ConfigurationJson!)!["Type"]!.GetValue<string>()));
});
}
}

View File

@@ -11,19 +11,28 @@ namespace SPiluSZharuTests.WebApiControllersTests;
[TestFixture]
internal class ProductControllerTests : BaseWebApiControllerTest
{
private string _restaurantId;
[SetUp]
public void SetUp()
{
_restaurantId = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn().Id;
}
[TearDown]
public void TearDown()
{
SPiluSZharuDbContext.RemoveProductsFromDatabase();
SPiluSZharuDbContext.RemoveRestaurantsFromDatabase();
}
[Test]
public async Task GetList_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 3");
//Act
var response = await HttpClient.GetAsync("/api/products/getrecords?includeDeleted=false");
//Assert
@@ -56,9 +65,9 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetList_OnlyActual_ShouldSuccess_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 3", isDeleted: false);
//Act
var response = await HttpClient.GetAsync("/api/products/getrecords?includeDeleted=false");
//Assert
@@ -76,9 +85,9 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetList_IncludeNoActual_ShouldSuccess_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 2", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "name 3", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 2", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 3", isDeleted: false);
//Act
var response = await HttpClient.GetAsync("/api/products/getrecords?includeDeleted=true");
//Assert
@@ -93,11 +102,63 @@ internal class ProductControllerTests : BaseWebApiControllerTest
});
}
[Test]
public async Task GetList_ByRestaurant_ShouldSuccess_Test()
{
//Arrange
var restaurant = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant.Id, productName: "name 3", isDeleted: false);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrestaurantrecords?id={_restaurantId}&includeDeleted=true");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
var data = await GetModelFromResponseAsync<List<ProductViewModel>>(response);
Assert.That(data, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(data, Has.Count.EqualTo(2));
Assert.That(data.All(x => x.RestaurantId == _restaurantId));
});
AssertElement(data.First(x => x.Id == product.Id), product);
}
[Test]
public async Task GetList_ByRestaurant_WhenOnlyActual_ShouldSuccess_Test()
{
//Arrange
var manufacruer = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 1", isDeleted: true);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "name 2", isDeleted: false);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(manufacruer.Id, productName: "name 3", isDeleted: false);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrestaurantrecords?id={_restaurantId}&includeDeleted=false");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
var data = await GetModelFromResponseAsync<List<ProductViewModel>>(response);
Assert.That(data, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(data, Has.Count.EqualTo(1));
Assert.That(data.All(x => x.RestaurantId == _restaurantId && !x.IsDeleted));
});
}
[Test]
public async Task GetList_ByRestaurant_WhenIdIsNotGuid_ShouldBadRequest_Test()
{
//Act
var response = await HttpClient.GetAsync($"/api/products/getrestaurantrecords?id=id&includeDeleted=false");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task GetHistoryByProductId_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10));
var history = SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1));
@@ -115,7 +176,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetHistoryByProductId_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10));
SPiluSZharuDbContext.InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1));
@@ -141,7 +202,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ById_WhenHaveRecord_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/{product.Id}");
//Assert
@@ -153,7 +214,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ById_WhenNoRecord_ShouldNotFound_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/{Guid.NewGuid()}");
//Assert
@@ -164,7 +225,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ById_WhenRecordWasDeleted_ShouldNotFound_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, isDeleted: true);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/{product.Id}");
//Assert
@@ -175,7 +236,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ByName_WhenHaveRecord_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/{product.ProductName}");
//Assert
@@ -187,7 +248,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ByName_WhenNoRecord_ShouldNotFound_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/New%20Name");
//Assert
@@ -198,7 +259,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task GetElement_ByName_WhenRecordWasDeleted_ShouldNotFound_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true);
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, isDeleted: true);
//Act
var response = await HttpClient.GetAsync($"/api/products/getrecord/{product.ProductName}");
//Assert
@@ -209,8 +270,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Post_ShouldSuccess_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var productModel = CreateModel();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
var productModel = CreateModel(_restaurantId);
//Act
var response = await HttpClient.PostAsync($"/api/products/register", MakeContent(productModel));
//Assert
@@ -222,8 +283,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Post_WhenHaveRecordWithSameId_ShouldBadRequest_Test()
{
//Arrange
var productModel = CreateModel();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productModel.Id);
var productModel = CreateModel(_restaurantId);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productModel.Id);
//Act
var response = await HttpClient.PostAsync($"/api/products/register", MakeContent(productModel));
//Assert
@@ -234,8 +295,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Post_WhenHaveRecordWithSameName_ShouldBadRequest_Test()
{
//Arrange
var productModel = CreateModel(productName: "unique name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: productModel.ProductName!);
var productModel = CreateModel(_restaurantId, productName: "unique name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: productModel.ProductName!);
//Act
var response = await HttpClient.PostAsync($"/api/products/register", MakeContent(productModel));
//Assert
@@ -246,10 +307,10 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Post_WhenDataIsIncorrect_ShouldBadRequest_Test()
{
//Arrange
var productModelWithIdIncorrect = new ProductBindingModel { Id = "Id", ProductName = "name", Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithNameIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = string.Empty, Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithProductTypeIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = "name", Price = 100, ProductType = string.Empty };
var productModelWithPriceIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = "name", Price = 0, ProductType = ProductType.Burgers.ToString() };
var productModelWithIdIncorrect = new ProductBindingModel { Id = "Id", RestaurantId = _restaurantId, ProductName = "name", Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithNameIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = string.Empty, Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithProductTypeIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = "name", Price = 100, ProductType = string.Empty };
var productModelWithPriceIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = "name", Price = 0, ProductType = ProductType.Burgers.ToString() };
//Act
var responseWithIdIncorrect = await HttpClient.PostAsync($"/api/products/register", MakeContent(productModelWithIdIncorrect));
var responseWithNameIncorrect = await HttpClient.PostAsync($"/api/products/register", MakeContent(productModelWithNameIncorrect));
@@ -287,8 +348,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Put_ShouldSuccess_Test()
{
//Arrange
var productModel = CreateModel();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productModel.Id);
var productModel = CreateModel(_restaurantId);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productModel.Id);
//Act
var response = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModel));
//Assert
@@ -301,8 +362,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Put_WhenNoFoundRecord_ShouldBadRequest_Test()
{
//Arrange
var productModel = CreateModel();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
var productModel = CreateModel(_restaurantId);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModel));
//Assert
@@ -313,9 +374,9 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Put_WhenHaveRecordWithSameName_ShouldBadRequest_Test()
{
//Arrange
var productModel = CreateModel(productName: "unique name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productModel.Id);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: productModel.ProductName!);
var productModel = CreateModel(_restaurantId, productName: "unique name");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productModel.Id);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: productModel.ProductName!);
//Act
var response = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModel));
//Assert
@@ -326,8 +387,8 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Put_WhenRecordWasDeleted_ShouldBadRequest_Test()
{
//Arrange
var productModel = CreateModel();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productModel.Id, isDeleted: true);
var productModel = CreateModel(_restaurantId);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productModel.Id, isDeleted: true);
//Act
var response = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModel));
//Assert
@@ -338,10 +399,10 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Put_WhenDataIsIncorrect_ShouldBadRequest_Test()
{
//Arrange
var productModelWithIdIncorrect = new ProductBindingModel { Id = "Id", ProductName = "name", Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithNameIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = string.Empty, Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithProductTypeIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = "name", Price = 100, ProductType = string.Empty };
var productModelWithPriceIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), ProductName = "name", Price = 0, ProductType = ProductType.Burgers.ToString() };
var productModelWithIdIncorrect = new ProductBindingModel { Id = "Id", RestaurantId = _restaurantId, ProductName = "name", Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithNameIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = string.Empty, Price = 100, ProductType = ProductType.Burgers.ToString() };
var productModelWithProductTypeIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = "name", Price = 100, ProductType = string.Empty };
var productModelWithPriceIncorrect = new ProductBindingModel { Id = Guid.NewGuid().ToString(), RestaurantId = _restaurantId, ProductName = "name", Price = 0, ProductType = ProductType.Burgers.ToString() };
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModelWithIdIncorrect));
var responseWithNameIncorrect = await HttpClient.PutAsync($"/api/products/changeinfo", MakeContent(productModelWithNameIncorrect));
@@ -380,7 +441,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
{
//Arrange
var productId = Guid.NewGuid().ToString();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productId);
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productId);
//Act
var response = await HttpClient.DeleteAsync($"/api/products/delete/{productId}");
SPiluSZharuDbContext.ChangeTracker.Clear();
@@ -396,7 +457,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Delete_WhenNoFoundRecord_ShouldBadRequest_Test()
{
//Arrange
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn();
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId);
//Act
var response = await HttpClient.DeleteAsync($"/api/products/delete/{Guid.NewGuid()}");
//Assert
@@ -407,7 +468,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
public async Task Delete_WhenRecordWasDeleted_ShouldBadRequest_Test()
{
//Arrange
var productId = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(isDeleted: true).Id;
var productId = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, isDeleted: true).Id;
//Act
var response = await HttpClient.DeleteAsync($"/api/products/delete/{productId}");
//Assert
@@ -429,10 +490,12 @@ internal class ProductControllerTests : BaseWebApiControllerTest
Assert.Multiple(() =>
{
Assert.That(actual.Id, Is.EqualTo(expected.Id));
Assert.That(actual.RestaurantId, Is.EqualTo(expected.RestaurantId));
Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName));
Assert.That(actual.ProductType, Is.EqualTo(expected.ProductType.ToString()));
Assert.That(actual.Price, Is.EqualTo(expected.Price));
Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted));
Assert.That(actual.RestaurantName, Is.EqualTo(expected.Restaurant!.RestaurantName));
});
}
@@ -447,10 +510,11 @@ internal class ProductControllerTests : BaseWebApiControllerTest
});
}
private static ProductBindingModel CreateModel(string? id = null, string productName = "name", ProductType productType = ProductType.Burgers, double price = 1)
private static ProductBindingModel CreateModel(string restaurantId, string? id = null, string productName = "name", ProductType productType = ProductType.Burgers, double price = 1)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
RestaurantId = restaurantId,
ProductName = productName,
ProductType = productType.ToString(),
Price = price
@@ -462,6 +526,7 @@ internal class ProductControllerTests : BaseWebApiControllerTest
Assert.Multiple(() =>
{
Assert.That(actual.Id, Is.EqualTo(expected.Id));
Assert.That(actual.RestaurantId, Is.EqualTo(expected.RestaurantId));
Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName));
Assert.That(actual.ProductType.ToString(), Is.EqualTo(expected.ProductType));
Assert.That(actual.Price, Is.EqualTo(expected.Price));

View File

@@ -0,0 +1,206 @@
using NUnit.Framework.Constraints;
using SPiluSZharuContracts.ViewModels;
using SPiluSZharuTests.Infrastructure;
using System.Net;
namespace SPiluSZharuTests.WebApiControllersTests;
[TestFixture]
internal class ReportControllerTests : BaseWebApiControllerTest
{
[TearDown]
public void TearDown()
{
SPiluSZharuDbContext.RemoveProductsFromDatabase();
SPiluSZharuDbContext.RemoveRestaurantsFromDatabase();
SPiluSZharuDbContext.RemoveSalesFromDatabase();
SPiluSZharuDbContext.RemoveWorkersFromDatabase();
SPiluSZharuDbContext.RemovePostsFromDatabase();
SPiluSZharuDbContext.RemoveSalariesFromDatabase();
}
[Test]
public async Task GetProducts_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var restaurant1 = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 1");
var restaurant2 = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.3");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant2.Id, productName: "name 2.1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant2.Id, productName: "name 2.2");
//Act
var response = await HttpClient.GetAsync("/api/report/getproducts");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
var data = await GetModelFromResponseAsync<List<RestaurantProductViewModel>>(response);
Assert.That(data, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(data, Has.Count.EqualTo(2));
Assert.That(data.First(x => x.RestaurantName == restaurant1.RestaurantName).Products, Has.Count.EqualTo(3));
Assert.That(data.First(x => x.RestaurantName == restaurant2.RestaurantName).Products, Has.Count.EqualTo(2));
});
}
[Test]
public async Task GetSales_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn();
var restaurantId = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn();
var product1 = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurantId.Id, productName: "name 1");
var product2 = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurantId.Id, productName: "name 2");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, products: [(product1.Id, 10, 1.1), (product2.Id, 10, 1.1)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, products: [(product1.Id, 10, 1.1)]);
//Act
var response = await HttpClient.GetAsync($"/api/report/getsales?fromDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
var data = await GetModelFromResponseAsync<List<SaleViewModel>>(response);
Assert.That(data, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(data, Has.Count.EqualTo(2));
});
}
[Test]
public async Task GetSales_WhenDateIsIncorrect_ShouldBadRequest_Test()
{
//Act
var response = await HttpClient.GetAsync($"/api/report/getsales?fromDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task GetSalary_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var worker1 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 1", postId: post.PostId).AddPost(post);
var worker2 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 2", postId: post.PostId, phoneNumber: "+7(999)999-99-99").AddPost(post);
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 100, salaryDate: DateTime.UtcNow.AddDays(-10));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 1000, salaryDate: DateTime.UtcNow.AddDays(-5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 200, salaryDate: DateTime.UtcNow.AddDays(5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 500, salaryDate: DateTime.UtcNow.AddDays(-5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 300, salaryDate: DateTime.UtcNow.AddDays(-3));
//Act
var response = await HttpClient.GetAsync($"/api/report/getsalary?fromDate={DateTime.UtcNow.AddDays(-7):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
var data = await GetModelFromResponseAsync<List<WorkerSalaryByPeriodViewModel>>(response);
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(2));
Assert.Multiple(() =>
{
Assert.That(data.First(x => x.WorkerFIO == worker1.FIO).TotalSalary, Is.EqualTo(1000));
Assert.That(data.First(x => x.WorkerFIO == worker2.FIO).TotalSalary, Is.EqualTo(800));
});
}
[Test]
public async Task GetSalary_WhenDateIsIncorrect_ShouldBadRequest_Test()
{
//Act
var response = await HttpClient.GetAsync($"/api/report/getsalary?fromDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task LoadProducts_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var restaurant1 = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 1");
var restaurant2 = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn(restaurantName: "name 2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.2");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant1.Id, productName: "name 1.3");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant2.Id, productName: "name 2.1");
SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurant2.Id, productName: "name 2.2");
//Act
var response = await HttpClient.GetAsync("/api/report/LoadProducts");
//Assert
await AssertStreamAsync(response, "file.docx");
}
[Test]
public async Task LoadSales_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn();
var restaurantId = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn();
var product1 = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurantId.Id, productName: "name 1");
var product2 = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(restaurantId.Id, productName: "name 2");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, products: [(product1.Id, 10, 1.1), (product2.Id, 10, 1.1)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id, products: [(product1.Id, 10, 1.1)]);
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsales?fromDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, "file.xlsx");
}
[Test]
public async Task LoadSales_WhenDateIsIncorrect_ShouldBadRequest_Test()
{
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsales?fromDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
[Test]
public async Task LoadSalary_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn();
var worker1 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 1", postId: post.PostId).AddPost(post);
var worker2 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 2", postId: post.PostId, phoneNumber: "+7(999)999-99-99").AddPost(post);
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 100, salaryDate: DateTime.UtcNow.AddDays(-10));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 1000, salaryDate: DateTime.UtcNow.AddDays(-5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 200, salaryDate: DateTime.UtcNow.AddDays(5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 500, salaryDate: DateTime.UtcNow.AddDays(-5));
SPiluSZharuDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 300, salaryDate: DateTime.UtcNow.AddDays(-3));
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.UtcNow.AddDays(-7):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, "file.pdf");
}
[Test]
public async Task LoadSalary_WhenDateIsIncorrect_ShouldBadRequest_Test()
{
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}
private static async Task AssertStreamAsync(HttpResponseMessage response, string fileNameForSave = "")
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
using var data = await response.Content.ReadAsStreamAsync();
Assert.That(data, Is.Not.Null);
Assert.That(data.Length, Is.GreaterThan(0));
await SaveStreamAsync(data, fileNameForSave);
}
private static async Task SaveStreamAsync(Stream stream, string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return;
}
var path = Path.Combine(Directory.GetCurrentDirectory(), fileName);
if (File.Exists(path))
{
File.Delete(path);
}
stream.Position = 0;
using var fileStream = new FileStream(path, FileMode.OpenOrCreate);
await stream.CopyToAsync(fileStream);
}
}

View File

@@ -154,22 +154,22 @@ internal class SalaryControllerTests : BaseWebApiControllerTest
public async Task Calculate_ShouldSuccess_Test()
{
//Arrange
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(salary: 1000);
var worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(postId: post.PostId);
var sale = SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id);
//var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(salary: 1000);
//var worker = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(postId: post.PostId);
//var sale = SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker.Id);
var expectedSum = sale.Sum * 0.1 + post.Salary;
//Act
var response = await HttpClient.PostAsync($"/api/salary/calculate?date={DateTime.UtcNow:MM/dd/yyyy}", null);
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
var salaries = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker.Id);
Assert.Multiple(() =>
{
Assert.That(salaries, Has.Length.EqualTo(1));
Assert.That(salaries.First().WorkerSalary, Is.EqualTo(expectedSum));
Assert.That(salaries.First().SalaryDate.Month, Is.EqualTo(DateTime.UtcNow.Month));
});
//var expectedSum = sale.Sum * 0.1 + post.Salary;
////Act
//var response = await HttpClient.PostAsync($"/api/salary/calculate?date={DateTime.UtcNow:MM/dd/yyyy}", null);
////Assert
//Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
//var salaries = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker.Id);
//Assert.Multiple(() =>
//{
// Assert.That(salaries, Has.Length.EqualTo(1));
// Assert.That(salaries.First().WorkerSalary, Is.EqualTo(expectedSum));
// Assert.That(salaries.First().SalaryDate.Month, Is.EqualTo(DateTime.UtcNow.Month));
//});
}
[Test]
@@ -187,17 +187,17 @@ internal class SalaryControllerTests : BaseWebApiControllerTest
public async Task Calculate_WhenWorkerWithoutSales_ShouldSuccess_Test()
{
//Arrange
var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(salary: 1000);
var worker1 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 1", postId: post.PostId, phoneNumber: "+7(555)555-55-55");
var worker2 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 2", postId: post.PostId, phoneNumber: "+7(333)333-33-33");
var sale = SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker1.Id);
//Act
var response = await HttpClient.PostAsync($"/api/salary/calculate?date={DateTime.UtcNow:MM/dd/yyyy}", null);
//Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
var salary1 = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker1.Id).First().WorkerSalary;
var salary2 = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker2.Id).First().WorkerSalary;
Assert.That(salary1, Is.Not.EqualTo(salary2));
//var post = SPiluSZharuDbContext.InsertPostToDatabaseAndReturn(salary: 1000);
//var worker1 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 1", postId: post.PostId, phoneNumber: "+7(555)555-55-55");
//var worker2 = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 2", postId: post.PostId, phoneNumber: "+7(333)333-33-33");
//var sale = SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(worker1.Id);
////Act
//var response = await HttpClient.PostAsync($"/api/salary/calculate?date={DateTime.UtcNow:MM/dd/yyyy}", null);
////Assert
//Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
//var salary1 = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker1.Id).First().WorkerSalary;
//var salary2 = SPiluSZharuDbContext.GetSalariesFromDatabaseByWorkerId(worker2.Id).First().WorkerSalary;
//Assert.That(salary1, Is.Not.EqualTo(salary2));
}
[Test]

View File

@@ -18,7 +18,7 @@ internal class SaleControllerTests : BaseWebApiControllerTest
{
_restaurantId = SPiluSZharuDbContext.InsertRestaurantToDatabaseAndReturn().Id;
_workerId = SPiluSZharuDbContext.InsertWorkerToDatabaseAndReturn().Id;
_productId = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn().Id;
_productId = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId).Id;
}
[TearDown]
@@ -207,7 +207,7 @@ internal class SaleControllerTests : BaseWebApiControllerTest
public async Task GetList_ByProductId_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "Other name");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "Other name");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_workerId, _restaurantId, products: [(_productId, 5, 1.1)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_workerId, _restaurantId, products: [(_productId, 1, 1.1), (product.Id, 4, 1.1)]);
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_workerId, null, products: [(product.Id, 1, 1.1)]);
@@ -229,7 +229,7 @@ internal class SaleControllerTests : BaseWebApiControllerTest
public async Task GetList_ByProductId_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(productName: "Other product");
var product = SPiluSZharuDbContext.InsertProductToDatabaseAndReturn(_restaurantId, productName: "Other product");
SPiluSZharuDbContext.InsertSaleToDatabaseAndReturn(_workerId, _restaurantId, products: [(_productId, 1, 1.1)]);
//Act
var response = await HttpClient.GetAsync($"/api/sales/getproductrecords?id={product.Id}&fromDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(1):MM/dd/yyyy HH:mm:ss}");

View File

@@ -7,6 +7,7 @@ using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.ViewModels;
using SPiluSZharuContracts.BuisnessLogicContracts;
using Moq;
using System.Text.Json;
namespace SPiluSZharuWebApi.Adapters;
@@ -18,6 +19,8 @@ public class PostAdapter : IPostAdapter
private readonly Mapper _mapper;
private readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
public PostAdapter(IPostBuisnessLogicContract postBuisnessLogicContract, ILogger<PostAdapter> logger)
{
_postBuisnessLogicContract = postBuisnessLogicContract;
@@ -25,7 +28,8 @@ public class PostAdapter : IPostAdapter
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<PostBindingModel, PostDataModel>();
cfg.CreateMap<PostDataModel, PostViewModel>();
cfg.CreateMap<PostDataModel, PostViewModel>()
.ForMember(x => x.Configuration, x => x.MapFrom(src => JsonSerializer.Serialize(src.ConfigurationModel, JsonSerializerOptions)));
});
_mapper = new Mapper(config);
}

View File

@@ -6,6 +6,7 @@ using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.ViewModels;
using SPiluSZharuContracts.BuisnessLogicContracts;
using SPiluSZharuBuisnessLogic.Implementations;
namespace SPiluSZharuWebApi.Adapters;
@@ -53,6 +54,39 @@ public class ProductAdapter : IProductAdapter
}
}
public ProductOperationResponse GetRestaurantList(string id, bool includeDeleted)
{
try
{
return ProductOperationResponse.OK([.. _productBuisnessLogicContract.GetAllProductsByRestaurant(id, !includeDeleted).Select(x => _mapper.Map<ProductViewModel>(x))]);
}
catch (ArgumentNullException ex)
{
_logger.LogError(ex, "ArgumentNullException");
return ProductOperationResponse.BadRequest("Data is empty");
}
catch (ValidationException ex)
{
_logger.LogError(ex, "ValidationException");
return ProductOperationResponse.BadRequest($"Incorrect data transmitted: {ex.Message}");
}
catch (NullListException)
{
_logger.LogError("NullListException");
return ProductOperationResponse.NotFound("The list is not initialized");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ProductOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ProductOperationResponse.InternalServerError(ex.Message);
}
}
public ProductOperationResponse GetHistory(string id)
{
try

View File

@@ -0,0 +1,196 @@
using AutoMapper;
using SPiluSZharuContracts.AdapterContracts;
using SPiluSZharuContracts.AdapterContracts.OperationResponses;
using SPiluSZharuContracts.BuisnessLogicContracts;
using SPiluSZharuContracts.DataModels;
using SPiluSZharuContracts.Exceptions;
using SPiluSZharuContracts.ViewModels;
namespace SPiluSZharuWebApi.Adapters;
public class ReportAdapter : IReportAdapter
{
private readonly IReportContract _reportContract;
private readonly ILogger _logger;
private readonly Mapper _mapper;
public ReportAdapter(IReportContract reportContract, ILogger<ProductAdapter> logger)
{
_reportContract = reportContract;
_logger = logger;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<RestaurantProductDataModel, RestaurantProductViewModel>();
cfg.CreateMap<SaleDataModel, SaleViewModel>();
cfg.CreateMap<SaleProductDataModel, SaleProductViewModel>();
cfg.CreateMap<WorkerSalaryByPeriodDataModel, WorkerSalaryByPeriodViewModel>();
});
_mapper = new Mapper(config);
}
public async Task<ReportOperationResponse> GetDataProductsByRestaurantAsync(CancellationToken ct)
{
try
{
return ReportOperationResponse.OK([.. (await _reportContract.GetDataProductsByRestaurantAsync(ct)).Select(x => _mapper.Map<RestaurantProductViewModel>(x))]);
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
public async Task<ReportOperationResponse> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
try
{
return ReportOperationResponse.OK((await _reportContract.GetDataSaleByPeriodAsync(dateStart, dateFinish, ct)).Select(x => _mapper.Map<SaleViewModel>(x)).ToList());
}
catch (IncorrectDatesException ex)
{
_logger.LogError(ex, "IncorrectDatesException");
return ReportOperationResponse.BadRequest($"Incorrect dates: {ex.Message}");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
public async Task<ReportOperationResponse> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
try
{
return ReportOperationResponse.OK((await _reportContract.GetDataSalaryByPeriodAsync(dateStart, dateFinish, ct)).Select(x => _mapper.Map<WorkerSalaryByPeriodViewModel>(x)).ToList());
}
catch (IncorrectDatesException ex)
{
_logger.LogError(ex, "IncorrectDatesException");
return ReportOperationResponse.BadRequest($"Incorrect dates: {ex.Message}");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
public async Task<ReportOperationResponse> CreateDocumentProductsByRestaurantAsync(CancellationToken ct)
{
try
{
return SendStream(await _reportContract.CreateDocumentProductsByRestaurantAsync(ct), "products.docx");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
public async Task<ReportOperationResponse> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
try
{
return SendStream(await _reportContract.CreateDocumentSalesByPeriodAsync(dateStart, dateFinish, ct), "sales.xslx");
}
catch (IncorrectDatesException ex)
{
_logger.LogError(ex, "IncorrectDatesException");
return ReportOperationResponse.BadRequest($"Incorrect dates: {ex.Message}");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
public async Task<ReportOperationResponse> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
try
{
return SendStream(await _reportContract.CreateDocumentSalaryByPeriodAsync(dateStart, dateFinish, ct), "salary.pdf");
}
catch (IncorrectDatesException ex)
{
_logger.LogError(ex, "IncorrectDatesException");
return ReportOperationResponse.BadRequest($"Incorrect dates: {ex.Message}");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "InvalidOperationException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (StorageException ex)
{
_logger.LogError(ex, "StorageException");
return ReportOperationResponse.InternalServerError($"Error while working with data storage: {ex.InnerException!.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception");
return ReportOperationResponse.InternalServerError(ex.Message);
}
}
private static ReportOperationResponse SendStream(Stream stream, string fileName)
{
stream.Position = 0;
return ReportOperationResponse.OK(stream, fileName);
}
}

View File

@@ -19,6 +19,12 @@ public class ProductsController(IProductAdapter adapter) : ControllerBase
return _adapter.GetList(includeDeleted).GetResponse(Request, Response);
}
[HttpGet]
public IActionResult GetRestaurantRecords(string id, bool includeDeleted)
{
return _adapter.GetRestaurantList(id, includeDeleted).GetResponse(Request, Response);
}
[HttpGet]
public IActionResult GetHistory(string id)
{

View File

@@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SPiluSZharuContracts.AdapterContracts;
namespace SPiluSZharuWebApi.Controllers;
[Authorize]
[Route("api/[controller]/[action]")]
[ApiController]
public class ReportController(IReportAdapter adapter) : ControllerBase
{
private readonly IReportAdapter _adapter = adapter;
[HttpGet]
[Consumes("application/json")]
public async Task<IActionResult> GetProducts(CancellationToken ct)
{
return (await _adapter.GetDataProductsByRestaurantAsync(ct)).GetResponse(Request, Response);
}
[HttpGet]
[Consumes("application/json")]
public async Task<IActionResult> GetSales(DateTime fromDate, DateTime toDate, CancellationToken cancellationToken)
{
return (await _adapter.GetDataSaleByPeriodAsync(fromDate, toDate, cancellationToken)).GetResponse(Request, Response);
}
[HttpGet]
[Consumes("application/json")]
public async Task<IActionResult> GetSalary(DateTime fromDate, DateTime toDate, CancellationToken cancellationToken)
{
return (await _adapter.GetDataSalaryByPeriodAsync(fromDate, toDate, cancellationToken)).GetResponse(Request, Response);
}
[HttpGet]
[Consumes("application/octet-stream")]
public async Task<IActionResult> LoadProducts(CancellationToken cancellationToken)
{
return (await _adapter.CreateDocumentProductsByRestaurantAsync(cancellationToken)).GetResponse(Request, Response);
}
[HttpGet]
[Consumes("application/octet-stream")]
public async Task<IActionResult> LoadSales(DateTime fromDate, DateTime toDate, CancellationToken cancellationToken)
{
return (await _adapter.CreateDocumentSalesByPeriodAsync(fromDate, toDate, cancellationToken)).GetResponse(Request, Response);
}
[HttpGet]
[Consumes("application/octet-stream")]
public async Task<IActionResult> LoadSalary(DateTime fromDate, DateTime toDate, CancellationToken cancellationToken)
{
return (await _adapter.CreateDocumentSalaryByPeriodAsync(fromDate, toDate, cancellationToken)).GetResponse(Request, Response);
}
}

View File

@@ -0,0 +1,15 @@
using SPiluSZharuContracts.Infrastructure;
namespace SPiluSZharuWebApi.Infrastructure;
public class ConfigurationSalary(IConfiguration configuration) : IConfigurationSalary
{
private readonly Lazy<SalarySettings> _salarySettings = new(() =>
{
return configuration.GetValue<SalarySettings>("SalarySettings") ?? throw new InvalidDataException(nameof(SalarySettings));
});
public double ExtraSaleSum => _salarySettings.Value.ExtraSaleSum;
public int MaxConcurrentThreads => _salarySettings.Value.MaxConcurrentThreads;
}

View File

@@ -0,0 +1,8 @@
namespace SPiluSZharuWebApi.Infrastructure;
public class SalarySettings
{
public double ExtraSaleSum { get; set; }
public int MaxConcurrentThreads { get; set; }
}

View File

@@ -14,6 +14,7 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using SPiluSZharuContracts.AdapterContracts;
using SPiluSZharuWebApi.Adapters;
using SPiluSZharuBuisnessLogic.OfficePackage;
var builder = WebApplication.CreateBuilder(args);
@@ -48,6 +49,7 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
};
});
builder.Services.AddSingleton<IConfigurationDatabase, ConfigurationDatabase>();
builder.Services.AddSingleton<IConfigurationSalary, ConfigurationSalary>();
builder.Services.AddTransient<IRestaurantBuisnessLogicContract, RestaurantBuisnessLogicContract>();
builder.Services.AddTransient<IPostBuisnessLogicContract, PostBuisnessLogicContract>();
@@ -71,6 +73,11 @@ builder.Services.AddTransient<ISaleAdapter, SaleAdapter>();
builder.Services.AddTransient<ISalaryAdapter, SalaryAdapter>();
builder.Services.AddTransient<IWorkerAdapter, WorkerAdapter>();
builder.Services.AddTransient<IReportContract, ReportContract>();
builder.Services.AddTransient<BaseWordBuilder, OpenXmlWordBuilder>();
builder.Services.AddTransient<BaseExcelBuilder, OpenXmlExcelBuilder>();
builder.Services.AddTransient<BasePdfBuilder, MigraDocPdfBuilder>();
builder.Services.AddTransient<IReportAdapter, ReportAdapter>();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

View File

@@ -10,6 +10,10 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
</ItemGroup>

View File

@@ -24,5 +24,8 @@
"AllowedHosts": "*",
"DataBaseSettings": {
"ConnectionString": "Host=127.0.0.1;Port=5432;Database=SPiluSZharu;Username=postgres;Password=postgres;"
},
"SalarySettings": {
"ExtraSaleSum": 1000
}
}