26 Commits

Author SHA1 Message Date
7b9beba3a3 доработки+ 2025-05-12 17:31:18 +04:00
5ba7478569 доработки 2025-05-12 17:30:30 +04:00
80d515ad4f локализация 2025-05-12 11:52:20 +04:00
69ed258009 Full Strings 2025-05-11 23:37:16 +04:00
8d19cd1280 продолжение со стоками 2025-05-11 15:22:00 +04:00
658d4909e6 продолжение со строками 2025-05-10 12:31:56 +04:00
cafccb31a9 Строки 2025-05-08 12:36:47 +04:00
c475b16143 продолжение 2025-05-07 16:33:04 +04:00
6622397eb5 ошибки 2025-05-06 21:10:49 +04:00
aed07873eb даты и зарплата 2025-05-06 20:08:37 +04:00
15b9cf0c08 full labwork6 2025-04-28 17:11:46 +04:00
8b6cde76aa CreateDocumentProductsHistoryAsync 2025-04-25 22:00:06 +04:00
dce1602dd3 Получение историй по продуктам 2025-04-25 19:41:14 +04:00
a76106fc40 Расчёт зарпалы 2025-04-25 15:06:16 +04:00
4da523cd0d Изменение в должности 2025-04-24 22:59:34 +04:00
094abf932e Первая миграция 2025-04-24 20:33:08 +04:00
64bd009c89 дороботка зарплаты и доведение всех тестов до зеленой зоны 2025-04-14 17:02:44 +04:00
6bae5a6002 worker+webapi 2025-04-10 15:24:51 +04:00
2b88c8b4b9 продолжения написания тестов webapi 2025-04-09 13:32:02 +04:00
0bb305aa40 написание тестов webapi 2025-04-08 12:55:43 +04:00
cf6462bbda обновление тестов по хранилищам 2025-04-06 20:17:48 +04:00
e3dbc9328a Изменения, связанные с Продажей и должностью 2025-03-17 13:28:45 +04:00
0d0d580d5c исправленные тесты 2025-03-03 17:08:31 +04:00
935acf89b6 Тесты 2025-03-03 15:27:32 +04:00
2af69496be Контракты 2025-03-02 22:07:54 +04:00
7333258941 DbContext 2025-03-02 21:31:46 +04:00
165 changed files with 13780 additions and 870 deletions

View File

@@ -9,6 +9,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "North_Bridge_Tests", "North
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "North_Bridge_BusinessLogics", "North_Bridge_BusinessLogics\North_Bridge_BusinessLogics.csproj", "{51817427-2BC6-40CF-8269-3C55DBDBF867}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "North_Bridge_BusinessLogics", "North_Bridge_BusinessLogics\North_Bridge_BusinessLogics.csproj", "{51817427-2BC6-40CF-8269-3C55DBDBF867}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "North_Bridge_DataBase", "North_Bridge_DataBase\North_Bridge_DataBase.csproj", "{B87C64C4-0BCE-4C82-A11D-66CDB1EDBB84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "North_Bridge_WebApi", "North_Bridge_WebApi\North_Bridge_WebApi.csproj", "{CC8C0B38-FAFD-4073-A40D-22DCD4749629}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -27,6 +31,14 @@ Global
{51817427-2BC6-40CF-8269-3C55DBDBF867}.Debug|Any CPU.Build.0 = Debug|Any CPU {51817427-2BC6-40CF-8269-3C55DBDBF867}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51817427-2BC6-40CF-8269-3C55DBDBF867}.Release|Any CPU.ActiveCfg = Release|Any CPU {51817427-2BC6-40CF-8269-3C55DBDBF867}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51817427-2BC6-40CF-8269-3C55DBDBF867}.Release|Any CPU.Build.0 = Release|Any CPU {51817427-2BC6-40CF-8269-3C55DBDBF867}.Release|Any CPU.Build.0 = Release|Any CPU
{B87C64C4-0BCE-4C82-A11D-66CDB1EDBB84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B87C64C4-0BCE-4C82-A11D-66CDB1EDBB84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B87C64C4-0BCE-4C82-A11D-66CDB1EDBB84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B87C64C4-0BCE-4C82-A11D-66CDB1EDBB84}.Release|Any CPU.Build.0 = Release|Any CPU
{CC8C0B38-FAFD-4073-A40D-22DCD4749629}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC8C0B38-FAFD-4073-A40D-22DCD4749629}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC8C0B38-FAFD-4073-A40D-22DCD4749629}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC8C0B38-FAFD-4073-A40D-22DCD4749629}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -1,25 +1,28 @@
 
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using North_Bridge_Contract.BusinessLogicsContracts; using North_Bridge_Contract.BusinessLogicsContracts;
using North_Bridge_Contract.DataModels; using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts; using North_Bridge_Contract.StoragesContracts;
using System.Text.Json; using System.Text.Json;
namespace North_Bridge_BusinessLogics.Implementations; namespace North_Bridge_BusinessLogics.Implementations;
internal class PostBusinessLogicContract(IPostStorageContract postStorageContract, ILogger logger) : IPostBusinessLogicContract internal class PostBusinessLogicContract(IPostStorageContract postStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IPostBusinessLogicContract
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
private readonly IPostStorageContract _postStorageContract = postStorageContract; private readonly IPostStorageContract _postStorageContract = postStorageContract;
public List<PostDataModel> GetAllPosts(bool onlyActive = true) private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<PostDataModel> GetAllPosts()
{ {
_logger.LogInformation("GetAllPosts params: {onlyActive}", onlyActive); _logger.LogInformation("GetAllPosts");
return _postStorageContract.GetList(onlyActive) ?? throw new return _postStorageContract.GetList();
NullListException();
} }
public List<PostDataModel> GetAllDataOfPost(string postId) public List<PostDataModel> GetAllDataOfPost(string postId)
@@ -33,7 +36,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
{ {
throw new ValidationException("The value in the field postId is not a unique identifier."); throw new ValidationException("The value in the field postId is not a unique identifier.");
} }
return _postStorageContract.GetPostWithHistory(postId) ?? throw new NullListException(); return _postStorageContract.GetPostWithHistory(postId);
} }
public PostDataModel GetPostByData(string data) public PostDataModel GetPostByData(string data)
@@ -46,10 +49,10 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
if (data.IsGuid()) if (data.IsGuid())
{ {
return _postStorageContract.GetElementById(data) ?? throw new return _postStorageContract.GetElementById(data) ?? throw new
ElementNotFoundException(data); ElementNotFoundException(data, _localizer);
} }
return _postStorageContract.GetElementByName(data) ?? throw new return _postStorageContract.GetElementByName(data) ?? throw new
ElementNotFoundException(data); ElementNotFoundException(data, _localizer);
} }
public void InsertPost(PostDataModel postDataModel) public void InsertPost(PostDataModel postDataModel)
@@ -57,7 +60,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
_logger.LogInformation("New data: {json}", _logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(postDataModel)); JsonSerializer.Serialize(postDataModel));
ArgumentNullException.ThrowIfNull(postDataModel); ArgumentNullException.ThrowIfNull(postDataModel);
postDataModel.Validate(); postDataModel.Validate(_localizer);
_postStorageContract.AddElement(postDataModel); _postStorageContract.AddElement(postDataModel);
} }
public void UpdatePost(PostDataModel postDataModel) public void UpdatePost(PostDataModel postDataModel)
@@ -65,7 +68,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
_logger.LogInformation("Update data: {json}", _logger.LogInformation("Update data: {json}",
JsonSerializer.Serialize(postDataModel)); JsonSerializer.Serialize(postDataModel));
ArgumentNullException.ThrowIfNull(postDataModel); ArgumentNullException.ThrowIfNull(postDataModel);
postDataModel.Validate(); postDataModel.Validate(_localizer);
_postStorageContract.UpdElement(postDataModel); _postStorageContract.UpdElement(postDataModel);
} }
public void DeletePost(string id) public void DeletePost(string id)
@@ -77,7 +80,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
} }
if (!id.IsGuid()) if (!id.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "id"));
} }
_postStorageContract.DelElement(id); _postStorageContract.DelElement(id);
} }
@@ -90,7 +93,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
} }
if (!id.IsGuid()) if (!id.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "id"));
} }
_postStorageContract.ResElement(id); _postStorageContract.ResElement(id);
} }

View File

@@ -5,20 +5,23 @@ using Microsoft.Extensions.Logging;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using System.Text.Json; using System.Text.Json;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_BusinessLogics.Implementations; namespace North_Bridge_BusinessLogics.Implementations;
internal class ProductBusinessLogicContract(IProductStorageContract productStorageContract, ILogger logger) : IProductBusinessLogicContract internal class ProductBusinessLogicContract(IProductStorageContract productStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IProductBusinessLogicContract
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
private readonly IProductStorageContract _productStorageContract = productStorageContract; private readonly IProductStorageContract _productStorageContract = productStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<ProductDataModel> GetAllProducts(bool onlyActive) public List<ProductDataModel> GetAllProducts(bool onlyActive)
{ {
_logger.LogInformation("GetAllProducts params: {onlyActive}", onlyActive); _logger.LogInformation("GetAllProducts params: {onlyActive}", onlyActive);
return _productStorageContract.GetList(onlyActive) ?? throw new return _productStorageContract.GetList(onlyActive);
NullListException();
} }
public List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId) public List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId)
@@ -32,7 +35,7 @@ internal class ProductBusinessLogicContract(IProductStorageContract productStora
{ {
throw new ValidationException("The value in the field productId is not a unique identifier."); throw new ValidationException("The value in the field productId is not a unique identifier.");
} }
return _productStorageContract.GetHistoryByProductId(productId) ?? throw new NullListException(); return _productStorageContract.GetHistoryByProductId(productId);
} }
public ProductDataModel GetProductByData(string data) public ProductDataModel GetProductByData(string data)
@@ -45,10 +48,10 @@ internal class ProductBusinessLogicContract(IProductStorageContract productStora
if (data.IsGuid()) if (data.IsGuid())
{ {
return _productStorageContract.GetElementById(data) ?? throw return _productStorageContract.GetElementById(data) ?? throw
new ElementNotFoundException(data); new ElementNotFoundException(data, _localizer);
} }
return _productStorageContract.GetElementByName(data) ?? throw new return _productStorageContract.GetElementByName(data) ?? throw new
ElementNotFoundException(data); ElementNotFoundException(data, _localizer);
} }
public void InsertProduct(ProductDataModel productDataModel) public void InsertProduct(ProductDataModel productDataModel)
@@ -56,7 +59,7 @@ internal class ProductBusinessLogicContract(IProductStorageContract productStora
_logger.LogInformation("New data: {json}", _logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(productDataModel)); JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel); ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate(); productDataModel.Validate(_localizer);
_productStorageContract.AddElement(productDataModel); _productStorageContract.AddElement(productDataModel);
} }
@@ -66,7 +69,7 @@ internal class ProductBusinessLogicContract(IProductStorageContract productStora
_logger.LogInformation("Update data: {json}", _logger.LogInformation("Update data: {json}",
JsonSerializer.Serialize(productDataModel)); JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel); ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate(); productDataModel.Validate(_localizer);
_productStorageContract.UpdElement(productDataModel); _productStorageContract.UpdElement(productDataModel);
} }
@@ -79,7 +82,7 @@ internal class ProductBusinessLogicContract(IProductStorageContract productStora
} }
if (!id.IsGuid()) if (!id.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "id"));
} }
_productStorageContract.DelElement(id); _productStorageContract.DelElement(id);
} }

View File

@@ -0,0 +1,173 @@
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using North_Bridge_BusinessLogics.OfficePackage;
using North_Bridge_Contract.BusinessLogicsContracts;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
namespace North_Bridge_BusinessLogics.Implementations;
internal class ReportContract : IReportContract
{
private readonly IProductStorageContract _productStorageContract;
private readonly ISaleStorageContract _saleStorageContract;
private readonly ISalaryStorageContract _salaryStorageContract;
private readonly BaseWordBuilder _baseWordBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder;
private readonly BasePdfBuilder _basePdfBuilder;
private readonly ILogger _logger;
private readonly IStringLocalizer<Messages> _localizer;
public readonly string[] _documentHeader;
public readonly string[] _tableHeader;
public ReportContract(IProductStorageContract productStorageContract, ISaleStorageContract saleStorageContract, ISalaryStorageContract salaryStorageContract, BaseWordBuilder baseWordBuilder, BaseExcelBuilder baseExcelBuilder, BasePdfBuilder basePdfBuilder, ILogger logger, IStringLocalizer<Messages> localizer)
{
_productStorageContract = productStorageContract;
_saleStorageContract = saleStorageContract;
_salaryStorageContract = salaryStorageContract;
_baseWordBuilder = baseWordBuilder;
_baseExcelBuilder = baseExcelBuilder;
_basePdfBuilder = basePdfBuilder;
_logger = logger;
_localizer = localizer;
_documentHeader = [_localizer["DocumentDocCaptionProduct"], _localizer["DocumentDocCaptionOldPrice"], _localizer["DocumentDocCaptionDate"]];
_tableHeader = [_localizer["DocumentExcelCaptionDate"], _localizer["DocumentExcelCaptionSum"]
, _localizer["DocumentExcelCaptionProduct"], _localizer["DocumentExcelCaptionCount"]];
}
public Task<List<ProductAndProductHistoryDataModel>> GetDataProductsByHistoryAsync(CancellationToken ct)
{
_logger.LogInformation("Get data ProductsByHistory");
return GetProductsHistoriesAsync(ct);
}
private async Task<List<ProductAndProductHistoryDataModel>> GetProductsHistoriesAsync(CancellationToken ct) =>
[.. (await _productStorageContract.GetHistoriesListAsync(ct)).GroupBy(x => x.ProductName).Select(x => new ProductAndProductHistoryDataModel {
ProductName = x.Key, Histories = [.. x.Select(y => y.OldPrice.ToString())], Data = [.. x.Select(y => y.ChangeDate.ToString())] })];
public async Task<Stream> CreateDocumentProductsByHistoryAsync(CancellationToken ct)
{
_logger.LogInformation("Create report ProductHistory");
var data = await GetProductsHistoriesAsync(ct) ?? throw new InvalidOperationException("No found data");
return _baseWordBuilder
.AddHeader(_localizer["DocumentDocHeader"])
.AddParagraph(string.Format(_localizer["DocumentDocSubHeader"], DateTime.Now))
.AddTable(
[3000, 3000, 3000],
[.. new List<string[]>() { _documentHeader }
.Union([.. data.SelectMany(x =>
(new List<string[]>() { new[] { x.ProductName, "", "" } })
.Union(x.Histories.Zip(x.Data, (price, date) => new[] { "", price, date }))
)])
])
.Build();
}
public async Task<List<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
return [.. (await _saleStorageContract.GetListAsync(dateStart,
dateFinish, ct)).OrderBy(x => x.SaleDate)];
}
public Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Get data SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
return GetDataBySalesAsync(dateStart, dateFinish, ct);
}
public 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");
// Создаем список строк таблицы
var tableRows = new List<string[]>
{
_tableHeader
};
// Добавляем данные
foreach (var sale in data)
{
// Основная строка продажи
tableRows.Add(new string[]
{
sale.SaleDate.ToShortDateString(),
sale.Sum.ToString("N2"),
"", // Пустое место для названия продукта
"" // Пустое место для количества
});
// Строки для каждого продукта
foreach (var product in sale.Products ?? Enumerable.Empty<ProductForSaleDataModel>())
{
tableRows.Add(new string[]
{
"", // Пустая дата
"", // Пустая сумма
product.ProductName,
product.Count.ToString("N2")
});
}
}
// Добавляем итоговую строку
tableRows.Add(new string[]
{
"Всего",
data.Sum(x => x.Sum).ToString("N2"),
"",
""
});
return _baseExcelBuilder
.AddHeader(_localizer["DocumentExcelHeader"], 0, 4)
.AddParagraph(string.Format(_localizer["DocumentExcelSubHeader"],
dateStart.ToLocalTime().ToShortDateString(),
dateFinish.ToLocalTime().ToShortDateString()), 2)
.AddTable([15, 15, 40, 15], tableRows)
.Build();
}
public Task<List<WorkerSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Get data SalaryByPeriod from {dateStart} to { dateFinish}", dateStart, dateFinish);
return GetDataBySalaryAsync(dateStart, dateFinish, ct);
}
private async Task<List<WorkerSalaryByPeriodDataModel>> GetDataBySalaryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
return [.. (await _salaryStorageContract.GetListAsync(dateStart, dateFinish, ct))
.GroupBy(x => x.WorkerId)
.Select(x => new WorkerSalaryByPeriodDataModel {
WorkerFIO = x.First().WorkerFIO,
TotalSalary = x.Sum(y => y.Salary),
FromPeriod = x.Min(y => y.SalaryDate),
ToPeriod = x.Max(y => y.SalaryDate)
})
.OrderBy(x => x.WorkerFIO)];
}
public async Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Create report SalaryByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
var data = await GetDataBySalaryAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
return _basePdfBuilder
.AddHeader(_localizer["DocumentPdfHeader"])
.AddParagraph(string.Format(_localizer["DocumentPdfSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()))
.AddPieChart("Начисления", [.. data.Select(x => (x.WorkerFIO, x.TotalSalary))])
.Build();
}
}

View File

@@ -1,13 +1,17 @@
using North_Bridge_Contract.BusinessLogicsContracts; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.StoragesContracts;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using North_Bridge_Contract.BusinessLogicsContracts;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Infrastructure.PostConfigurations;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
namespace North_Bridge_BusinessLogics.Implementations; namespace North_Bridge_BusinessLogics.Implementations;
internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract, ISaleStorageContract saleStorageContract, IPostStorageContract postStorageContract, IWorkerStorageContract workerStorageContract, ILogger logger) : ISalaryBusinessLogicContract internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract, ISaleStorageContract saleStorageContract, IPostStorageContract postStorageContract, IWorkerStorageContract workerStorageContract, ILogger logger, IConfigurationSalary сonfiguration, IStringLocalizer<Messages> localizer) : ISalaryBusinessLogicContract
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
@@ -19,22 +23,28 @@ internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageC
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract; private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
private readonly IStringLocalizer<Messages> _localizer = localizer;
private readonly Lock _lockObject = new();
public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate) public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate)
{ {
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}", fromDate, toDate); _logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}", fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
return _salaryStorageContract.GetList(fromDate, toDate) ?? throw new return _salaryStorageContract.GetList(fromDate, toDate);
NullListException();
} }
public List<SalaryDataModel> GetAllSalariesByPeriodByWorker(DateTime fromDate, DateTime toDate, string workerId) public List<SalaryDataModel> GetAllSalariesByPeriodByWorker(DateTime fromDate, DateTime toDate, string workerId)
{ {
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
if (workerId.IsEmpty()) if (workerId.IsEmpty())
{ {
@@ -42,30 +52,84 @@ internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageC
} }
if (!workerId.IsGuid()) if (!workerId.IsGuid())
{ {
throw new ValidationException("The value in the field workerId is not a unique identifier."); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "workerId"));
} }
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, { workerId}", fromDate, toDate, workerId); _logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, { workerId}", fromDate, toDate, workerId);
return _salaryStorageContract.GetList(fromDate, toDate, workerId) ?? return _salaryStorageContract.GetList(fromDate, toDate, workerId);
throw new NullListException();
} }
public void CalculateSalaryByMounth(DateTime date) public void CalculateSalaryByMounth(DateTime date)
{ {
_logger.LogInformation("CalculateSalaryByMounth: {date}", date); _logger.LogInformation("CalculateSalaryByMounth: {date}", date);
var startDate = new DateTime(date.Year, date.Month, 1); var startDate = new DateTime(date.Year, date.Month, 1).ToUniversalTime();
var finishDate = new DateTime(date.Year, date.Month, var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month)).ToUniversalTime();
DateTime.DaysInMonth(date.Year, date.Month)); var workers = _workerStorageContract.GetList();
var workers = _workerStorageContract.GetList() ?? throw new NullListException();
foreach (var worker in workers) foreach (var worker in workers)
{ {
var sales = _saleStorageContract.GetList(startDate, var sales = _saleStorageContract.GetList(startDate, finishDate, workerId: worker.Id);
finishDate, workerId: worker.Id)?.Sum(x => x.Sum) ?? var post = _postStorageContract.GetElementById(worker.PostId);
throw new NullListException(); var salary = post.ConfigurationModel switch
var post = _postStorageContract.GetElementById(worker.PostId) {
?? throw new NullListException(); null => 0,
var salary = post.Salary + sales * 0.1; CashierPostConfiguration cpc => CalculateSalaryForCashier(sales, startDate, finishDate, cpc),
_logger.LogDebug("The employee {workerId} was paid a salary of { salary}", worker.Id, salary); SupervisorPostConfiguration spc => CalculateSalaryForSupervisor(startDate, finishDate, spc),
PostConfiguration pc => pc.Rate,
};
_logger.LogDebug("The employee {workerId} was paid a salary of {salary}", worker.Id, salary);
_salaryStorageContract.AddElement(new SalaryDataModel(worker.Id, finishDate, salary)); _salaryStorageContract.AddElement(new SalaryDataModel(worker.Id, finishDate, salary));
} }
} }
private double CalculateSalaryForCashier(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, CashierPostConfiguration config)
{
var calcPercent = 0.0;
var days = (finishDate - startDate).Days;
var dates = Enumerable.Range(0, days)
.Select(offset => startDate.AddDays(offset))
.ToList();
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = _salaryConfiguration.MaxThreads
};
Parallel.ForEach(dates, parallelOptions, date =>
{
var salesInDay = sales.Where(x => x.SaleDate.Date == date.Date).ToArray();
if (salesInDay.Length == 0) return;
double dailySum = salesInDay.Sum(x => x.Sum);
double averageSale = dailySum / salesInDay.Length;
lock (_lockObject)
{
calcPercent += averageSale * config.SalePercent;
}
});
double bonus = 0;
try
{
bonus = 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 + bonus;
}
private double CalculateSalaryForSupervisor(DateTime startDate, DateTime finishDate, SupervisorPostConfiguration config)
{
try
{
return config.Rate + config.PersonalCountTrendPremium * _workerStorageContract.GetWorkerTrend(startDate, finishDate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in the supervisor payroll process");
return 0;
}
}
} }

View File

@@ -1,28 +1,31 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using North_Bridge_Contract.BusinessLogicsContracts; using North_Bridge_Contract.BusinessLogicsContracts;
using North_Bridge_Contract.DataModels; using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts; using North_Bridge_Contract.StoragesContracts;
using System.Text.Json; using System.Text.Json;
namespace North_Bridge_BusinessLogics.Implementations; namespace North_Bridge_BusinessLogics.Implementations;
internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract, ILogger logger) : ISaleBusinessLogicContract internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : ISaleBusinessLogicContract
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract; private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate) public List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate)
{ {
_logger.LogInformation("GetAllSales params: {fromDate}, {toDate}", fromDate, toDate); _logger.LogInformation("GetAllSales params: {fromDate}, {toDate}", fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
return _saleStorageContract.GetList(fromDate, toDate) ?? throw new return _saleStorageContract.GetList(fromDate, toDate);
NullListException();
} }
public List<SaleDataModel> GetAllSalesByWorkerByPeriod(string workerId, public List<SaleDataModel> GetAllSalesByWorkerByPeriod(string workerId,
@@ -31,7 +34,7 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
_logger.LogInformation("GetAllSales params: {workerId}, {fromDate}, { toDate}", workerId, fromDate, toDate); _logger.LogInformation("GetAllSales params: {workerId}, {fromDate}, { toDate}", workerId, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
if (workerId.IsEmpty()) if (workerId.IsEmpty())
{ {
@@ -39,9 +42,9 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
} }
if (!workerId.IsGuid()) if (!workerId.IsGuid())
{ {
throw new ValidationException("The value in the field workerId is not a unique identifier."); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "workerId"));
} }
return _saleStorageContract.GetList(fromDate, toDate, workerId: workerId) ?? throw new NullListException(); return _saleStorageContract.GetList(fromDate, toDate, workerId: workerId);
} }
public List<SaleDataModel> GetAllSalesByProductByPeriod(string productId, DateTime fromDate, DateTime toDate) public List<SaleDataModel> GetAllSalesByProductByPeriod(string productId, DateTime fromDate, DateTime toDate)
@@ -49,7 +52,7 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
_logger.LogInformation("GetAllSales params: {productId}, {fromDate}, { toDate}", productId, fromDate, toDate); _logger.LogInformation("GetAllSales params: {productId}, {fromDate}, { toDate}", productId, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
if (productId.IsEmpty()) if (productId.IsEmpty())
{ {
@@ -57,9 +60,9 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
} }
if (!productId.IsGuid()) if (!productId.IsGuid())
{ {
throw new ValidationException("The value in the field productId is not a unique identifier."); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "productId"));
} }
return _saleStorageContract.GetList(fromDate, toDate, productId: productId) ?? throw new NullListException(); return _saleStorageContract.GetList(fromDate, toDate, productId: productId);
} }
public SaleDataModel GetSaleByData(string data) public SaleDataModel GetSaleByData(string data)
@@ -71,10 +74,10 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
} }
if (!data.IsGuid()) if (!data.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "data"));
} }
return _saleStorageContract.GetElementById(data) ?? throw new return _saleStorageContract.GetElementById(data) ?? throw new
ElementNotFoundException(data); ElementNotFoundException(data, _localizer);
} }
public void InsertSale(SaleDataModel saleDataModel) public void InsertSale(SaleDataModel saleDataModel)
@@ -82,7 +85,7 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
_logger.LogInformation("New data: {json}", _logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(saleDataModel)); JsonSerializer.Serialize(saleDataModel));
ArgumentNullException.ThrowIfNull(saleDataModel); ArgumentNullException.ThrowIfNull(saleDataModel);
saleDataModel.Validate(); saleDataModel.Validate(_localizer);
_saleStorageContract.AddElement(saleDataModel); _saleStorageContract.AddElement(saleDataModel);
} }
@@ -95,7 +98,7 @@ internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContrac
} }
if (!id.IsGuid()) if (!id.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "id"));
} }
_saleStorageContract.DelElement(id); _saleStorageContract.DelElement(id);
} }

View File

@@ -1,23 +1,28 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using North_Bridge_Contract.BusinessLogicsContracts; using North_Bridge_Contract.BusinessLogicsContracts;
using North_Bridge_Contract.DataModels; using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts; using North_Bridge_Contract.StoragesContracts;
using System.Text.Json; using System.Text.Json;
namespace North_Bridge_BusinessLogics.Implementations; namespace North_Bridge_BusinessLogics.Implementations;
internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageContract, ILogger logger) : IWorkerBusinessLogicContract internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IWorkerBusinessLogicContract
{ {
private readonly ILogger _logger = logger; private readonly ILogger _logger = logger;
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract; private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<WorkerDataModel> GetAllWorkers(bool onlyActive = true) public List<WorkerDataModel> GetAllWorkers(bool onlyActive = true)
{ {
_logger.LogInformation("GetAllWorkers params: {onlyActive}", onlyActive); _logger.LogInformation("GetAllWorkers params: {onlyActive}", onlyActive);
return _workerStorageContract.GetList(onlyActive) ?? throw new NullListException(); return _workerStorageContract.GetList(onlyActive);
} }
public List<WorkerDataModel> GetAllWorkersByPost(string postId, bool public List<WorkerDataModel> GetAllWorkersByPost(string postId, bool
@@ -30,9 +35,9 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
} }
if (!postId.IsGuid()) if (!postId.IsGuid())
{ {
throw new ValidationException("The value in the field postId is not a unique identifier."); throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "PostId"));
} }
return _workerStorageContract.GetList(onlyActive, postId) ?? throw new NullListException(); return _workerStorageContract.GetList(onlyActive, postId);
} }
public List<WorkerDataModel> GetAllWorkersByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true) public List<WorkerDataModel> GetAllWorkersByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
@@ -40,10 +45,10 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
_logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate); _logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
return _workerStorageContract.GetList(onlyActive, fromBirthDate: return _workerStorageContract.GetList(onlyActive, fromBirthDate:
fromDate, toBirthDate: toDate) ?? throw new NullListException(); fromDate, toBirthDate: toDate);
} }
public List<WorkerDataModel> GetAllWorkersByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true) public List<WorkerDataModel> GetAllWorkersByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
@@ -51,10 +56,10 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
_logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate); _logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate)) if (fromDate.IsDateNotOlder(toDate))
{ {
throw new IncorrectDatesException(fromDate, toDate); throw new IncorrectDatesException(fromDate, toDate, _localizer);
} }
return _workerStorageContract.GetList(onlyActive, fromEmploymentDate: return _workerStorageContract.GetList(onlyActive, fromEmploymentDate:
fromDate, toEmploymentDate: toDate) ?? throw new NullListException(); fromDate, toEmploymentDate: toDate);
} }
public WorkerDataModel GetWorkerByData(string data) public WorkerDataModel GetWorkerByData(string data)
@@ -67,10 +72,10 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
if (data.IsGuid()) if (data.IsGuid())
{ {
return _workerStorageContract.GetElementById(data) ?? throw return _workerStorageContract.GetElementById(data) ?? throw
new ElementNotFoundException(data); new ElementNotFoundException(data, _localizer);
} }
return _workerStorageContract.GetElementByFIO(data) ?? throw new return _workerStorageContract.GetElementByFIO(data) ?? throw new
ElementNotFoundException(data); ElementNotFoundException(data, _localizer);
} }
public void InsertWorker(WorkerDataModel workerDataModel) public void InsertWorker(WorkerDataModel workerDataModel)
@@ -78,7 +83,7 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
_logger.LogInformation("New data: {json}", _logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(workerDataModel)); JsonSerializer.Serialize(workerDataModel));
ArgumentNullException.ThrowIfNull(workerDataModel); ArgumentNullException.ThrowIfNull(workerDataModel);
workerDataModel.Validate(); workerDataModel.Validate(_localizer);
_workerStorageContract.AddElement(workerDataModel); _workerStorageContract.AddElement(workerDataModel);
} }
@@ -87,7 +92,7 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
_logger.LogInformation("Update data: {json}", _logger.LogInformation("Update data: {json}",
JsonSerializer.Serialize(workerDataModel)); JsonSerializer.Serialize(workerDataModel));
ArgumentNullException.ThrowIfNull(workerDataModel); ArgumentNullException.ThrowIfNull(workerDataModel);
workerDataModel.Validate(); workerDataModel.Validate(_localizer);
_workerStorageContract.UpdElement(workerDataModel); _workerStorageContract.UpdElement(workerDataModel);
} }
@@ -100,7 +105,7 @@ internal class WorkerBusinessLogicContract(IWorkerStorageContract workerStorageC
} }
if (!id.IsGuid()) if (!id.IsGuid())
{ {
throw new ValidationException("Id is not a unique identifier"); throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
} }
_workerStorageContract.DelElement(id); _workerStorageContract.DelElement(id);
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
@@ -9,10 +9,13 @@
<ItemGroup> <ItemGroup>
<InternalsVisibleTo Include="North_Bridge_Tests" /> <InternalsVisibleTo Include="North_Bridge_Tests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" /> <InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
<InternalsVisibleTo Include="North_Bridge_WebApi" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,12 @@
namespace North_Bridge_BusinessLogics.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 North_Bridge_BusinessLogics.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 North_Bridge_BusinessLogics.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 North_Bridge_BusinessLogics.OfficePackage;
public 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 North_Bridge_BusinessLogics.OfficePackage;
public 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 North_Bridge_BusinessLogics.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

@@ -0,0 +1,22 @@

using North_Bridge_Contract.AdapterContracts.OperationResponses;
using North_Bridge_Contract.BindingModels;
namespace North_Bridge_Contract.AdapterContracts;
public interface IPostAdapter
{
PostOperationResponse GetList();
PostOperationResponse GetHistory(string id);
PostOperationResponse GetElement(string data);
PostOperationResponse RegisterPost(PostBindingModel postModel);
PostOperationResponse ChangePostInfo(PostBindingModel postModel);
PostOperationResponse RemovePost(string id);
PostOperationResponse RestorePost(string id);
}

View File

@@ -0,0 +1,20 @@

using North_Bridge_Contract.AdapterContracts.OperationResponses;
using North_Bridge_Contract.BindingModels;
namespace North_Bridge_Contract.AdapterContracts;
public interface IProductAdapter
{
ProductOperationResponse GetList(bool includeDeleted);
ProductOperationResponse GetHistory(string id);
ProductOperationResponse GetElement(string data);
ProductOperationResponse RegisterProduct(ProductBindingModel productModel);
ProductOperationResponse ChangeProductInfo(ProductBindingModel productModel);
ProductOperationResponse RemoveProduct(string id);
}

View File

@@ -0,0 +1,18 @@
using North_Bridge_Contract.AdapterContracts.OperationResponses;
namespace North_Bridge_Contract.AdapterContracts;
public interface IReportAdapter
{
Task<ReportOperationResponse> GetDataProductsByHistoryAsync(CancellationToken ct);
Task<ReportOperationResponse> GetDataBySalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentProductsHistoryAsync(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,13 @@

using North_Bridge_Contract.AdapterContracts.OperationResponses;
namespace North_Bridge_Contract.AdapterContracts;
public interface ISalaryAdapter
{
SalaryOperationResponse GetListByPeriod(DateTime fromDate, DateTime toDate);
SalaryOperationResponse GetListByPeriodByWorker(DateTime fromDate, DateTime toDate, string workerId);
SalaryOperationResponse CalculateSalary(DateTime date);
}

View File

@@ -0,0 +1,20 @@

using North_Bridge_Contract.AdapterContracts.OperationResponses;
using North_Bridge_Contract.BindingModels;
namespace North_Bridge_Contract.AdapterContracts;
public interface ISaleAdapter
{
SaleOperationResponse GetList(DateTime fromDate, DateTime toDate);
SaleOperationResponse GetWorkerList(string id, DateTime fromDate, DateTime toDate);
SaleOperationResponse GetProductList(string id, DateTime fromDate, DateTime toDate);
SaleOperationResponse GetElement(string id);
SaleOperationResponse MakeSale(SaleBindingModel saleModel);
SaleOperationResponse CancelSale(string id);
}

View File

@@ -0,0 +1,28 @@
using North_Bridge_Contract.AdapterContracts.OperationResponses;
using North_Bridge_Contract.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace North_Bridge_Contract.AdapterContracts;
public interface IWorkerAdapter
{
WorkerOperationResponse GetList(bool includeDeleted);
WorkerOperationResponse GetPostList(string id, bool includeDeleted);
WorkerOperationResponse GetListByBirthDate(DateTime fromDate, DateTime toDate, bool includeDeleted);
WorkerOperationResponse GetListByEmploymentDate(DateTime fromDate, DateTime toDate, bool includeDeleted);
WorkerOperationResponse GetElement(string data);
WorkerOperationResponse RegisterWorker(WorkerBindingModel workerModel);
WorkerOperationResponse ChangeWorkerInfo(WorkerBindingModel workerModel);
WorkerOperationResponse RemoveWorker(string id);
}

View File

@@ -0,0 +1,20 @@

using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses;
public class PostOperationResponse : OperationResponse
{
public static PostOperationResponse OK(List<PostViewModel> data) => OK<PostOperationResponse, List<PostViewModel>>(data);
public static PostOperationResponse OK(PostViewModel data) => OK<PostOperationResponse, PostViewModel>(data);
public static PostOperationResponse NoContent() => NoContent<PostOperationResponse>();
public static PostOperationResponse NotFound(string message) => NotFound<PostOperationResponse>(message);
public static PostOperationResponse BadRequest(string message) => BadRequest<PostOperationResponse>(message);
public static PostOperationResponse InternalServerError(string message) => InternalServerError<PostOperationResponse>(message);
}

View File

@@ -0,0 +1,27 @@
using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses
{
public class ProductOperationResponse : OperationResponse
{
public static ProductOperationResponse OK(List<ProductViewModel> data) => OK<ProductOperationResponse, List<ProductViewModel>>(data);
public static ProductOperationResponse OK(List<ProductHistoryViewModel> data) => OK<ProductOperationResponse, List<ProductHistoryViewModel>>(data);
public static ProductOperationResponse OK(ProductViewModel data) => OK<ProductOperationResponse, ProductViewModel>(data);
public static ProductOperationResponse NoContent() => NoContent<ProductOperationResponse>();
public static ProductOperationResponse NotFound(string message) => NotFound<ProductOperationResponse>(message);
public static ProductOperationResponse BadRequest(string message) => BadRequest<ProductOperationResponse>(message);
public static ProductOperationResponse InternalServerError(string message) => InternalServerError<ProductOperationResponse>(message);
}
}

View File

@@ -0,0 +1,19 @@
using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses;
public class ReportOperationResponse : OperationResponse
{
public static ReportOperationResponse OK(List<ProductAndProductHistoryViewModel> data) => OK<ReportOperationResponse, List<ProductAndProductHistoryViewModel>>(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

@@ -0,0 +1,18 @@

using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses;
public class SalaryOperationResponse : OperationResponse
{
public static SalaryOperationResponse OK(List<SalaryViewModel> data) => OK<SalaryOperationResponse, List<SalaryViewModel>>(data);
public static SalaryOperationResponse NoContent() => NoContent<SalaryOperationResponse>();
public static SalaryOperationResponse NotFound(string message) => NotFound<SalaryOperationResponse>(message);
public static SalaryOperationResponse BadRequest(string message) => BadRequest<SalaryOperationResponse>(message);
public static SalaryOperationResponse InternalServerError(string message) => InternalServerError<SalaryOperationResponse>(message);
}

View File

@@ -0,0 +1,21 @@

using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses;
public class SaleOperationResponse : OperationResponse
{
public static SaleOperationResponse OK(List<SaleViewModel> data) => OK<SaleOperationResponse, List<SaleViewModel>>(data);
public static SaleOperationResponse OK(SaleViewModel data) => OK<SaleOperationResponse, SaleViewModel>(data);
public static SaleOperationResponse NoContent() => NoContent<SaleOperationResponse>();
public static SaleOperationResponse NotFound(string message) => NotFound<SaleOperationResponse>(message);
public static SaleOperationResponse BadRequest(string message) => BadRequest<SaleOperationResponse>(message);
public static SaleOperationResponse InternalServerError(string message) => InternalServerError<SaleOperationResponse>(message);
}

View File

@@ -0,0 +1,20 @@

using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.ViewModels;
namespace North_Bridge_Contract.AdapterContracts.OperationResponses;
public class WorkerOperationResponse : OperationResponse
{
public static WorkerOperationResponse OK(List<WorkerViewModel> data) => OK<WorkerOperationResponse, List<WorkerViewModel>>(data);
public static WorkerOperationResponse OK(WorkerViewModel data) => OK<WorkerOperationResponse, WorkerViewModel>(data);
public static WorkerOperationResponse NoContent() => NoContent<WorkerOperationResponse>();
public static WorkerOperationResponse NotFound(string message) => NotFound<WorkerOperationResponse>(message);
public static WorkerOperationResponse BadRequest(string message) => BadRequest<WorkerOperationResponse>(message);
public static WorkerOperationResponse InternalServerError(string message) => InternalServerError<WorkerOperationResponse>(message);
}

View File

@@ -0,0 +1,15 @@

namespace North_Bridge_Contract.BindingModels;
public class PostBindingModel
{
public string Id { get; set; }
public string PostId => Id;
public string PostName { get; set; }
public string PostType { get; set; }
public string ConfigurationJson { get; set; }
}

View File

@@ -0,0 +1,13 @@

namespace North_Bridge_Contract.BindingModels;
public class ProductBindingModel
{
public string Id { get; set; }
public string ProductName { get; set; }
public string ProductType { get; set; }
public double Price { get; set; }
}

View File

@@ -0,0 +1,13 @@

namespace North_Bridge_Contract.BindingModels;
public class ProductForSaleBindingModel
{
public string SaleId { get; set; }
public string ProductId { get; set; }
public int Count { get; set; }
public double Price { get; set; }
}

View File

@@ -0,0 +1,11 @@

namespace North_Bridge_Contract.BindingModels;
public class SaleBindingModel
{
public string Id { get; set; }
public string WorkerId { get; set; }
public List<ProductForSaleBindingModel> Products { get; set; }
}

View File

@@ -0,0 +1,17 @@

namespace North_Bridge_Contract.BindingModels;
public class WorkerBindingModel
{
public string Id { get; set; }
public string FIO { get; set; }
public string Email { get; set; }
public string PostId { get; set; }
public DateTime BirthDate { get; set; }
public DateTime EmploymentDate { get; set; }
}

View File

@@ -2,9 +2,9 @@
namespace North_Bridge_Contract.BusinessLogicsContracts; namespace North_Bridge_Contract.BusinessLogicsContracts;
public interface IPostBusinessLogicContract internal interface IPostBusinessLogicContract
{ {
List<PostDataModel> GetAllPosts(bool onlyActive); List<PostDataModel> GetAllPosts();
List<PostDataModel> GetAllDataOfPost(string postId); List<PostDataModel> GetAllDataOfPost(string postId);

View File

@@ -2,7 +2,7 @@
namespace North_Bridge_Contract.BusinessLogicsContracts; namespace North_Bridge_Contract.BusinessLogicsContracts;
public interface IProductBusinessLogicContract internal interface IProductBusinessLogicContract
{ {
List<ProductDataModel> GetAllProducts(bool onlyActive = true); List<ProductDataModel> GetAllProducts(bool onlyActive = true);

View File

@@ -0,0 +1,18 @@
using North_Bridge_Contract.DataModels;
namespace North_Bridge_Contract.BusinessLogicsContracts;
internal interface IReportContract
{
Task<List<ProductAndProductHistoryDataModel>> GetDataProductsByHistoryAsync(CancellationToken ct);
Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<List<WorkerSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentProductsByHistoryAsync(CancellationToken ct);
Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
}

View File

@@ -2,7 +2,7 @@
namespace North_Bridge_Contract.BusinessLogicsContracts; namespace North_Bridge_Contract.BusinessLogicsContracts;
public interface ISalaryBusinessLogicContract internal interface ISalaryBusinessLogicContract
{ {
List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate); List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate);

View File

@@ -2,7 +2,7 @@
namespace North_Bridge_Contract.BusinessLogicsContracts; namespace North_Bridge_Contract.BusinessLogicsContracts;
public interface ISaleBusinessLogicContract internal interface ISaleBusinessLogicContract
{ {
List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate); List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate);

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace North_Bridge_Contract.BusinessLogicsContracts; namespace North_Bridge_Contract.BusinessLogicsContracts;
public interface IWorkerBusinessLogicContract internal interface IWorkerBusinessLogicContract
{ {
List<WorkerDataModel> GetAllWorkers(bool onlyActive = true); List<WorkerDataModel> GetAllWorkers(bool onlyActive = true);

View File

@@ -2,48 +2,56 @@
using North_Bridge_Contract.Enums; using North_Bridge_Contract.Enums;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Infrastructure.PostConfigurations;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class PostDataModel : IValidation internal class PostDataModel(string postId, string postName, PostType postType, PostConfiguration configuration) : IValidation
{ {
public string Id { get; private set; } public string Id { get; private set; } = postId;
public string PostName { get; private set; } public string PostName { get; private set; } = postName;
public PostType PostType { get; private set; } public PostType PostType { get; private set; } = postType;
public double Salary { get; private set; } public PostConfiguration ConfigurationModel { get; private set; } = configuration;
public bool IsActual { get; private set; } public PostDataModel(string postId, string postName, PostType postType, string configurationJson) : this(postId, postName, postType, (PostConfiguration)null)
public DateTime ChangeDate { get; private set; }
public PostDataModel(string id, string postName, PostType postType, double salary, bool isActual, DateTime changeDate)
{ {
Id = id; var obj = JToken.Parse(configurationJson);
PostName = postName; if (obj is not null)
PostType = postType; {
Salary = salary; ConfigurationModel = obj.Value<string>("Type") switch
IsActual = isActual; {
ChangeDate = changeDate; nameof(CashierPostConfiguration) => JsonConvert.DeserializeObject<CashierPostConfiguration>(configurationJson)!,
nameof(SupervisorPostConfiguration) => JsonConvert.DeserializeObject<SupervisorPostConfiguration>(configurationJson)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(configurationJson)!,
};
}
} }
public void Validate() public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (Id.IsEmpty()) if (Id.IsEmpty())
throw new ValidationException("Field Id is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid()) if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "Id"));
if (PostName.IsEmpty()) if (PostName.IsEmpty())
throw new ValidationException("Field PostName is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostName"));
if (PostType == PostType.None) if (PostType == PostType.None)
throw new ValidationException("Field PostType is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostType"));
if (Salary <= 0) if (ConfigurationModel is null)
throw new ValidationException("Field Salary is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotInitialized"], "ConfigurationModel"));
if (ConfigurationModel!.Rate <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Rate"));
} }
} }

View File

@@ -0,0 +1,10 @@
namespace North_Bridge_Contract.DataModels;
public class ProductAndProductHistoryDataModel
{
public required string ProductName { get; set; }
public required List<string> Histories { get; set; }
public required List<string> Data { get; set; }
}

View File

@@ -1,46 +1,41 @@
using North_Bridge_Contract.Enums; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Enums;
using North_Bridge_Contract.Exceptions; using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class ProductDataModel : IValidation internal class ProductDataModel(string id, string productName, ProductType productType, double price, bool isDeleted) : IValidation
{ {
public string Id { get; private set; } public string Id { get; private set; } = id;
public string ProductName { get; private set; } public string ProductName { get; private set; } = productName;
public ProductType ProductType { get; private set; } public ProductType ProductType { get; private set; } = productType;
public double Price { get; private set; } public double Price { get; private set; } = price;
public bool IsDeleted { get; private set; } public bool IsDeleted { get; private set; } = isDeleted;
public ProductDataModel(string id, string productName, ProductType productType, double price, bool isDeleted) public ProductDataModel(string id, string productName, ProductType productType, double price) : this(id, productName, productType, price, false) { }
{
Id = id;
ProductName = productName;
ProductType = productType;
Price = price;
IsDeleted = isDeleted;
}
public void Validate() public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (Id.IsEmpty()) if (Id.IsEmpty())
throw new ValidationException("Field Id is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid()) if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "Id"));
if (ProductName.IsEmpty()) if (ProductName.IsEmpty())
throw new ValidationException("Field ProductName is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductName"));
if (ProductType == ProductType.None) if (ProductType == ProductType.None)
throw new ValidationException("Field ProductType is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductType"));
if (Price <= 0) if (Price <= 0)
throw new ValidationException("Field Price is less than or equal to 0"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Price"));
} }
} }

View File

@@ -1,39 +1,49 @@
using North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
using System.Diagnostics;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class ProductForSaleDataModel : IValidation internal class ProductForSaleDataModel(string saleId, string productId, int count, double price) : IValidation
{ {
public string SaleId { get; private set; } private readonly ProductDataModel _product;
public string ProductId { get; private set; } public string SaleId { get; private set; } = saleId;
public int Count { get; private set; } public string ProductId { get; private set; } = productId;
public ProductForSaleDataModel(string saleId, string productId, int count) public int Count { get; private set; } = count;
public double Price { get; private set; } = price;
public string ProductName => _product?.ProductName ?? string.Empty;
public ProductForSaleDataModel(string saleId, string productId, int count, double price, ProductDataModel product) : this(saleId, productId, count, price)
{ {
SaleId = saleId; _product = product;
ProductId = productId;
Count = count;
} }
public void Validate() public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (SaleId.IsEmpty()) if (SaleId.IsEmpty())
throw new ValidationException("Field SaleId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "SaleId"));
if (!SaleId.IsGuid()) if (!SaleId.IsGuid())
throw new ValidationException("The value in the field SaleId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "SaleId"));
if (ProductId.IsEmpty()) if (ProductId.IsEmpty())
throw new ValidationException("Field ProductId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductId"));
if (!ProductId.IsGuid()) if (!ProductId.IsGuid())
throw new ValidationException("The value in the field ProductId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ProductId"));
if (Count <= 0) if (Count <= 0)
throw new ValidationException("Field Count is less than or equal to 0"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Count"));
if (Price <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Price"));
} }
} }

View File

@@ -1,33 +1,38 @@
using North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class ProductHistoryDataModel : IValidation internal class ProductHistoryDataModel(string productId, double oldPrice) : IValidation
{ {
public string ProductId { get; private set; } private readonly ProductDataModel _product;
public double OldPrice { get; private set; } public string ProductId { get; private set; } = productId;
public DateTime ChangeDate { get; private set; } public double OldPrice { get; private set; } = oldPrice;
public ProductHistoryDataModel(string productId, double oldPrice) public string ProductName => _product?.ProductName ?? string.Empty;
public DateTime ChangeDate { get; private set; } = DateTime.UtcNow;
public ProductHistoryDataModel(string productId, double oldPrice, DateTime changeDate, ProductDataModel product) : this(productId, oldPrice)
{ {
ProductId = productId; ChangeDate = changeDate;
OldPrice = oldPrice; _product = product;
ChangeDate = DateTime.UtcNow;
} }
public void Validate() public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (ProductId.IsEmpty()) if (ProductId.IsEmpty())
throw new ValidationException("Field ProductId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductId"));
if (!ProductId.IsGuid()) if (!ProductId.IsGuid())
throw new ValidationException("The value in the field ProductId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ProductId"));
if (OldPrice <= 0) if (OldPrice <= 0)
throw new ValidationException("Field OldPrice is less than or equal to 0"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "OldPrice"));
} }
} }

View File

@@ -1,33 +1,37 @@
using North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class SalaryDataModel : IValidation internal class SalaryDataModel(string workerId, DateTime salaryDate, double workerSalary) : IValidation
{ {
public string WorkerId { get; private set; } private readonly WorkerDataModel _worker;
public DateTime SalaryDate { get; private set; } public string WorkerId { get; private set; } = workerId;
public double Salary { get; private set; } public DateTime SalaryDate { get; private set; } = salaryDate.ToUniversalTime();
public SalaryDataModel(string workerId, DateTime salaryDate, double salary) public double Salary { get; private set; } = workerSalary;
public string WorkerFIO => _worker?.FIO ?? string.Empty;
public SalaryDataModel(string workerId, DateTime salaryDate, double workerSalary, WorkerDataModel worker) : this(workerId, salaryDate, workerSalary)
{ {
WorkerId = workerId; _worker = worker;
SalaryDate = salaryDate;
Salary = salary;
} }
public void Validate() public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (WorkerId.IsEmpty()) if (WorkerId.IsEmpty())
throw new ValidationException("Field WorkerId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "WorkerId"));
if (!WorkerId.IsGuid()) if (!WorkerId.IsGuid())
throw new ValidationException("The value in the field WorkerId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "WorkerId"));
if (Salary <= 0) if (Salary <= 0)
throw new ValidationException("Field Salary is less than or equal to 0"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Salary"));
} }
} }

View File

@@ -1,16 +1,20 @@
using North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class SaleDataModel : IValidation internal class SaleDataModel : IValidation
{ {
private readonly WorkerDataModel _worker;
public string Id { get; private set; } public string Id { get; private set; }
public string WorkerId { get; private set; } public string WorkerId { get; private set; }
public DateTime SaleDate { get; private set; } public DateTime SaleDate { get; private set; } = DateTime.UtcNow;
public double Sum { get; private set; } public double Sum { get; private set; }
@@ -18,33 +22,50 @@ public class SaleDataModel : IValidation
public List<ProductForSaleDataModel> Products { get; private set; } public List<ProductForSaleDataModel> Products { get; private set; }
public SaleDataModel(string id, string workerId, double sum, bool isCancel, List<ProductForSaleDataModel> products) public string WorkerFIO => _worker?.FIO ?? string.Empty;
public string WorkerEmail => _worker?.Email ?? string.Empty;
public SaleDataModel(string id, string workerId, bool isCancel, List<ProductForSaleDataModel> productsForSale)
{ {
Id = id; Id = id;
WorkerId = workerId; WorkerId = workerId;
Sum = sum;
IsCancel = isCancel; IsCancel = isCancel;
Products = products; Products = productsForSale;
Sum = Products?.Sum(x => x.Price * x.Count) ?? 0;
} }
public void Validate() public SaleDataModel(string id, string workerId, double sum, bool isCancel, List<ProductForSaleDataModel> saleProducts, WorkerDataModel worker) : this(id, workerId, isCancel, saleProducts)
{
Sum = sum;
_worker = worker;
}
public SaleDataModel(string id, string workerId, List<ProductForSaleDataModel> products) : this(id, workerId, false, products) { }
public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (Id.IsEmpty()) if (Id.IsEmpty())
throw new ValidationException("Field Id is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid()) if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "Id"));
if (WorkerId.IsEmpty()) if (WorkerId.IsEmpty())
throw new ValidationException("Field WorkerId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "WorkerId"));
if (!WorkerId.IsGuid()) if (!WorkerId.IsGuid())
throw new ValidationException("The value in the field WorkerId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "WorkerId"));
if (Sum <= 0) if (Sum <= 0)
throw new ValidationException("Field Sum is less than or equal to 0"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Sum"));
if ((Products?.Count ?? 0) == 0) if (Products is null)
throw new ValidationException("The sale must include products"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotInitialized"], "Products"));
if (Products.Count == 0)
throw new ValidationException(localizer["ValidationExceptionMessageNoProductInSale"]);
Products.ForEach(x => x.Validate(localizer));
} }
} }

View File

@@ -1,66 +1,71 @@
using North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions; using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Infrastructure; using North_Bridge_Contract.Infrastructure;
using North_Bridge_Contract.Resources;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace North_Bridge_Contract.DataModels; namespace North_Bridge_Contract.DataModels;
public class WorkerDataModel : IValidation internal class WorkerDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
{ {
public string Id { get; private set; } public readonly PostDataModel _post;
public string FIO { get; private set; } public string Id { get; private set; } = id;
public string Email { get; private set; } public string FIO { get; private set; } = fio;
public string PostId { get; private set; } public string Email { get; private set; } = email;
public DateTime BirthDate { get; private set; } public string PostId { get; private set; } = postId;
public DateTime EmploymentDate { get; private set; } public DateTime BirthDate { get; private set; } = birthDate.ToUniversalTime();
public bool IsDeleted { get; private set; } public DateTime EmploymentDate { get; private set; } = employmentDate.ToUniversalTime();
public WorkerDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) public bool IsDeleted { get; private set; } = isDeleted;
public string PostName => _post?.PostName ?? string.Empty;
public WorkerDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted, PostDataModel post) :
this(id, fio, email, postId, birthDate, employmentDate, isDeleted)
{ {
Id = id; _post = post;
FIO = fio;
Email = email;
PostId = postId;
BirthDate = birthDate;
EmploymentDate = employmentDate;
IsDeleted = isDeleted;
} }
public void Validate() public WorkerDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate) : this(id, fio, email, postId, birthDate, employmentDate, false) { }
public void Validate(IStringLocalizer<Messages> localizer)
{ {
if (Id.IsEmpty()) if (Id.IsEmpty())
throw new ValidationException("Field Id is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid()) if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "Id"));
if (FIO.IsEmpty()) if (FIO.IsEmpty())
throw new ValidationException("Field FIO is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "FIO"));
if (Email.IsEmpty()) if (Email.IsEmpty())
throw new ValidationException("Field Email is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Email"));
if (!Regex.IsMatch(Email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")) if (!Regex.IsMatch(Email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"))
throw new ValidationException("Field Email is not a valid email address"); throw new ValidationException(localizer["ValidationExceptionMessageIncorrectEmail"]);
if (PostId.IsEmpty()) if (PostId.IsEmpty())
throw new ValidationException("Field PostId is empty"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostId"));
if (!PostId.IsGuid()) if (!PostId.IsGuid())
throw new ValidationException("The value in the field PostId is not a unique identifier"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "PostId"));
if (BirthDate.Date > DateTime.Now.AddYears(-18).Date) if (BirthDate.Date > DateTime.Now.AddYears(-18).Date)
throw new ValidationException($"Only adults can be hired (BirthDate = {BirthDate.ToShortDateString()})"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageMinorsBirthDate"], BirthDate.ToShortDateString()));
if (EmploymentDate.Date < BirthDate.Date) if (EmploymentDate.Date < BirthDate.Date)
throw new ValidationException("The date of employment cannot be less than the date of birth"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmploymentDateAndBirthDate"],
EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
if ((EmploymentDate - BirthDate).TotalDays / 365 < 18) if ((EmploymentDate - BirthDate).TotalDays / 365 < 18)
throw new ValidationException($"Only adults can be hired (EmploymentDate - {EmploymentDate.ToShortDateString()}, BirthDate - {BirthDate.ToShortDateString()})"); throw new ValidationException(string.Format(localizer["ValidationExceptionMessageMinorsEmploymentDate"],
EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
} }
} }

View File

@@ -0,0 +1,12 @@
namespace North_Bridge_Contract.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,9 @@

using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.Exceptions;
internal class ElementDeletedException(string id, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementDeletedExceptionMessage"], id))
{ }

View File

@@ -1,15 +1,13 @@
 
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.Extentions; namespace North_Bridge_Contract.Extentions;
public class ElementExistsException : Exception internal class ElementExistsException(string paramName, string paramValue, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementExistsExceptionMessage"], paramValue, paramName))
{ {
public string ParamName { get; private set; } public string ParamName { get; private set; } = paramName;
public string ParamValue { get; private set; } public string ParamValue { get; private set; } = paramValue;
public ElementExistsException(string paramName, string paramValue) : base($"There is already an element with value{paramValue} of parameter { paramName}")
{
ParamName = paramName;
ParamValue = paramValue;
}
} }

View File

@@ -1,12 +1,11 @@
 
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.Exceptions; namespace North_Bridge_Contract.Exceptions;
public class ElementNotFoundException : Exception internal class ElementNotFoundException(string value, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementNotFoundExceptionMessage"], value))
{ {
public string Value { get; private set; } public string Value { get; private set; } = value;
public ElementNotFoundException(string value) : base($"Element not found at value = { value}")
{
Value = value;
}
} }

View File

@@ -1,7 +1,9 @@
 
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.Exceptions; namespace North_Bridge_Contract.Exceptions;
public class IncorrectDatesException : Exception internal class IncorrectDatesException(DateTime start, DateTime end, IStringLocalizer<Messages> localizer) :
{ Exception(string.Format(localizer["IncorrectDatesExceptionMessage"], start.ToShortDateString(), end.ToShortDateString()))
public IncorrectDatesException(DateTime start, DateTime end) : base($"The end date must be later than the start date..StartDate: { start: dd.MM.YYYY}. EndDate: {end:dd.MM.YYYY}") { } { }
}

View File

@@ -1,6 +0,0 @@
namespace North_Bridge_Contract.Exceptions;
public class NullListException : Exception
{
public NullListException() : base("The returned list is null") { }
}

View File

@@ -1,6 +1,8 @@
namespace North_Bridge_Contract.Exceptions; using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
public class StorageException : Exception namespace North_Bridge_Contract.Exceptions;
{
public StorageException(Exception ex) : base($"Error while working in storage: {ex.Message}", ex) { } internal class StorageException(Exception ex, IStringLocalizer<Messages> localizer) :
} Exception(string.Format(localizer["StorageExceptionMessage"], ex.Message), ex)
{ }

View File

@@ -1,10 +1,6 @@
 
namespace North_Bridge_Contract.Exceptions; namespace North_Bridge_Contract.Exceptions;
public class ValidationException : Exception public class ValidationException(string message) : Exception(message)
{ {
public ValidationException(string message) : base(message)
{
}
} }

View File

@@ -0,0 +1,7 @@

namespace North_Bridge_Contract.Infrastructure;
public interface IConfigurationDatabase
{
string ConnectionString { get; }
}

View File

@@ -0,0 +1,10 @@
namespace North_Bridge_Contract.Infrastructure;
public interface IConfigurationSalary
{
double ExtraInstallationSum { get; }
double ExtraSaleSum { get; }
int MaxThreads { get; }
}

View File

@@ -1,7 +1,10 @@
 
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.Resources;
namespace North_Bridge_Contract.Infrastructure; namespace North_Bridge_Contract.Infrastructure;
public interface IValidation internal interface IValidation
{ {
void Validate(); void Validate(IStringLocalizer<Messages> localizer);
} }

View File

@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net;
namespace North_Bridge_Contract.Infrastructure
{
public class OperationResponse
{
protected HttpStatusCode StatusCode { get; set; }
protected object Result { get; set; }
protected string FileName { get; set; }
public IActionResult GetResponse(HttpRequest request, HttpResponse response)
{
ArgumentNullException.ThrowIfNull(request);
ArgumentNullException.ThrowIfNull(response);
response.StatusCode = (int)StatusCode;
if (Result is null)
{
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
};
protected static TResult NotFound<TResult>(string errorMessage = null) where TResult : OperationResponse, new() => new()
{
StatusCode =
HttpStatusCode.NotFound,
Result = errorMessage
};
protected static TResult InternalServerError<TResult>(string errorMessage = null) where TResult : OperationResponse, new() => new()
{
StatusCode =
HttpStatusCode.InternalServerError,
Result = errorMessage
};
}
}

View File

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

View File

@@ -0,0 +1,12 @@
using System.Globalization;
namespace North_Bridge_Contract.Infrastructure.PostConfigurations;
public class PostConfiguration
{
public virtual string Type => nameof(PostConfiguration);
public double Rate { get; set; }
public string CultureName { get; set; } = CultureInfo.CurrentCulture.Name;
}

View File

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

View File

@@ -1,9 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>disable</Nullable>
</PropertyGroup>
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\Messages.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Messages.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Messages.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Messages.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="North_Bridge_BusinessLogics" />
<InternalsVisibleTo Include="North_Bridge_DataBase" />
<InternalsVisibleTo Include="North_Bridge_Tests" />
<InternalsVisibleTo Include="North_Bridge_WebApi" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,414 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace North_Bridge_Contract.Resources {
using System;
/// <summary>
/// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
/// </summary>
// Этот класс создан автоматически классом StronglyTypedResourceBuilder
// с помощью такого средства, как ResGen или Visual Studio.
// Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
// с параметром /str или перестройте свой проект VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Messages {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Messages() {
}
/// <summary>
/// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("North_Bridge_Contract.Resources.Messages", typeof(Messages).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Перезаписывает свойство CurrentUICulture текущего потока для всех
/// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент по данным: {0} был удален.
/// </summary>
internal static string AdapterMessageElementDeletedException {
get {
return ResourceManager.GetString("AdapterMessageElementDeletedException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Не найден элемент по данным: {0}.
/// </summary>
internal static string AdapterMessageElementNotFoundException {
get {
return ResourceManager.GetString("AdapterMessageElementNotFoundException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Данные пусты.
/// </summary>
internal static string AdapterMessageEmptyDate {
get {
return ResourceManager.GetString("AdapterMessageEmptyDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Неправильные даты: {0}.
/// </summary>
internal static string AdapterMessageIncorrectDatesException {
get {
return ResourceManager.GetString("AdapterMessageIncorrectDatesException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Ошибка при обработке данных: {0}.
/// </summary>
internal static string AdapterMessageInvalidOperationException {
get {
return ResourceManager.GetString("AdapterMessageInvalidOperationException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Ошибка при работе с хранилищем данных: {0}.
/// </summary>
internal static string AdapterMessageStorageException {
get {
return ResourceManager.GetString("AdapterMessageStorageException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Переданы неверные данные: {0}.
/// </summary>
internal static string AdapterMessageValidationException {
get {
return ResourceManager.GetString("AdapterMessageValidationException", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата изменения.
/// </summary>
internal static string DocumentDocCaptionDate {
get {
return ResourceManager.GetString("DocumentDocCaptionDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Старая цена.
/// </summary>
internal static string DocumentDocCaptionOldPrice {
get {
return ResourceManager.GetString("DocumentDocCaptionOldPrice", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Товар.
/// </summary>
internal static string DocumentDocCaptionProduct {
get {
return ResourceManager.GetString("DocumentDocCaptionProduct", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на История продуктов.
/// </summary>
internal static string DocumentDocHeader {
get {
return ResourceManager.GetString("DocumentDocHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Сформировано на дату {0}.
/// </summary>
internal static string DocumentDocSubHeader {
get {
return ResourceManager.GetString("DocumentDocSubHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Кол-во.
/// </summary>
internal static string DocumentExcelCaptionCount {
get {
return ResourceManager.GetString("DocumentExcelCaptionCount", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата.
/// </summary>
internal static string DocumentExcelCaptionDate {
get {
return ResourceManager.GetString("DocumentExcelCaptionDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Товар.
/// </summary>
internal static string DocumentExcelCaptionProduct {
get {
return ResourceManager.GetString("DocumentExcelCaptionProduct", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Сумма.
/// </summary>
internal static string DocumentExcelCaptionSum {
get {
return ResourceManager.GetString("DocumentExcelCaptionSum", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Всего.
/// </summary>
internal static string DocumentExcelCaptionTotal {
get {
return ResourceManager.GetString("DocumentExcelCaptionTotal", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Продажи за период.
/// </summary>
internal static string DocumentExcelHeader {
get {
return ResourceManager.GetString("DocumentExcelHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на c {0} по {1}.
/// </summary>
internal static string DocumentExcelSubHeader {
get {
return ResourceManager.GetString("DocumentExcelSubHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Начисления.
/// </summary>
internal static string DocumentPdfDiagramCaption {
get {
return ResourceManager.GetString("DocumentPdfDiagramCaption", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Зарплатная ведомость.
/// </summary>
internal static string DocumentPdfHeader {
get {
return ResourceManager.GetString("DocumentPdfHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на за период с {0} по {1}.
/// </summary>
internal static string DocumentPdfSubHeader {
get {
return ResourceManager.GetString("DocumentPdfSubHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Нельзя изменить удаленный элемент (идентификатор: {0}).
/// </summary>
internal static string ElementDeletedExceptionMessage {
get {
return ResourceManager.GetString("ElementDeletedExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Уже существует элемент со значением {0} параметра {1}.
/// </summary>
internal static string ElementExistsExceptionMessage {
get {
return ResourceManager.GetString("ElementExistsExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент не найден по значению = {0}.
/// </summary>
internal static string ElementNotFoundExceptionMessage {
get {
return ResourceManager.GetString("ElementNotFoundExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата окончания должна быть позже даты начала. Дата начала: {0}. ​​Дата окончания: {1}.
/// </summary>
internal static string IncorrectDatesExceptionMessage {
get {
return ResourceManager.GetString("IncorrectDatesExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Недостаточно данных для обработки: {0}.
/// </summary>
internal static string NotEnoughDataToProcessExceptionMessage {
get {
return ResourceManager.GetString("NotEnoughDataToProcessExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Не найдены данные.
/// </summary>
internal static string NotFoundDataMessage {
get {
return ResourceManager.GetString("NotFoundDataMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Ошибка при работе в хранилище: {0}.
/// </summary>
internal static string StorageExceptionMessage {
get {
return ResourceManager.GetString("StorageExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата трудоустройства не может быть раньше даты рождения ({0}, {1}).
/// </summary>
internal static string ValidationExceptionMessageEmploymentDateAndBirthDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmploymentDateAndBirthDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле {0} пусто.
/// </summary>
internal static string ValidationExceptionMessageEmptyField {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmptyField", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле Электронная почта не является электронной почтой.
/// </summary>
internal static string ValidationExceptionMessageIncorrectEmail {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectEmail", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле Телефонный номер не является телефонным номером.
/// </summary>
internal static string ValidationExceptionMessageIncorrectPhoneNumber {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectPhoneNumber", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле {0} меньше или равно 0.
/// </summary>
internal static string ValidationExceptionMessageLessOrEqualZero {
get {
return ResourceManager.GetString("ValidationExceptionMessageLessOrEqualZero", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Несовершеннолетние не могут быть приняты на работу (Дата рождения: {0}).
/// </summary>
internal static string ValidationExceptionMessageMinorsBirthDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorsBirthDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Несовершеннолетние не могут быть приняты на работу (Дата трудоустройства: {0}, Дата рождения: {1}).
/// </summary>
internal static string ValidationExceptionMessageMinorsEmploymentDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorsEmploymentDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на В продаже должен быть хотя бы один товар.
/// </summary>
internal static string ValidationExceptionMessageNoProductInSale {
get {
return ResourceManager.GetString("ValidationExceptionMessageNoProductInSale", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле {0}, не является типом уникального идентификатора.
/// </summary>
internal static string ValidationExceptionMessageNotAId {
get {
return ResourceManager.GetString("ValidationExceptionMessageNotAId", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле , не проинициализировано.
/// </summary>
internal static string ValidationExceptionMessageNotInitialized {
get {
return ResourceManager.GetString("ValidationExceptionMessageNotInitialized", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>Element nach Daten: {0} wurde gelöscht</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Element mit Daten: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>Die Daten sind leer</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Falsche Datumsangaben: {0}</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Fehler bei der Datenverarbeitung: {0}</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Fehler beim Arbeiten mit dem Datenspeicher: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Falsche Daten übergeben: Wert im Feld: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Änderungsdatum</value>
</data>
<data name="DocumentDocCaptionOldPrice" xml:space="preserve">
<value>Alter Preis</value>
</data>
<data name="DocumentDocCaptionProduct" xml:space="preserve">
<value>Produkt-Name</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Produkt-Geschichte</value>
</data>
<data name="DocumentDocSubHeader" xml:space="preserve">
<value>Erstellt am Datum {0}</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Anzahl</value>
</data>
<data name="DocumentExcelCaptionDate" xml:space="preserve">
<value>Datum</value>
</data>
<data name="DocumentExcelCaptionProduct" xml:space="preserve">
<value>Ware</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Summe</value>
</data>
<data name="DocumentExcelCaptionTotal" xml:space="preserve">
<value>Insgesamt</value>
</data>
<data name="DocumentExcelHeader" xml:space="preserve">
<value>Umsatz pro Zeitraum</value>
</data>
<data name="DocumentExcelSubHeader" xml:space="preserve">
<value>c {0} nach {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Anrechnungen</value>
</data>
<data name="DocumentPdfHeader" xml:space="preserve">
<value>Gehaltsliste</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>für den Zeitraum {0} bis {1}</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Das gelöschte Element kann nicht geändert werden (ID: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>Fehler beim Zugriff auf den Datenspeicher {0} des Parameters {1} vorhanden</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Element wurde nicht durch Wert = {0} gefunden</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>Das Enddatum muss später als das Startdatum sein. Startdatum: {0}. Enddatum: {1}</value>
</data>
<data name="NotEnoughDataToProcessExceptionMessage" xml:space="preserve">
<value>Zu verarbeitende Daten sind nicht ausreichend: {0}</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>Keine Daten gefunden</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Fehler beim Ausführen im Speicher: {0}</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>Das Beschäftigungsdatum darf nicht vor dem Geburtsdatum liegen ({0}, {1})</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Der Wert im Feld "{0}" ist leer</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>Der Wert im Feld E-Mail ist keine E-Mail</value>
</data>
<data name="ValidationExceptionMessageIncorrectPhoneNumber" xml:space="preserve">
<value>Der Wert im Feld Telefonnummer ist keine Telefonnummer</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>Der Wert im Feld {0} ist kleiner oder gleich 0</value>
</data>
<data name="ValidationExceptionMessageMinorsBirthDate" xml:space="preserve">
<value>Minderjährige können nicht eingestellt werden (Geburtsdatum: {0})</value>
</data>
<data name="ValidationExceptionMessageMinorsEmploymentDate" xml:space="preserve">
<value>Minderjährige können nicht eingestellt werden (Beschäftigungsdatum: {0}, Geburtsdatum: {1})</value>
</data>
<data name="ValidationExceptionMessageNoProductInSale" xml:space="preserve">
<value>Es muss mindestens ein Produkt zum Verkauf stehen</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>Der Wert im Feld "{0}" ist kein eindeutiger Bezeichnertyp</value>
</data>
<data name="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>Wert im Feld , nicht initialisiert</value>
</data>
</root>

View File

@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>The item according to the data: {0} has been deleted</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Not found element by data: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>The data is empty</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Incorrect dates: {0}</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Error during data processing: {0}</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Error when working with the data warehouse: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Incorrect data transmitted: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Date of change</value>
</data>
<data name="DocumentDocCaptionOldPrice" xml:space="preserve">
<value>Old price</value>
</data>
<data name="DocumentDocCaptionProduct" xml:space="preserve">
<value>Product Name</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Product History</value>
</data>
<data name="DocumentDocSubHeader" xml:space="preserve">
<value>Generated on date {0}</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Quantity</value>
</data>
<data name="DocumentExcelCaptionDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="DocumentExcelCaptionProduct" xml:space="preserve">
<value>Product</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Sum</value>
</data>
<data name="DocumentExcelCaptionTotal" xml:space="preserve">
<value>Total</value>
</data>
<data name="DocumentExcelHeader" xml:space="preserve">
<value>Sales for the period</value>
</data>
<data name="DocumentExcelSubHeader" xml:space="preserve">
<value>from {0} to {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="DocumentPdfHeader" xml:space="preserve">
<value>Salary statement</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>for the period from {0} to {1}</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>A deleted item cannot be changed (id: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>There is already an element with value {0} of the parameter {1}</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>The element was not found by value = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>The end date must be later than the start date. Start date: {0}. End date: {1}</value>
</data>
<data name="NotEnoughDataToProcessExceptionMessage" xml:space="preserve">
<value>Insufficient data to process: {0}</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>No data found</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Error when working in the storage: {0}</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>The date of employment cannot be earlier than the date of birth ({0}, {1})</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>The value in the {0} field is empty</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>The value in the Email field is not an email.</value>
</data>
<data name="ValidationExceptionMessageIncorrectPhoneNumber" xml:space="preserve">
<value>The value in the Phone Number field is not a phone number.</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>The value in the {0} field is less than or equal to 0</value>
</data>
<data name="ValidationExceptionMessageMinorsBirthDate" xml:space="preserve">
<value>Minors cannot be employed (Date of birth: {0})</value>
</data>
<data name="ValidationExceptionMessageMinorsEmploymentDate" xml:space="preserve">
<value>Minors cannot be employed (Date of employment: {0}, Date of birth: {1})</value>
</data>
<data name="ValidationExceptionMessageNoProductInSale" xml:space="preserve">
<value>There must be at least one product on sale.</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>The value in the {0} field is not a type of unique identifier.</value>
</data>
<data name="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>Value in the field , not initialized</value>
</data>
</root>

View File

@@ -0,0 +1,237 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>Элемент по данным: {0} был удален</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Не найден элемент по данным: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>Данные пусты</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Неправильные даты: {0}</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Ошибка при обработке данных: {0}</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Ошибка при работе с хранилищем данных: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Переданы неверные данные: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Дата изменения</value>
</data>
<data name="DocumentDocCaptionOldPrice" xml:space="preserve">
<value>Старая цена</value>
</data>
<data name="DocumentDocCaptionProduct" xml:space="preserve">
<value>Товар</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>История продуктов</value>
</data>
<data name="DocumentDocSubHeader" xml:space="preserve">
<value>Сформировано на дату {0}</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Кол-во</value>
</data>
<data name="DocumentExcelCaptionDate" xml:space="preserve">
<value>Дата</value>
</data>
<data name="DocumentExcelCaptionProduct" xml:space="preserve">
<value>Товар</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Сумма</value>
</data>
<data name="DocumentExcelCaptionTotal" xml:space="preserve">
<value>Всего</value>
</data>
<data name="DocumentExcelHeader" xml:space="preserve">
<value>Продажи за период</value>
</data>
<data name="DocumentExcelSubHeader" xml:space="preserve">
<value>c {0} по {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Начисления</value>
</data>
<data name="DocumentPdfHeader" xml:space="preserve">
<value>Зарплатная ведомость</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>за период с {0} по {1}</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Нельзя изменить удаленный элемент (идентификатор: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>Уже существует элемент со значением {0} параметра {1}</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Элемент не найден по значению = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>Дата окончания должна быть позже даты начала. Дата начала: {0}. ​​Дата окончания: {1}</value>
</data>
<data name="NotEnoughDataToProcessExceptionMessage" xml:space="preserve">
<value>Недостаточно данных для обработки: {0}</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>Не найдены данные</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Ошибка при работе в хранилище: {0}</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>Дата трудоустройства не может быть раньше даты рождения ({0}, {1})</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Значение в поле {0} пусто</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>Значение в поле Электронная почта не является электронной почтой</value>
</data>
<data name="ValidationExceptionMessageIncorrectPhoneNumber" xml:space="preserve">
<value>Значение в поле Телефонный номер не является телефонным номером</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>Значение в поле {0} меньше или равно 0</value>
</data>
<data name="ValidationExceptionMessageMinorsBirthDate" xml:space="preserve">
<value>Несовершеннолетние не могут быть приняты на работу (Дата рождения: {0})</value>
</data>
<data name="ValidationExceptionMessageMinorsEmploymentDate" xml:space="preserve">
<value>Несовершеннолетние не могут быть приняты на работу (Дата трудоустройства: {0}, Дата рождения: {1})</value>
</data>
<data name="ValidationExceptionMessageNoProductInSale" xml:space="preserve">
<value>В продаже должен быть хотя бы один товар</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>Значение в поле {0}, не является типом уникального идентификатора</value>
</data>
<data name="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>Значение в поле , не проинициализировано</value>
</data>
</root>

View File

@@ -2,9 +2,9 @@
namespace North_Bridge_Contract.StoragesContracts; namespace North_Bridge_Contract.StoragesContracts;
public interface IPostStorageContract internal interface IPostStorageContract
{ {
List<PostDataModel> GetList(bool onlyActual = true); List<PostDataModel> GetList();
List<PostDataModel> GetPostWithHistory(string postId); List<PostDataModel> GetPostWithHistory(string postId);

View File

@@ -2,15 +2,17 @@
namespace North_Bridge_Contract.StoragesContracts; namespace North_Bridge_Contract.StoragesContracts;
public interface IProductStorageContract internal interface IProductStorageContract
{ {
List<ProductDataModel> GetList(bool onlyActive = true); List<ProductDataModel> GetList(bool onlyActive = true);
List<ProductHistoryDataModel> GetHistoryByProductId(string productId); List<ProductHistoryDataModel> GetHistoryByProductId(string productId);
ProductDataModel? GetElementById(string id); Task<List<ProductHistoryDataModel>> GetHistoriesListAsync(CancellationToken ct);
ProductDataModel? GetElementByName(string name); ProductDataModel GetElementById(string id);
ProductDataModel GetElementByName(string name);
void AddElement(ProductDataModel productDataModel); void AddElement(ProductDataModel productDataModel);

View File

@@ -2,9 +2,11 @@
namespace North_Bridge_Contract.StoragesContracts; namespace North_Bridge_Contract.StoragesContracts;
public interface ISalaryStorageContract internal interface ISalaryStorageContract
{ {
List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string? workerId = null); List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string workerId = null);
Task<List<SalaryDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
void AddElement(SalaryDataModel salaryDataModel); void AddElement(SalaryDataModel salaryDataModel);
} }

View File

@@ -2,11 +2,13 @@
namespace North_Bridge_Contract.StoragesContracts; namespace North_Bridge_Contract.StoragesContracts;
public interface ISaleStorageContract internal interface ISaleStorageContract
{ {
List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string? workerId = null, string? productId = null); List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string workerId = null, string productId = null);
SaleDataModel? GetElementById(string id); Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
SaleDataModel GetElementById(string id);
void AddElement(SaleDataModel saleDataModel); void AddElement(SaleDataModel saleDataModel);

View File

@@ -2,7 +2,7 @@
namespace North_Bridge_Contract.StoragesContracts; namespace North_Bridge_Contract.StoragesContracts;
public interface IWorkerStorageContract internal interface IWorkerStorageContract
{ {
List<WorkerDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null); List<WorkerDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null);
@@ -15,4 +15,6 @@ public interface IWorkerStorageContract
void UpdElement(WorkerDataModel workerDataModel); void UpdElement(WorkerDataModel workerDataModel);
void DelElement(string id); void DelElement(string id);
int GetWorkerTrend(DateTime fromPeriod, DateTime toPeriod);
} }

View File

@@ -0,0 +1,13 @@

namespace North_Bridge_Contract.ViewModels;
public class PostViewModel
{
public required string Id { get; set; }
public required string PostName { get; set; }
public required string PostType { get; set; }
public required string Configuration { get; set; }
}

View File

@@ -0,0 +1,10 @@
namespace North_Bridge_Contract.ViewModels;
public class ProductAndProductHistoryViewModel
{
public required string ProductName { get; set; }
public required List<string> Histories { get; set; }
public required List<string> Data { get; set; }
}

View File

@@ -0,0 +1,13 @@

namespace North_Bridge_Contract.ViewModels;
public class ProductForSaleViewModel
{
public required string ProductId { get; set; }
public required string ProductName { get; set; }
public int Count { get; set; }
public double Price { get; set; }
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace North_Bridge_Contract.ViewModels;
public class ProductHistoryViewModel
{
public required string ProductName { get; set; }
public double OldPrice { get; set; }
public DateTime ChangeDate { get; set; }
}

View File

@@ -0,0 +1,15 @@

namespace North_Bridge_Contract.ViewModels;
public class ProductViewModel
{
public required string Id { get; set; }
public required string ProductName { get; set; }
public required string ProductType { get; set; }
public double Price { get; set; }
public bool IsDeleted { get; set; }
}

View File

@@ -0,0 +1,13 @@

namespace North_Bridge_Contract.ViewModels;
public class SalaryViewModel
{
public required string WorkerId { get; set; }
public required string WorkerFIO { get; set; }
public DateTime SalaryDate { get; set; }
public double Salary { get; set; }
}

View File

@@ -0,0 +1,19 @@

namespace North_Bridge_Contract.ViewModels;
public class SaleViewModel
{
public required string Id { get; set; }
public required string WorkerId { get; set; }
public required string WorkerFIO { get; set; }
public DateTime SaleDate { get; set; }
public double Sum { get; set; }
public bool IsCancel { get; set; }
public required List<ProductForSaleViewModel> Products { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace North_Bridge_Contract.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,21 @@

namespace North_Bridge_Contract.ViewModels;
public class WorkerViewModel
{
public required string Id { get; set; }
public required string FIO { get; set; }
public string Email { get; set; }
public required string PostId { get; set; }
public required string PostName { get; set; }
public bool IsDeleted { get; set; }
public DateTime BirthDate { get; set; }
public DateTime EmploymentDate { get; set; }
}

View File

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

View File

@@ -0,0 +1,212 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
using North_Bridge_DataBase.Models;
using Npgsql;
namespace North_Bridge_DataBase.Implementations
{
internal class PostStorageContract : IPostStorageContract
{
private readonly North_Bridge_DbContext _dbContext;
private readonly Mapper _mapper;
private readonly IStringLocalizer<Messages> _localizer;
public PostStorageContract(North_Bridge_DbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Post, PostDataModel>()
.ForMember(x => x.Id, x => x.MapFrom(src =>
src.PostId));
cfg.CreateMap<PostDataModel, Post>()
.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.Configuration, x => x.MapFrom(src => src.ConfigurationModel));
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<PostDataModel> GetList()
{
try
{
return [.._dbContext.Posts.Select(x => _mapper.Map<PostDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public List<PostDataModel> GetPostWithHistory(string postId)
{
try
{
return [.. _dbContext.Posts.Where(x => x.PostId ==
postId).Select(x => _mapper.Map<PostDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public PostDataModel? GetElementById(string id)
{
try
{
return
_mapper.Map<PostDataModel>(_dbContext.Posts.FirstOrDefault(x => x.PostId == id &&
x.IsActual));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public PostDataModel? GetElementByName(string name)
{
try
{
return
_mapper.Map<PostDataModel>(_dbContext.Posts.FirstOrDefault(x => x.PostName ==
name && x.IsActual));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void AddElement(PostDataModel postDataModel)
{
try
{
_dbContext.Posts.Add(_mapper.Map<Post>(postDataModel));
_dbContext.SaveChanges();
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostName",
postDataModel.PostName, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Posts_PostId_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostId", postDataModel.Id, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void UpdElement(PostDataModel postDataModel)
{
try
{
var transaction = _dbContext.Database.BeginTransaction();
try
{
var element = GetPostById(postDataModel.Id) ?? throw new
ElementNotFoundException(postDataModel.Id, _localizer);
if (!element.IsActual)
{
throw new
ElementDeletedException(postDataModel.Id, _localizer);
}
element.IsActual = false;
_dbContext.SaveChanges();
var newElement = _mapper.Map<Post>(postDataModel);
_dbContext.Posts.Add(newElement);
_dbContext.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostName",
postDataModel.PostName, _localizer);
}
catch (Exception ex) when (ex is ElementDeletedException || ex is
ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void DelElement(string id)
{
try
{
var element = GetPostById(id) ?? throw new
ElementNotFoundException(id, _localizer);
if (!element.IsActual)
{
throw new ElementDeletedException(id, _localizer);
}
element.IsActual = false;
_dbContext.SaveChanges();
}
catch
{
_dbContext.ChangeTracker.Clear();
throw;
}
}
public void ResElement(string id)
{
try
{
var element = GetPostById(id) ?? throw new
ElementNotFoundException(id, _localizer);
element.IsActual = true;
_dbContext.SaveChanges();
}
catch
{
_dbContext.ChangeTracker.Clear();
throw;
}
}
private Post? GetPostById(string id) => _dbContext.Posts.Where(x =>
x.PostId == id).OrderByDescending(x => x.ChangeDate).FirstOrDefault();
}
}

View File

@@ -0,0 +1,213 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
using North_Bridge_DataBase.Models;
using Npgsql;
namespace North_Bridge_DataBase.Implementations
{
internal class ProductStorageContract : IProductStorageContract
{
private readonly North_Bridge_DbContext _dbContext;
private readonly Mapper _mapper;
private readonly IStringLocalizer<Messages> _localizer;
public ProductStorageContract(North_Bridge_DbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Product, ProductDataModel>();
cfg.CreateMap<ProductDataModel, Product>()
.ForMember(x => x.IsDeleted, x => x.MapFrom(src =>
false));
cfg.CreateMap<ProductHistory, ProductHistoryDataModel>();
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<ProductDataModel> GetList(bool onlyActive = true)
{
try
{
var query = _dbContext.Products.AsQueryable();
if (onlyActive)
{
query = query.Where(x => !x.IsDeleted);
}
return [.. query.Select(x => _mapper.Map<ProductDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public List<ProductHistoryDataModel> GetHistoryByProductId(string productId)
{
try
{
return [.. _dbContext.ProductHistories.Where(x => x.ProductId
== productId).OrderByDescending(x => x.ChangeDate).Select(x =>
_mapper.Map<ProductHistoryDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public async Task<List<ProductHistoryDataModel>> GetHistoriesListAsync(CancellationToken ct)
{
try
{
return [.. await _dbContext.ProductHistories.Include(x => x.Product).Select(x => _mapper.Map<ProductHistoryDataModel>(x)).ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public ProductDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<ProductDataModel>(GetProductById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public ProductDataModel? GetElementByName(string name)
{
try
{
return
_mapper.Map<ProductDataModel>(_dbContext.Products.FirstOrDefault(x =>
x.ProductName == name && !x.IsDeleted));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void AddElement(ProductDataModel productDataModel)
{
try
{
_dbContext.Products.Add(_mapper.Map<Product>(productDataModel));
_dbContext.SaveChanges();
}
catch (InvalidOperationException ex) when (ex.TargetSite?.Name ==
"ThrowIdentityConflict")
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", productDataModel.Id, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Products_ProductName_IsDeleted" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("ProductName",
productDataModel.ProductName, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "PK_Products" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", productDataModel.Id, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void UpdElement(ProductDataModel productDataModel)
{
try
{
var transaction = _dbContext.Database.BeginTransaction();
try
{
var element = GetProductById(productDataModel.Id) ??
throw new ElementNotFoundException(productDataModel.Id, _localizer);
if (element.Price != productDataModel.Price)
{
_dbContext.ProductHistories.Add(new
ProductHistory()
{ ProductId = element.Id, OldPrice = element.Price });
_dbContext.SaveChanges();
}
_dbContext.Products.Update(_mapper.Map(productDataModel,
element));
_dbContext.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Products_ProductName_IsDeleted" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("ProductName",
productDataModel.ProductName, _localizer);
}
catch (Exception ex) when (ex is ElementDeletedException || ex is
ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void DelElement(string id)
{
try
{
var element = GetProductById(id) ?? throw new
ElementNotFoundException(id, _localizer);
element.IsDeleted = true;
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
private Product? GetProductById(string id) =>
_dbContext.Products.FirstOrDefault(x => x.Id == id && !x.IsDeleted);
}
}

View File

@@ -0,0 +1,80 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
using North_Bridge_DataBase.Models;
namespace North_Bridge_DataBase.Implementations;
internal class SalaryStorageContract : ISalaryStorageContract
{
private readonly North_Bridge_DbContext _dbContext;
private readonly Mapper _mapper;
private readonly IStringLocalizer<Messages> _localizer;
public SalaryStorageContract(North_Bridge_DbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Worker, WorkerDataModel>();
cfg.CreateMap<Salary, SalaryDataModel>();
cfg.CreateMap<SalaryDataModel, Salary>()
.ForMember(dest => dest.WorkerSalary, opt =>
opt.MapFrom(src => src.Salary));
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string? workerId = null)
{
try
{
var query = _dbContext.Salaries.Where(x => x.SalaryDate >=
startDate && x.SalaryDate <= endDate);
if (workerId is not null)
{
query = query.Where(x => x.WorkerId == workerId);
}
return [.. query.Select(x => _mapper.Map<SalaryDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
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, _localizer);
}
}
public void AddElement(SalaryDataModel salaryDataModel)
{
try
{
_dbContext.Salaries.Add(_mapper.Map<Salary>(salaryDataModel));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
}

View File

@@ -0,0 +1,154 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
using North_Bridge_DataBase.Models;
namespace North_Bridge_DataBase.Implementations;
internal class SaleStorageContract : ISaleStorageContract
{
private readonly North_Bridge_DbContext _dbContext;
private readonly Mapper _mapper;
private readonly IStringLocalizer<Messages> _localizer;
public SaleStorageContract(North_Bridge_DbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Worker, WorkerDataModel>();
cfg.CreateMap<Product, ProductDataModel>();
cfg.CreateMap<ProductForSale, ProductForSaleDataModel>();
cfg.CreateMap<ProductForSaleDataModel, ProductForSale>();
cfg.CreateMap<Sale, SaleDataModel>();
cfg.CreateMap<Sale, SaleDataModel>()
.ConstructUsing((sale, ctx) =>
new SaleDataModel(
sale.Id,
sale.WorkerId,
sale.Sum,
sale.IsCancel,
ctx.Mapper.Map<List<ProductForSaleDataModel>>(sale.ProductsForSale),
ctx.Mapper.Map<WorkerDataModel>(sale.Worker)
));
cfg.CreateMap<SaleDataModel, Sale>()
.ForMember(x => x.IsCancel, x => x.MapFrom(src => false))
.ForMember(x => x.ProductsForSale, x => x.MapFrom(src => src.Products));
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string? workerId = null, string? productId = null)
{
try
{
var query = _dbContext.Sales.Include(x
=> x.Worker).Include(x => x.ProductsForSale)!.ThenInclude(x =>
x.Product).AsQueryable();
if (startDate is not null && endDate is not null)
{
query = query.Where(x => x.SaleDate >= startDate &&
x.SaleDate < endDate);
}
if (workerId is not null)
{
query = query.Where(x => x.WorkerId == workerId);
}
if (productId is not null)
{
query = query.Where(x => x.ProductsForSale!.Any(y =>
y.ProductId == productId));
}
var f = query.ToArray();
return [.. query.Select(x => _mapper.Map<SaleDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public async Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
return [.. await _dbContext.Sales
.Include(x => x.Worker)
.Include(x => x.ProductsForSale)!
.ThenInclude(sc => sc.Product)
.Where(x => x.SaleDate >= DateTime.SpecifyKind(startDate, DateTimeKind.Utc)
&& x.SaleDate < DateTime.SpecifyKind(endDate, DateTimeKind.Utc))
.Select(x => _mapper.Map<SaleDataModel>(x))
.ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public SaleDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<SaleDataModel>(GetSaleById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void AddElement(SaleDataModel saleDataModel)
{
try
{
_dbContext.Sales.Add(_mapper.Map<Sale>(saleDataModel));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void DelElement(string id)
{
try
{
var element = GetSaleById(id) ?? throw new
ElementNotFoundException(id, _localizer);
if (element.IsCancel)
{
throw new ElementDeletedException(id, _localizer);
}
element.IsCancel = true;
_dbContext.SaveChanges();
}
catch (Exception ex) when (ex is ElementDeletedException || ex is
ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
private Sale? GetSaleById(string id) => _dbContext.Sales.Include(x => x.Worker).Include(x => x.ProductsForSale)!.ThenInclude(x => x.Product).FirstOrDefault(x => x.Id == id);
}

View File

@@ -0,0 +1,203 @@

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using North_Bridge_Contract.DataModels;
using North_Bridge_Contract.Exceptions;
using North_Bridge_Contract.Extentions;
using North_Bridge_Contract.Resources;
using North_Bridge_Contract.StoragesContracts;
using North_Bridge_DataBase.Models;
using Npgsql;
namespace North_Bridge_DataBase.Implementations;
internal class WorkerStorageContract : IWorkerStorageContract
{
private readonly North_Bridge_DbContext _dbContext;
private readonly Mapper _mapper;
private readonly IStringLocalizer<Messages> _localizer;
public WorkerStorageContract(North_Bridge_DbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Post, PostDataModel>()
.ForMember(x => x.Id, x => x.MapFrom(src => src.PostId));
cfg.CreateMap<Worker, WorkerDataModel>();
cfg.CreateMap<WorkerDataModel, Worker>();
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<WorkerDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null)
{
try
{
var query = _dbContext.Workers.AsQueryable();
if (onlyActive)
{
query = query.Where(x => !x.IsDeleted);
}
if (postId is not null)
{
query = query.Where(x => x.PostId == postId);
}
if (fromBirthDate is not null && toBirthDate is not null)
{
query = query.Where(x => x.BirthDate >= fromBirthDate && x.BirthDate <= toBirthDate);
}
if (fromEmploymentDate is not null && toEmploymentDate is not null)
{
query = query.Where(x => x.EmploymentDate >= fromEmploymentDate && x.EmploymentDate <= toEmploymentDate);
}
return [.. JoinPost(query).Select(x => _mapper.Map<WorkerDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public WorkerDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<WorkerDataModel>(GetWorkerById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public WorkerDataModel? GetElementByFIO(string fio)
{
try
{
return
_mapper.Map<WorkerDataModel>(AddPost(_dbContext.Workers.FirstOrDefault(x => x.FIO == fio && !x.IsDeleted)));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public WorkerDataModel? GetElementByEmail(string email)
{
try
{
return
_mapper.Map<WorkerDataModel>(AddPost(_dbContext.Workers.FirstOrDefault(x => x.Email == email && !x.IsDeleted)));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void AddElement(WorkerDataModel workerDataModel)
{
try
{
_dbContext.Workers.Add(_mapper.Map<Worker>(workerDataModel));
_dbContext.SaveChanges();
}
catch (InvalidOperationException ex) when (ex.TargetSite?.Name ==
"ThrowIdentityConflict")
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", workerDataModel.Id, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "PK_Workers" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", workerDataModel.Id, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void UpdElement(WorkerDataModel workerDataModel)
{
try
{
var element = GetWorkerById(workerDataModel.Id) ?? throw new
ElementNotFoundException(workerDataModel.Id, _localizer);
_dbContext.Workers.Update(_mapper.Map(workerDataModel,
element));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void DelElement(string id)
{
try
{
var element = GetWorkerById(id) ?? throw new
ElementNotFoundException(id, _localizer);
element.IsDeleted = true;
element.DateOfDelete = DateTime.UtcNow;
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
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, _localizer);
}
}
private Worker? GetWorkerById(string id) => AddPost(_dbContext.Workers.FirstOrDefault(x => x.Id == id && !x.IsDeleted));
private IQueryable<Worker> JoinPost(IQueryable<Worker> query) => query.GroupJoin(_dbContext.Posts.Where(x => x.IsActual), x =>
x.PostId, y => y.PostId, (x, y) => new { Worker = x, Post = y })
.SelectMany(xy => xy.Post.DefaultIfEmpty(), (x, y) => x.Worker.AddPost(y));
private Worker? AddPost(Worker? worker) => worker?.AddPost(_dbContext.Posts.FirstOrDefault(x => x.PostId == worker.PostId && x.IsActual));
}

View File

@@ -0,0 +1,295 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using North_Bridge_DataBase;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace North_Bridge_DataBase.Migrations
{
[DbContext(typeof(North_Bridge_DbContext))]
[Migration("20250424162754_FirstMigration")]
partial class FirstMigration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PrevPrevProductName")
.HasColumnType("text");
b.Property<string>("PrevProductName")
.HasColumnType("text");
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("North_Bridge_DataBase.Models.ProductForSale", 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("North_Bridge_DataBase.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("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
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("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Email")
.HasColumnType("text");
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>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductForSale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductsForSale")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("North_Bridge_DataBase.Models.Sale", "Sale")
.WithMany("ProductsForSale")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductHistory", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Salary", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.SetNull)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,225 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace North_Bridge_DataBase.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),
PrevProductName = table.Column<string>(type: "text", nullable: true),
PrevPrevProductName = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", 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),
Email = table.Column<string>(type: "text", nullable: true),
PostId = 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),
WorkerSalary = table.Column<double>(type: "double precision", nullable: false),
SalaryDate = table.Column<DateTime>(type: "timestamp without time zone", 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),
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_Workers_WorkerId",
column: x => x.WorkerId,
principalTable: "Workers",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
});
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_Salaries_WorkerId",
table: "Salaries",
column: "WorkerId");
migrationBuilder.CreateIndex(
name: "IX_SaleProducts_ProductId",
table: "SaleProducts",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Sales_WorkerId",
table: "Sales",
column: "WorkerId");
migrationBuilder.CreateIndex(
name: "IX_Workers_Email",
table: "Workers",
column: "Email",
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: "Workers");
}
}
}

View File

@@ -0,0 +1,296 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using North_Bridge_DataBase;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace North_Bridge_DataBase.Migrations
{
[DbContext(typeof(North_Bridge_DbContext))]
[Migration("20250424185440_ChangeFieldsInPost")]
partial class ChangeFieldsInPost
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PrevPrevProductName")
.HasColumnType("text");
b.Property<string>("PrevProductName")
.HasColumnType("text");
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("North_Bridge_DataBase.Models.ProductForSale", 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("North_Bridge_DataBase.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("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
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("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Worker", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Email")
.HasColumnType("text");
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>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductForSale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductsForSale")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("North_Bridge_DataBase.Models.Sale", "Sale")
.WithMany("ProductsForSale")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductHistory", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Salary", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.SetNull)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.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 North_Bridge_DataBase.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,299 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using North_Bridge_DataBase;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace North_Bridge_DataBase.Migrations
{
[DbContext(typeof(North_Bridge_DbContext))]
[Migration("20250425110414_AddDateOfDeleteInWorker")]
partial class AddDateOfDeleteInWorker
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PrevPrevProductName")
.HasColumnType("text");
b.Property<string>("PrevProductName")
.HasColumnType("text");
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("North_Bridge_DataBase.Models.ProductForSale", 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("North_Bridge_DataBase.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("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
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("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("North_Bridge_DataBase.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<string>("Email")
.HasColumnType("text");
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>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductForSale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductsForSale")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("North_Bridge_DataBase.Models.Sale", "Sale")
.WithMany("ProductsForSale")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductHistory", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Salary", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.SetNull)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.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 North_Bridge_DataBase.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,296 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using North_Bridge_DataBase;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace North_Bridge_DataBase.Migrations
{
[DbContext(typeof(North_Bridge_DbContext))]
partial class North_Bridge_DbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PrevPrevProductName")
.HasColumnType("text");
b.Property<string>("PrevProductName")
.HasColumnType("text");
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("North_Bridge_DataBase.Models.ProductForSale", 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("North_Bridge_DataBase.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("North_Bridge_DataBase.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("North_Bridge_DataBase.Models.Sale", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsCancel")
.HasColumnType("boolean");
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("WorkerId");
b.ToTable("Sales");
});
modelBuilder.Entity("North_Bridge_DataBase.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<string>("Email")
.HasColumnType("text");
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>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("Workers");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductForSale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductsForSale")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("North_Bridge_DataBase.Models.Sale", "Sale")
.WithMany("ProductsForSale")
.HasForeignKey("SaleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Sale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.ProductHistory", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Product", "Product")
.WithMany("ProductHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Salary", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Salaries")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.HasOne("North_Bridge_DataBase.Models.Worker", "Worker")
.WithMany("Sales")
.HasForeignKey("WorkerId")
.OnDelete(DeleteBehavior.SetNull)
.IsRequired();
b.Navigation("Worker");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Product", b =>
{
b.Navigation("ProductHistories");
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Sale", b =>
{
b.Navigation("ProductsForSale");
});
modelBuilder.Entity("North_Bridge_DataBase.Models.Worker", b =>
{
b.Navigation("Salaries");
b.Navigation("Sales");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,22 @@

using North_Bridge_Contract.Enums;
using North_Bridge_Contract.Infrastructure.PostConfigurations;
namespace North_Bridge_DataBase.Models;
public class Post
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public required string PostId { get; set; }
public required string PostName { get; set; }
public PostType PostType { get; set; }
public required PostConfiguration Configuration { get; set; }
public bool IsActual { get; set; }
public DateTime ChangeDate { get; set; }
}

View File

@@ -0,0 +1,28 @@

using North_Bridge_Contract.Enums;
using System.ComponentModel.DataAnnotations.Schema;
namespace North_Bridge_DataBase.Models;
public class Product
{
public required string Id { get; set; }
public required string ProductName { get; set; }
public ProductType ProductType { get; set; }
public double Price { get; set; }
public bool IsDeleted { get; set; }
public string? PrevProductName { get; set; }
public string? PrevPrevProductName { get; set; }
[ForeignKey("ProductId")]
public List<ProductForSale>? ProductsForSale { get; set; }
[ForeignKey("ProductId")]
public List<ProductHistory>? ProductHistories { get; set; }
}

View File

@@ -0,0 +1,17 @@

namespace North_Bridge_DataBase.Models;
public class ProductForSale
{
public required string SaleId { get; set; }
public required string ProductId { get; set; }
public int Count { get; set; }
public Sale? Sale { get; set; }
public Product? Product { get; set; }
public double Price { get; set; }
}

View File

@@ -0,0 +1,15 @@

namespace North_Bridge_DataBase.Models;
public class ProductHistory
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public required string ProductId { get; set; }
public double OldPrice { get; set; }
public DateTime ChangeDate { get; set; } = DateTime.UtcNow;
public Product? Product { get; set; }
}

View File

@@ -0,0 +1,15 @@

namespace North_Bridge_DataBase.Models;
public class Salary
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public required string WorkerId { get; set; }
public double WorkerSalary { get; set; }
public DateTime SalaryDate { get; set; }
public Worker? Worker { get; set; }
}

View File

@@ -0,0 +1,22 @@

using System.ComponentModel.DataAnnotations.Schema;
namespace North_Bridge_DataBase.Models;
public class Sale
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public required string WorkerId { get; set; }
public DateTime SaleDate { get; set; }
public double Sum { get; set; }
public bool IsCancel { get; set; }
public Worker? Worker { get; set; }
[ForeignKey("SaleId")]
public List<ProductForSale>? ProductsForSale { get; set; }
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace North_Bridge_DataBase.Models;
public class Worker
{
public required string Id { get; set; }
public required string FIO { get; set; }
public string? Email { get; set; }
public required string PostId { get; set; }
public DateTime BirthDate { get; set; }
public DateTime EmploymentDate { get; set; }
public bool IsDeleted { get; set; }
public DateTime? DateOfDelete { get; set; }
[NotMapped]
public Post? Post { get; set; }
[ForeignKey("WorkerId")]
public List<Salary>? Salaries { get; set; }
[ForeignKey("WorkerId")]
public List<Sale>? Sales { get; set; }
public Worker AddPost(Post? post)
{
Post = post;
return this;
}
}

View File

@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="North_Bridge_Tests" />
<InternalsVisibleTo Include="North_Bridge_WebApi" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\North_Bridge_Contract\North_Bridge_Contract.csproj" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More