7 Commits
lab-6 ... lab-8

Author SHA1 Message Date
62b4ea6378 add 2025-05-23 02:07:39 +04:00
7ebeed213a lab-8 ready 2025-05-23 02:06:42 +04:00
866b990167 commit 2025-05-23 00:54:06 +04:00
e7fdf6e526 mb push 2025-04-25 10:36:53 +04:00
b331b2f885 Big fix 2025-04-25 10:36:24 +04:00
b03e6322c0 wip trash for 2025-04-25 09:04:29 +04:00
76c62c737f wip zheny neeed fix Expected: String containing "Не найден элемент по данным"
But was:  "AdapterMessageElementNotFoundByIdException"
2025-04-25 04:28:07 +04:00
226 changed files with 8547 additions and 5632 deletions

View File

@@ -1,23 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="CandyHouseTests" />
<InternalsVisibleTo Include="CandyHouseWebApi" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" />
<PackageReference Include="PDFsharp-MigraDoc" Version="6.2.0-preview-3" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\CandyHouseContracts\CandyHouseContracts.csproj" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="CandyHouseTests" />
<InternalsVisibleTo Include="CandyHouseWebApi" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<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>
<ProjectReference Include="..\CandyHouseContracts\CandyHouseContracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,23 +1,26 @@
using System.Text.Json;
using System.Text.RegularExpressions;
using CandyHouseContracts.BuisnessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Text.RegularExpressions;
namespace CandyHouseBusinessLogic.Implementations;
public class ClientBusinessLogicContract(IClientStorageContract clientStorageContract, ILogger logger) : IClientBusinessLogicContract
internal class ClientBusinessLogicContract(IClientStorageContract clientStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IClientBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IClientStorageContract _clientStorageContract = clientStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<ClientDataModel> GetAllClients()
{
_logger.LogInformation("GetAllClients");
return _clientStorageContract.GetList() ?? throw new NullListException();
return _clientStorageContract.GetList();
}
public ClientDataModel GetClientByData(string data)
@@ -29,20 +32,24 @@ public class ClientBusinessLogicContract(IClientStorageContract clientStorageCon
}
if (data.IsGuid())
{
return _clientStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _clientStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
if (Regex.IsMatch(data, @"^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$"))
{
return _clientStorageContract.GetElementByPhoneNumber(data) ?? throw new ElementNotFoundException(data);
return _clientStorageContract.GetElementByPhoneNumber(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _clientStorageContract.GetElementByFIO(data) ?? throw new ElementNotFoundException(data);
if (Regex.IsMatch(data, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"))
{
return _clientStorageContract.GetElementByEmail(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _clientStorageContract.GetElementByFIO(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertClient(ClientDataModel clientDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(clientDataModel));
ArgumentNullException.ThrowIfNull(clientDataModel);
clientDataModel.Validate();
clientDataModel.Validate(_localizer);
_clientStorageContract.AddElement(clientDataModel);
}
@@ -50,7 +57,7 @@ public class ClientBusinessLogicContract(IClientStorageContract clientStorageCon
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(clientDataModel));
ArgumentNullException.ThrowIfNull(clientDataModel);
clientDataModel.Validate();
clientDataModel.Validate(_localizer);
_clientStorageContract.UpdElement(clientDataModel);
}
@@ -63,8 +70,8 @@ public class ClientBusinessLogicContract(IClientStorageContract clientStorageCon
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_clientStorageContract.DelElement(id);
}
}
}

View File

@@ -0,0 +1,141 @@
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.Infrastructure.ClientConfigurations;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
namespace CandyHouseBusinessLogic.Implementations;
internal class ClientDiscountBusinessLogicContract(IClientDiscountStorageContract clientDiscountStorageContract,
ISaleStorageContract saleStorageContract, IClientStorageContract clientStorageContract, IStringLocalizer<Messages> localizer, ILogger logger, IConfigurationClientDiscount сonfiguration) : IClientDiscountBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IClientDiscountStorageContract _clientDiscountStorageContract = clientDiscountStorageContract;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly IClientStorageContract _clientStorageContract = clientStorageContract;
private readonly IConfigurationClientDiscount _clientDiscountConfiguration = сonfiguration;
private readonly IStringLocalizer<Messages> _localizer = localizer;
private readonly Lock _lockObject = new();
public List<ClientDiscountDataModel> GetAllClientDiscountsByPeriod(DateTime fromDate, DateTime toDate)
{
_logger.LogInformation("GetAllClientDiscounts params: {fromDate}, {toDate}", fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
return _clientDiscountStorageContract.GetList(fromDate, toDate);
}
public List<ClientDiscountDataModel> GetAllClientDiscountsByPeriodByClient(DateTime fromDate, DateTime toDate, string clientId)
{
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
if (clientId.IsEmpty())
{
throw new ArgumentNullException(nameof(clientId));
}
if (!clientId.IsGuid())
{
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "ClientId"));
}
_logger.LogInformation("GetAllClientDiscounts params: {fromDate}, {toDate}, {clientId}", fromDate, toDate, clientId);
return _clientDiscountStorageContract.GetList(fromDate, toDate, clientId);
}
public void CalculateClientDiscountByMonth(DateTime date)
{
_logger.LogInformation("CalculateClientDiscountByMounth: {date}", date);
var startDate = new DateTime(date.Year, date.Month, 1).ToUniversalTime();
var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month)).ToUniversalTime();
var clients = _clientStorageContract.GetList();
foreach (var client in clients)
{
var sales = _saleStorageContract.GetList(startDate, finishDate, clientId: client.Id);
double discountAmount = client.ConfigurationModel switch
{
null => 0,
SilverClientConfiguration sbc => CalculateClientDiscountForSilverClient(sales, startDate, finishDate, sbc),
GoldenClientConfiguration gbc => CalculateClientDiscountForGoldenClient(sales, startDate, finishDate, gbc),
ClientConfiguration bc => bc.BasicLevel,
};
_logger.LogDebug("The client {clientId} received a discount in the amount {discountAmount}", client.Id, discountAmount);
_clientDiscountStorageContract.AddElement(new ClientDiscountDataModel(client.Id, finishDate, discountAmount));
}
}
private double CalculateClientDiscountForSilverClient(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, SilverClientConfiguration config)
{
var tasks = new List<Task>();
var totalDiscount = 0.0;
var semaphore = new SemaphoreSlim(_clientDiscountConfiguration.MaxParallelThreads);
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
semaphore.Wait();
tasks.Add(Task.Factory.StartNew((object? obj) =>
{
try
{
var dateInTask = (DateTime)obj!;
var salesInDay = sales.Where(x => x.SaleDate >= dateInTask && x.SaleDate <= dateInTask.AddDays(1)).ToArray();
if (salesInDay.Length > 0)
{
lock (_lockObject)
{
totalDiscount += salesInDay.Sum(x => x.Sum) * config.SilverLevel;
}
}
}
finally
{
semaphore.Release();
}
}, date));
}
var calcBonusTask = Task.Run(() =>
{
return sales.Where(x => x.Sum > _clientDiscountConfiguration.ExtraSaleSum).Sum(x => x.Sum) * config.BonusForPurchases;
});
try
{
Task.WaitAll([Task.WhenAll(tasks), calcBonusTask]);
}
catch (AggregateException agEx)
{
foreach (var ex in agEx.InnerExceptions)
{
_logger.LogError(ex, "Error in the SilverClient discount calculation process");
}
return 0;
}
finally
{
semaphore.Dispose();
}
return config.BasicLevel + totalDiscount + calcBonusTask.Result;
}
private double CalculateClientDiscountForGoldenClient(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, GoldenClientConfiguration config)
{
try
{
return config.BasicLevel + config.GoldenLevel * sales.Count;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in GoldenClient discount calculation process");
return 0;
}
}
}

View File

@@ -1,28 +1,25 @@
using CandyHouseContracts.BuisnessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CandyHouseBusinessLogic.Implementations;
public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStorageContract, ILogger logger) : IEmployeeBusinessLogicContract
internal class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IEmployeeBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IEmployeeStorageContract _employeeStorageContract = employeeStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<EmployeeDataModel> GetAllEmployees(bool onlyActive = true)
{
_logger.LogInformation("GetAllEmployees params: {onlyActive}", onlyActive);
return _employeeStorageContract.GetList(onlyActive) ?? throw new NullListException();
return _employeeStorageContract.GetList(onlyActive);
}
public List<EmployeeDataModel> GetAllEmployeesByPost(string postId, bool onlyActive = true)
@@ -34,9 +31,9 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
}
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 _employeeStorageContract.GetList(onlyActive, postId) ?? throw new NullListException();
return _employeeStorageContract.GetList(onlyActive, postId);
}
public List<EmployeeDataModel> GetAllEmployeesByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
@@ -44,9 +41,9 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
_logger.LogInformation("GetAllEmployees params: {onlyActive}, {fromDate}, {toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
return _employeeStorageContract.GetList(onlyActive, fromBirthDate: fromDate, toBirthDate: toDate) ?? throw new NullListException();
return _employeeStorageContract.GetList(onlyActive, fromBirthDate: fromDate, toBirthDate: toDate);
}
public List<EmployeeDataModel> GetAllEmployeesByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
@@ -54,9 +51,9 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
_logger.LogInformation("GetAllEmployees params: {onlyActive}, {fromDate}, {toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
return _employeeStorageContract.GetList(onlyActive, fromEmploymentDate: fromDate, toEmploymentDate: toDate) ?? throw new NullListException();
return _employeeStorageContract.GetList(onlyActive, fromEmploymentDate: fromDate, toEmploymentDate: toDate);
}
public EmployeeDataModel GetEmployeeByData(string data)
@@ -68,20 +65,16 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
}
if (data.IsGuid())
{
return _employeeStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _employeeStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
if (Regex.IsMatch(data, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"))
{
return _employeeStorageContract.GetElementByEmail(data) ?? throw new ElementNotFoundException(data);
}
return _employeeStorageContract.GetElementByFIO(data) ?? throw new ElementNotFoundException(data);
return _employeeStorageContract.GetElementByFIO(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertEmployee(EmployeeDataModel employeeDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(employeeDataModel));
ArgumentNullException.ThrowIfNull(employeeDataModel);
employeeDataModel.Validate();
employeeDataModel.Validate(_localizer);
_employeeStorageContract.AddElement(employeeDataModel);
}
@@ -89,7 +82,7 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(employeeDataModel));
ArgumentNullException.ThrowIfNull(employeeDataModel);
employeeDataModel.Validate();
employeeDataModel.Validate(_localizer);
_employeeStorageContract.UpdElement(employeeDataModel);
}
@@ -102,8 +95,8 @@ public class EmployeeBusinessLogicContract(IEmployeeStorageContract employeeStor
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_employeeStorageContract.DelElement(id);
}
}
}

View File

@@ -0,0 +1,69 @@
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using System.Text.Json;
namespace CandyHouseBusinessLogic.Implementations;
internal class ManufacturerBusinessLogicContract(IManufacturerStorageContract manufacturerStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IManufacturerBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IManufacturerStorageContract _manufacturerStorageContract = manufacturerStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<ManufacturerDataModel> GetAllManufacturers()
{
_logger.LogInformation("GetAllManufacturers");
return _manufacturerStorageContract.GetList();
}
public ManufacturerDataModel GetManufacturerByData(string data)
{
_logger.LogInformation("Get element by data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _manufacturerStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _manufacturerStorageContract.GetElementByName(data) ?? _manufacturerStorageContract.GetElementByOldName(data) ??
throw new ElementNotFoundException(data, _localizer);
}
public void InsertManufacturer(ManufacturerDataModel manufacturerDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(manufacturerDataModel));
ArgumentNullException.ThrowIfNull(manufacturerDataModel);
manufacturerDataModel.Validate(_localizer);
_manufacturerStorageContract.AddElement(manufacturerDataModel);
}
public void UpdateManufacturer(ManufacturerDataModel manufacturerDataModel)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(manufacturerDataModel));
ArgumentNullException.ThrowIfNull(manufacturerDataModel);
manufacturerDataModel.Validate(_localizer);
_manufacturerStorageContract.UpdElement(manufacturerDataModel);
}
public void DeleteManufacturer(string id)
{
_logger.LogInformation("Delete by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_manufacturerStorageContract.DelElement(id);
}
}

View File

@@ -1,25 +1,25 @@
using CandyHouseContracts.BuisnessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CandyHouseBusinessLogic.Implementations;
public class PostBusinessLogicContract(IPostStorageContract postStorageContract, ILogger logger) : IPostBusinessLogicContract
internal class PostBusinessLogicContract(IPostStorageContract postStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IPostBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<PostDataModel> GetAllPosts()
{
_logger.LogInformation("GetAllPosts");
return _postStorageContract.GetList() ?? throw new NullListException();
return _postStorageContract.GetList();
}
public List<PostDataModel> GetAllDataOfPost(string postId)
@@ -31,9 +31,9 @@ public class PostBusinessLogicContract(IPostStorageContract postStorageContract,
}
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 _postStorageContract.GetPostWithHistory(postId) ?? throw new NullListException();
return _postStorageContract.GetPostWithHistory(postId);
}
public PostDataModel GetPostByData(string data)
@@ -45,16 +45,16 @@ public class PostBusinessLogicContract(IPostStorageContract postStorageContract,
}
if (data.IsGuid())
{
return _postStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _postStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _postStorageContract.GetElementByName(data) ?? throw new ElementNotFoundException(data);
return _postStorageContract.GetElementByName(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertPost(PostDataModel postDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(postDataModel));
ArgumentNullException.ThrowIfNull(postDataModel);
postDataModel.Validate();
postDataModel.Validate(_localizer);
_postStorageContract.AddElement(postDataModel);
}
@@ -62,7 +62,7 @@ public class PostBusinessLogicContract(IPostStorageContract postStorageContract,
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(postDataModel));
ArgumentNullException.ThrowIfNull(postDataModel);
postDataModel.Validate();
postDataModel.Validate(_localizer);
_postStorageContract.UpdElement(postDataModel);
}
@@ -75,7 +75,7 @@ public class PostBusinessLogicContract(IPostStorageContract postStorageContract,
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_postStorageContract.DelElement(id);
}
@@ -89,8 +89,8 @@ public class PostBusinessLogicContract(IPostStorageContract postStorageContract,
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_postStorageContract.ResElement(id);
}
}
}

View File

@@ -1,27 +1,39 @@
using CandyHouseContracts.BuisnessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using CandyHouseContracts.BusinessLogicContracts;
namespace CandyHouseBusinessLogic.Implementations;
public class ProductBusinessLogicContract(IProductStorageContract productStorageContract, ILogger logger) : IProductBusinessLogicContract
internal class ProductBusinessLogicContract(IProductStorageContract productStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IProductBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IProductStorageContract _productStorageContract = productStorageContract;
public List<ProductDataModel> GetAllProducts()
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<ProductDataModel> GetAllProducts(bool onlyActive)
{
_logger.LogInformation("GetAllProducts");
return _productStorageContract.GetList() ?? throw new NullListException();
_logger.LogInformation("GetAllProducts params: {onlyActive}", onlyActive);
return _productStorageContract.GetList(onlyActive);
}
public List<ProductDataModel> GetAllProductsByManufacturer(string manufacturerId, bool onlyActive = true)
{
if (manufacturerId.IsEmpty())
{
throw new ArgumentNullException(nameof(manufacturerId));
}
if (!manufacturerId.IsGuid())
{
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "ManufacturerId"));
}
_logger.LogInformation("GetAllProducts params: {manufacturerId}, {onlyActive}", manufacturerId, onlyActive);
return _productStorageContract.GetList(onlyActive, manufacturerId);
}
public List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId)
@@ -33,9 +45,9 @@ public class ProductBusinessLogicContract(IProductStorageContract productStorage
}
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 _productStorageContract.GetHistoryByProductId(productId) ?? throw new NullListException();
return _productStorageContract.GetHistoryByProductId(productId);
}
public ProductDataModel GetProductByData(string data)
@@ -47,16 +59,16 @@ public class ProductBusinessLogicContract(IProductStorageContract productStorage
}
if (data.IsGuid())
{
return _productStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _productStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _productStorageContract.GetElementByName(data) ?? throw new ElementNotFoundException(data);
return _productStorageContract.GetElementByName(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertProduct(ProductDataModel productDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate();
productDataModel.Validate(_localizer);
_productStorageContract.AddElement(productDataModel);
}
@@ -64,7 +76,7 @@ public class ProductBusinessLogicContract(IProductStorageContract productStorage
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate();
productDataModel.Validate(_localizer);
_productStorageContract.UpdElement(productDataModel);
}
@@ -77,8 +89,8 @@ public class ProductBusinessLogicContract(IProductStorageContract productStorage
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_productStorageContract.DelElement(id);
}
}
}

View File

@@ -1,95 +1,81 @@
using CandyHouseBusinessLogic.OfficePackage;
using CandyHouseContracts.BusinessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseBusinessLogic.OfficePackage;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
namespace CandyHouseBusinessLogic.Implementations;
internal class ReportContract(
IProductStorageContract productStorageContract,
ISaleStorageContract saleStorageContract,
IClientDiscountStorageContract clientDiscountStorageContract,
BaseWordBuilder baseWordBuilder,
BaseExcelBuilder baseExcelBuilder,
BasePdfBuilder basePdfBuilder,
ILogger logger) : IReportContract
internal class ReportContract : IReportContract
{
private readonly IProductStorageContract _productStorageContract = productStorageContract;
private readonly IProductStorageContract _productStorageContract;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly ISaleStorageContract _saleStorageContract;
private readonly IClientDiscountStorageContract _clientDiscountStorageContract = clientDiscountStorageContract;
private readonly IClientDiscountStorageContract _clientDiscountStorageContract;
private readonly BaseWordBuilder _baseWordBuilder = baseWordBuilder;
private readonly BaseWordBuilder _baseWordBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder = baseExcelBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder;
private readonly BasePdfBuilder _basePdfBuilder = basePdfBuilder;
private readonly BasePdfBuilder _basePdfBuilder;
private readonly ILogger _logger = logger;
private readonly IStringLocalizer<Messages> _localizer;
internal static readonly string[] documentHeader = ["Продукт", "Цена", "Дата"];
private readonly ILogger _logger;
internal static readonly string[] tableHeader = ["Дата", "Сумма", "Скидка", "Продавец", "Товар", "Кол-во"];
internal readonly string[] _documentHeader;
internal readonly string[] _tableHeader;
public ReportContract(IProductStorageContract productStorageContract, ISaleStorageContract saleStorageContract, IClientDiscountStorageContract clientDiscountStorageContract, BaseWordBuilder baseWordBuilder, BaseExcelBuilder baseExcelBuilder, BasePdfBuilder basePdfBuilder, IStringLocalizer<Messages> localizer, ILogger logger)
{
_productStorageContract = productStorageContract;
_saleStorageContract = saleStorageContract;
_clientDiscountStorageContract = clientDiscountStorageContract;
_baseWordBuilder = baseWordBuilder;
_baseExcelBuilder = baseExcelBuilder;
_basePdfBuilder = basePdfBuilder;
_localizer = localizer;
_logger = logger;
_documentHeader = [_localizer["DocumentDocCaptionProduct"], _localizer["DocumentDocCaptionPrice"], _localizer["DocumentDocCaptionDate"]];
_tableHeader = [_localizer["DocumentExcelCaptionDate"], _localizer["DocumentExcelCaptionSum"],
_localizer["DocumentExcelCaptionDiscount"], _localizer["DocumentExcelCaptionEmployee"], _localizer["DocumentExcelCaptionProduct"], _localizer["DocumentExcelCaptionCount"]];
}
public async Task<Stream> CreateDocumentProductHistoryPricesAsync(CancellationToken ct)
{
_logger.LogInformation("Create report ProductHistoryPrices");
var data = await GetDataByHistoryPricesAsync(ct);
return _baseWordBuilder
.AddHeader("История цен на продукцию")
.AddParagraph($"Сформировано на дату {DateTime.UtcNow}")
.AddTable([3000, 5000, 4000],
[
.. new List<string[]>() { documentHeader }.Union([
.. data.SelectMany(x =>
(new List<string[]>() { new string[] { x.ProductName, "", "" } }).Union(x.Prices.Select(y =>
new string[] { "", y.Split(" (")[0], y.Split(" (")[1].TrimEnd(')') })))
])
])
.AddHeader(_localizer["DocumentDocHeader"])
.AddParagraph(string.Format(_localizer["DocumentDocSubHeader"], DateTime.Now))
.AddTable([3000, 5000, 4000], [.. new List<string[]>() { _documentHeader }.Union([.. data.SelectMany(x => (new List<string[]>() { new string[] { x.ProductName, "", "" } }).Union(x.Prices.Select(y => new string[] { "", y.Split(" (")[0], y.Split(" (")[1].TrimEnd(')') })))])])
.Build();
}
public async Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish,
CancellationToken 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 data = await GetDataBySalesAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
return _baseExcelBuilder
.AddHeader("Продажи за период", 0, 6)
.AddParagraph($"c {dateStart.ToShortDateString()} по {dateFinish.ToShortDateString()}", 2)
.AddTable([10, 10, 10, 10, 10, 10],
[
.. new List<string[]>() { tableHeader }.Union(data.SelectMany(x =>
(new List<string[]>()
{
new string[]
{
x.SaleDate.ToShortDateString(), x.Sum.ToString("N2"), x.Discount.ToString("N2"),
x.EmployeeFIO, "", ""
}
}).Union(x.Products!.Select(y => new string[]
{ "", "", "", "", y.ProductName, y.Count.ToString("N2") })).ToArray())).Union([
["Всего", data.Sum(x => x.Sum).ToString("N2"), data.Sum(x => x.Discount).ToString("N2"), "", "", ""]
])
])
.AddHeader(_localizer["DocumentExcelHeader"], 0, 6)
.AddParagraph(string.Format(_localizer["DocumentExcelSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()), 2)
.AddTable([10, 10, 10, 10, 10, 10], [.. new List<string[]>() { _tableHeader }.Union(data.SelectMany(x => (new List<string[]>() { new string[] { x.SaleDate.ToShortDateString(), x.Sum.ToString("N2"), x.Discount.ToString("N2"), x.EmployeeFIO, "", "" } }).Union(x.Products!.Select(y => new string[] { "", "", "", "", y.ProductName, y.Count.ToString("N2") })).ToArray())).Union([["Всего", data.Sum(x => x.Sum).ToString("N2"), data.Sum(x => x.Discount).ToString("N2"), "", "", ""]])])
.Build();
}
public async Task<Stream> CreateDocumentClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish,
CancellationToken ct)
public async Task<Stream> CreateDocumentClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Create report ClientDiscountByPeriod from {dateStart} to {dateFinish}", dateStart,
dateFinish);
var data = await GetDataByClientDiscountAsync(dateStart, dateFinish, ct) ??
throw new InvalidOperationException("No found data");
_logger.LogInformation("Create report ClientDiscountByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
var data = await GetDataByClientDiscountAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
return _basePdfBuilder
.AddHeader("Скидочная ведомость")
.AddParagraph($"за период с {dateStart.ToShortDateString()} по {dateFinish.ToShortDateString()}")
.AddHeader(_localizer["DocumentPdfHeader"])
.AddParagraph(string.Format(_localizer["DocumentPdfSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()))
.AddPieChart("Начисления", [.. data.Select(x => (x.ClientFIO, x.TotalDiscount))])
.Build();
}
@@ -100,66 +86,36 @@ internal class ReportContract(
return GetDataByHistoryPricesAsync(ct);
}
public Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish,
CancellationToken ct)
public Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Get data SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
return GetDataBySalesAsync(dateStart, dateFinish, ct);
}
public Task<List<ClientDiscountByPeriodDataModel>> GetDataClientDiscountByPeriodAsync(DateTime dateStart,
DateTime dateFinish, CancellationToken ct)
public Task<List<ClientDiscountByPeriodDataModel>> GetDataClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
_logger.LogInformation("Get data ClientDiscountByPeriod from {dateStart} to {dateFinish}", dateStart,
dateFinish);
_logger.LogInformation("Get data ClientDiscountByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
return GetDataByClientDiscountAsync(dateStart, dateFinish, ct);
}
private async Task<List<ProductHistoryPricesDataModel>> GetDataByHistoryPricesAsync(CancellationToken ct) =>
[
.. (await _productStorageContract.GetListAsync(ct))
.Select(async product => new
{
ProductName = product.ProductName,
History = await Task.Run(() => _productStorageContract.GetHistoryByProductId(product.Id))
}).Select(t => t.Result).Select(x => new ProductHistoryPricesDataModel
{
ProductName = x.ProductName,
Prices =
[
.. x.History.OrderByDescending(h => h.ChangeDate)
.Select(h => $"{h.OldPrice:N2} ({h.ChangeDate:dd.MM.yyyy})")
]
})
];
private async Task<List<ProductHistoryPricesDataModel>> GetDataByHistoryPricesAsync(CancellationToken ct) => [.. (await _productStorageContract.GetListAsync(ct)).
Select(async product => new { ProductName = product.ProductName, History = await Task.Run(() => _productStorageContract.GetHistoryByProductId(product.Id))}).Select(t => t.Result).Select(x => new ProductHistoryPricesDataModel{ ProductName = x.ProductName, Prices = [.. x.History.OrderByDescending(h => h.ChangeDate).Select(h => $"{h.OldPrice:N2} ({h.ChangeDate:dd.MM.yyyy})")] })];
private async Task<List<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish,
CancellationToken ct)
private async Task<List<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish);
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
return [.. (await _saleStorageContract.GetListAsync(dateStart, dateFinish, ct)).OrderBy(x => x.SaleDate)];
}
private async Task<List<ClientDiscountByPeriodDataModel>> GetDataByClientDiscountAsync(DateTime dateStart,
DateTime dateFinish, CancellationToken ct)
private async Task<List<ClientDiscountByPeriodDataModel>> GetDataByClientDiscountAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish);
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
return
[
.. (await _clientDiscountStorageContract.GetListAsync(dateStart, dateFinish, ct)).GroupBy(x => x.ClientFIO)
.Select(x => new ClientDiscountByPeriodDataModel
{
ClientFIO = x.Key, TotalDiscount = x.Sum(y => y.DiscountAmount),
FromPeriod = x.Min(y => y.DiscountDate), ToPeriod = x.Max(y => y.DiscountDate)
}).OrderBy(x => x.ClientFIO)
];
return [.. (await _clientDiscountStorageContract.GetListAsync(dateStart, dateFinish, ct)).GroupBy(x => x.ClientFIO).Select(x => new ClientDiscountByPeriodDataModel { ClientFIO = x.Key, TotalDiscount = x.Sum(y => y.DiscountAmount), FromPeriod = x.Min(y => y.DiscountDate), ToPeriod = x.Max(y => y.DiscountDate) }).OrderBy(x => x.ClientFIO)];
}
}

View File

@@ -1,124 +0,0 @@
using CandyHouseContracts.BuisnessLogicContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.Infrastructure.PostConfigurations;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseBusinessLogic.Implementations;
public class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract,ISaleStorageContract saleStorageContract,
IPostStorageContract postStorageContract, IEmployeeStorageContract employeeStorageContract, ILogger logger, IConfigurationSalary сonfiguration) : ISalaryBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly IEmployeeStorageContract _employeeStorageContract = employeeStorageContract;
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
private readonly Lock _lockObject = new();
public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate)
{
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}", fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
return _salaryStorageContract.GetList(fromDate, toDate) ?? throw new NullListException();
}
public List<SalaryDataModel> GetAllSalariesByPeriodByEmployee(DateTime fromDate, DateTime toDate, string employeeId)
{
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
if (employeeId.IsEmpty())
{
throw new ArgumentNullException(nameof(employeeId));
}
if (!employeeId.IsGuid())
{
throw new ValidationException("The value in the field employeeId is not a unique identifier.");
}
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, {employeeId}", fromDate, toDate, employeeId);
return _salaryStorageContract.GetList(fromDate, toDate, employeeId) ?? throw new NullListException();
}
public void CalculateSalaryByMounth(DateTime date)
{
_logger.LogInformation("CalculateSalaryByMounth: {date}", date);
var startDate = new DateTime(date.Year, date.Month, 1);
var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
var employees = _employeeStorageContract.GetList() ?? throw new NullListException();
foreach (var employee in employees)
{
var sales = _saleStorageContract.GetList(startDate, finishDate, employeeId: employee.Id) ?? throw new NullListException();
var post = _postStorageContract.GetElementById(employee.PostId) ?? throw new NullListException();
var salary = post.ConfigurationModel switch
{
null => 0,
ManagerPostConfiguration cpc => CalculateSalaryForSuperManager(sales, startDate, finishDate, cpc),
BakerPostConfiguration spc => CalculateSalaryForChief(startDate, finishDate, spc),
PostConfiguration pc => pc.Rate,
};
_logger.LogDebug("The employee {employeeId} was paid a salary of {salary}", employee.Id, salary);
_salaryStorageContract.AddElement(new SalaryDataModel(employee.Id, finishDate, salary));
}
}
private double CalculateSalaryForSuperManager(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, ManagerPostConfiguration config)
{
var calcPercent = 0.0;
var dates = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
dates.Add(date);
}
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = _salaryConfiguration.MaxConcurrentThreads
};
Parallel.ForEach(dates, parallelOptions, date =>
{
var salesInDay = sales.Where(x => x.SaleDate.Date == date.Date).ToArray();
if (salesInDay.Length > 0)
{
lock (_lockObject)
{
calcPercent += (salesInDay.Sum(x => x.Sum) / salesInDay.Length) * config.SalePercent;
}
}
});
double calcBonusTask = 0;
try
{
calcBonusTask = sales.Where(x => x.Sum > _salaryConfiguration.ExtraSaleSum).Sum(x => x.Sum) * config.BonusForExtraSales;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in bonus calculation");
}
return config.Rate + calcPercent + calcBonusTask;
}
private double CalculateSalaryForChief(DateTime startDate, DateTime finishDate, BakerPostConfiguration config)
{
try
{
return config.Rate + config.PersonalCountTrendPremium * _employeeStorageContract.GetEmployeeTrend(startDate, finishDate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in the chief payroll process");
return 0;
}
}
}

View File

@@ -1,31 +1,29 @@
using CandyHouseContracts.BuisnessLogicContracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using CandyHouseContracts.BusinessLogicsContracts;
using CandyHouseContracts.DataModels;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Resources;
using CandyHouseContracts.StoragesContracts;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CandyHouseBusinessLogic.Implementations;
public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract, ILogger logger) : ISaleBusinessLogicContract
internal class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : ISaleBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate)
{
_logger.LogInformation("GetAllSales params: {fromDate}, {toDate}", fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
return _saleStorageContract.GetList(fromDate, toDate) ?? throw new NullListException();
return _saleStorageContract.GetList(fromDate, toDate);
}
public List<SaleDataModel> GetAllSalesByEmployeeByPeriod(string employeeId, DateTime fromDate, DateTime toDate)
@@ -33,7 +31,7 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
_logger.LogInformation("GetAllSales params: {employeeId}, {fromDate}, {toDate}", employeeId, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
if (employeeId.IsEmpty())
{
@@ -41,9 +39,9 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
}
if (!employeeId.IsGuid())
{
throw new ValidationException("The value in the field employeeId is not a unique identifier.");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
}
return _saleStorageContract.GetList(fromDate, toDate, employeeId: employeeId) ?? throw new NullListException();
return _saleStorageContract.GetList(fromDate, toDate, employeeId: employeeId);
}
public List<SaleDataModel> GetAllSalesByClientByPeriod(string clientId, DateTime fromDate, DateTime toDate)
@@ -51,7 +49,7 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
_logger.LogInformation("GetAllSales params: {clientId}, {fromDate}, {toDate}", clientId, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
if (clientId.IsEmpty())
{
@@ -59,9 +57,9 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
}
if (!clientId.IsGuid())
{
throw new ValidationException("The value in the field clientId is not a unique identifier.");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "ClientId"));
}
return _saleStorageContract.GetList(fromDate, toDate, clientId: clientId) ?? throw new NullListException();
return _saleStorageContract.GetList(fromDate, toDate, clientId: clientId);
}
public List<SaleDataModel> GetAllSalesByProductByPeriod(string productId, DateTime fromDate, DateTime toDate)
@@ -69,7 +67,7 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
_logger.LogInformation("GetAllSales params: {productId}, {fromDate}, {toDate}", productId, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
if (productId.IsEmpty())
{
@@ -77,9 +75,9 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
}
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)
@@ -91,16 +89,16 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
}
if (!data.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
return _saleStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _saleStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertSale(SaleDataModel saleDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(saleDataModel));
ArgumentNullException.ThrowIfNull(saleDataModel);
saleDataModel.Validate();
saleDataModel.Validate(_localizer);
_saleStorageContract.AddElement(saleDataModel);
}
@@ -113,8 +111,8 @@ public class SaleBusinessLogicContract(ISaleStorageContract saleStorageContract,
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
}
_saleStorageContract.DelElement(id);
}
}
}

View File

@@ -1,5 +1,4 @@
using CandyHouseBusinessLogic.OfficePackage;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;
@@ -19,4 +14,4 @@ public interface IClientAdapter
ClientOperationResponse ChangeClientInfo(ClientBindingModel clientModel);
ClientOperationResponse RemoveClient(string id);
}
}

View File

@@ -0,0 +1,12 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
namespace CandyHouseContracts.AdapterContracts;
public interface IClientDiscountAdapter
{
ClientDiscountOperationResponse GetListByPeriod(DateTime fromDate, DateTime toDate);
ClientDiscountOperationResponse GetListByPeriodByClient(DateTime fromDate, DateTime toDate, string clientId);
ClientDiscountOperationResponse CalculateClientDiscount(DateTime date);
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;
@@ -25,4 +20,4 @@ public interface IEmployeeAdapter
EmployeeOperationResponse ChangeEmployeeInfo(EmployeeBindingModel employeeModel);
EmployeeOperationResponse RemoveEmployee(string id);
}
}

View File

@@ -0,0 +1,17 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.AdapterContracts;
public interface IManufacturerAdapter
{
ManufacturerOperationResponse GetList();
ManufacturerOperationResponse GetElement(string data);
ManufacturerOperationResponse RegisterManufacturer(ManufacturerBindingModel manufacturerModel);
ManufacturerOperationResponse ChangeManufacturerInfo(ManufacturerBindingModel manufacturerModel);
ManufacturerOperationResponse RemoveManufacturer(string id);
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;
@@ -23,4 +18,4 @@ public interface IPostAdapter
PostOperationResponse RemovePost(string id);
PostOperationResponse RestorePost(string id);
}
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;
@@ -12,6 +7,8 @@ public interface IProductAdapter
{
ProductOperationResponse GetList(bool includeDeleted);
ProductOperationResponse GetManufacturerList(string id, bool includeDeleted);
ProductOperationResponse GetHistory(string id);
ProductOperationResponse GetElement(string data);
@@ -21,4 +18,4 @@ public interface IProductAdapter
ProductOperationResponse ChangeProductInfo(ProductBindingModel productModel);
ProductOperationResponse RemoveProduct(string id);
}
}

View File

@@ -1,15 +0,0 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;
public interface ISalaryAdapter
{
SalaryOperationResponse GetListByPeriod(DateTime fromDate, DateTime toDate);
SalaryOperationResponse GetListByPeriodByEmployee(DateTime fromDate, DateTime toDate, string employeeId);
SalaryOperationResponse CalculateSalary(DateTime date);
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.AdapterContracts.OperationResponses;
using CandyHouseContracts.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts;

View File

@@ -0,0 +1,17 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
public class ClientDiscountOperationResponse : OperationResponse
{
public static ClientDiscountOperationResponse OK(List<ClientDiscountViewModel> data) => OK<ClientDiscountOperationResponse, List<ClientDiscountViewModel>>(data);
public static ClientDiscountOperationResponse NoContent() => NoContent<ClientDiscountOperationResponse>();
public static ClientDiscountOperationResponse NotFound(string message) => NotFound<ClientDiscountOperationResponse>(message);
public static ClientDiscountOperationResponse BadRequest(string message) => BadRequest<ClientDiscountOperationResponse>(message);
public static ClientDiscountOperationResponse InternalServerError(string message) => InternalServerError<ClientDiscountOperationResponse>(message);
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
@@ -21,4 +16,4 @@ public class ClientOperationResponse : OperationResponse
public static ClientOperationResponse NotFound(string message) => NotFound<ClientOperationResponse>(message);
public static ClientOperationResponse InternalServerError(string message) => InternalServerError<ClientOperationResponse>(message);
}
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
@@ -21,4 +16,4 @@ public class EmployeeOperationResponse : OperationResponse
public static EmployeeOperationResponse BadRequest(string message) => BadRequest<EmployeeOperationResponse>(message);
public static EmployeeOperationResponse InternalServerError(string message) => InternalServerError<EmployeeOperationResponse>(message);
}
}

View File

@@ -0,0 +1,19 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
public class ManufacturerOperationResponse : OperationResponse
{
public static ManufacturerOperationResponse OK(List<ManufacturerViewModel> data) => OK<ManufacturerOperationResponse, List<ManufacturerViewModel>>(data);
public static ManufacturerOperationResponse OK(ManufacturerViewModel data) => OK<ManufacturerOperationResponse, ManufacturerViewModel>(data);
public static ManufacturerOperationResponse NoContent() => NoContent<ManufacturerOperationResponse>();
public static ManufacturerOperationResponse NotFound(string message) => NotFound<ManufacturerOperationResponse>(message);
public static ManufacturerOperationResponse BadRequest(string message) => BadRequest<ManufacturerOperationResponse>(message);
public static ManufacturerOperationResponse InternalServerError(string message) => InternalServerError<ManufacturerOperationResponse>(message);
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
@@ -21,4 +16,4 @@ public class PostOperationResponse : OperationResponse
public static PostOperationResponse BadRequest(string message) => BadRequest<PostOperationResponse>(message);
public static PostOperationResponse InternalServerError(string message) => InternalServerError<PostOperationResponse>(message);
}
}

View File

@@ -1,10 +1,5 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
@@ -23,4 +18,4 @@ public class ProductOperationResponse : OperationResponse
public static ProductOperationResponse BadRequest(string message) => BadRequest<ProductOperationResponse>(message);
public static ProductOperationResponse InternalServerError(string message) => InternalServerError<ProductOperationResponse>(message);
}
}

View File

@@ -1,18 +0,0 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.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

@@ -1,10 +1,5 @@
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
@@ -21,4 +16,4 @@ public class SaleOperationResponse : OperationResponse
public static SaleOperationResponse BadRequest(string message) => BadRequest<SaleOperationResponse>(message);
public static SaleOperationResponse InternalServerError(string message) => InternalServerError<SaleOperationResponse>(message);
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class ClientBindingModel
{
@@ -14,5 +8,7 @@ public class ClientBindingModel
public string? PhoneNumber { get; set; }
public double DiscountSize { get; set; }
public string? Email { get; set; }
public string? ConfigurationJson { get; set; }
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class EmployeeBindingModel
{
@@ -12,11 +6,9 @@ public class EmployeeBindingModel
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

@@ -0,0 +1,8 @@
namespace CandyHouseContracts.BindingModels;
public class ManufacturerBindingModel
{
public string? Id { get; set; }
public string? ManufacturerName { get; set; }
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class PostBindingModel
{
@@ -15,5 +9,6 @@ public class PostBindingModel
public string? PostName { get; set; }
public string? PostType { get; set; }
public string? ConfigurationJson { get; set; }
public double Salary { get; set; }
}

View File

@@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class ProductBindingModel
{
public string? Id { get; set; }
public string? ProductName { get; set; }
public string? ProductDescription { get; set; }
public double Price { get; set; }
public string? ProductType { get; set; }
}
public string? ManufacturerId { get; set; }
public double Price { get; set; }
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class SaleBindingModel
{
@@ -17,4 +11,4 @@ public class SaleBindingModel
public int DiscountType { get; set; }
public List<SaleProductBindingModel>? Products { get; set; }
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BindingModels;
namespace CandyHouseContracts.BindingModels;
public class SaleProductBindingModel
{
@@ -15,4 +9,4 @@ public class SaleProductBindingModel
public int Count { get; set; }
public double Price { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BuisnessLogicContracts;
public interface ISalaryBusinessLogicContract
{
List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate);
List<SalaryDataModel> GetAllSalariesByPeriodByEmployee(DateTime fromDate, DateTime toDate, string employeeId);
void CalculateSalaryByMounth(DateTime date);
}

View File

@@ -1,13 +1,8 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BuisnessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface IClientBusinessLogicContract
internal interface IClientBusinessLogicContract
{
List<ClientDataModel> GetAllClients();
@@ -18,4 +13,4 @@ public interface IClientBusinessLogicContract
void UpdateClient(ClientDataModel clientDataModel);
void DeleteClient(string id);
}
}

View File

@@ -0,0 +1,12 @@
using CandyHouseContracts.DataModels;
namespace CandyHouseContracts.BusinessLogicsContracts;
internal interface IClientDiscountBusinessLogicContract
{
List<ClientDiscountDataModel> GetAllClientDiscountsByPeriod(DateTime fromDate, DateTime toDate);
List<ClientDiscountDataModel> GetAllClientDiscountsByPeriodByClient(DateTime fromDate, DateTime toDate, string clientId);
void CalculateClientDiscountByMonth(DateTime date);
}

View File

@@ -1,17 +1,12 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BuisnessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface IEmployeeBusinessLogicContract
internal interface IEmployeeBusinessLogicContract
{
List<EmployeeDataModel> GetAllEmployees(bool onlyActive = true);
List<EmployeeDataModel> GetAllEmployeesByPost(string employeeId, bool onlyActive = true);
List<EmployeeDataModel> GetAllEmployeesByPost(string postId, bool onlyActive = true);
List<EmployeeDataModel> GetAllEmployeesByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true);
@@ -24,4 +19,4 @@ public interface IEmployeeBusinessLogicContract
void UpdateEmployee(EmployeeDataModel employeeDataModel);
void DeleteEmployee(string id);
}
}

View File

@@ -0,0 +1,16 @@
using CandyHouseContracts.DataModels;
namespace CandyHouseContracts.BusinessLogicsContracts;
internal interface IManufacturerBusinessLogicContract
{
List<ManufacturerDataModel> GetAllManufacturers();
ManufacturerDataModel GetManufacturerByData(string data);
void InsertManufacturer(ManufacturerDataModel manufacturerDataModel);
void UpdateManufacturer(ManufacturerDataModel manufacturerDataModel);
void DeleteManufacturer(string id);
}

View File

@@ -1,13 +1,8 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BuisnessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface IPostBusinessLogicContract
internal interface IPostBusinessLogicContract
{
List<PostDataModel> GetAllPosts();
@@ -22,4 +17,4 @@ public interface IPostBusinessLogicContract
void DeletePost(string id);
void RestorePost(string id);
}
}

View File

@@ -1,10 +1,12 @@
using CandyHouseContracts.DataModels;
namespace CandyHouseContracts.BusinessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface IProductBusinessLogicContract
internal interface IProductBusinessLogicContract
{
List<ProductDataModel> GetAllProducts();
List<ProductDataModel> GetAllProducts(bool onlyActive = true);
List<ProductDataModel> GetAllProductsByManufacturer(string manufacturerId, bool onlyActive = true);
List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId);
@@ -15,4 +17,4 @@ public interface IProductBusinessLogicContract
void UpdateProduct(ProductDataModel productDataModel);
void DeleteProduct(string id);
}
}

View File

@@ -1,9 +1,8 @@
using CandyHouseContracts.DataModels;
namespace CandyHouseContracts.BusinessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface IReportContract
internal interface IReportContract
{
Task<List<ProductHistoryPricesDataModel>> GetDataProductHistoryPricesAsync(CancellationToken ct);

View File

@@ -1,13 +1,8 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.BuisnessLogicContracts;
namespace CandyHouseContracts.BusinessLogicsContracts;
public interface ISaleBusinessLogicContract
internal interface ISaleBusinessLogicContract
{
List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate);
@@ -22,4 +17,4 @@ public interface ISaleBusinessLogicContract
void InsertSale(SaleDataModel saleDataModel);
void CancelSale(string id);
}
}

View File

@@ -1,15 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Messages.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Messages.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="CandyHouseBusinessLogic" />
<InternalsVisibleTo Include="CandyHouseDatabase" />
<InternalsVisibleTo Include="CandyHouseWebApi" />
<InternalsVisibleTo Include="CandyHouseTests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\Messages.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Messages.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -1,42 +1,75 @@
using CandyHouseContracts.Extensions;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using CandyHouseContracts.Infrastructure.ClientConfigurations;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ValidationException = CandyHouseContracts.Exceptions.ValidationException;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
using CandyHouseContracts.Mapper;
namespace CandyHouseContracts.DataModels;
public class ClientDataModel(string id, string fIO, string phoneNumber, double discountSize) : IValidation
internal class ClientDataModel(string id, string fio, string phoneNumber, string email, ClientConfiguration configuration) : IValidation
{
public string Id { get; private set; } = id;
public string FIO { get; private set; } = fIO;
public string FIO { get; private set; } = fio;
public string PhoneNumber { get; private set; } = phoneNumber;
public double DiscountSize { get; private set; } = discountSize;
public string Email { get; private set; } = email;
public void Validate()
[AlternativeName("ConfigurationJson")]
[AlternativeName("Configuration")]
[PostProcessing(MappingCallMethodName = "ParseJson")]
public ClientConfiguration ConfigurationModel { get; private set; } = configuration;
public ClientDataModel() : this(string.Empty, string.Empty, string.Empty, string.Empty, null) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
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())
throw new ValidationException("Field FIO is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "FIO"));
if (PhoneNumber.IsEmpty())
throw new ValidationException("Field PhoneNumber is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PhoneNumber"));
if (!Regex.IsMatch(PhoneNumber, @"^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$"))
throw new ValidationException("Field PhoneNumber is not a phone number");
throw new ValidationException(localizer["ValidationExceptionMessageIncorrectPhoneNumber"]);
if (Email.IsEmpty())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Email"));
if (!Regex.IsMatch(Email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"))
throw new ValidationException(localizer["ValidationExceptionMessageIncorrectEmail"]);
if (ConfigurationModel is null)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotInitialized"], "ConfigurationModel"));
if (ConfigurationModel!.BasicLevel <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "BasicLevel"));
}
}
private ClientConfiguration? ParseJson(string json)
{
var obj = JToken.Parse(json);
if (obj is not null)
{
return obj.Value<string>("Type") switch
{
nameof(SilverClientConfiguration) => JsonConvert.DeserializeObject<SilverClientConfiguration>(json)!,
nameof(GoldenClientConfiguration) => JsonConvert.DeserializeObject<GoldenClientConfiguration>(json)!,
_ => JsonConvert.DeserializeObject<ClientConfiguration>(json)!,
};
}
return null;
}
}

View File

@@ -1,16 +1,18 @@
using CandyHouseContracts.Exceptions;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class ClientDiscountDataModel(string clientId, DateTime discountDate, double discountAmount) : IValidation
internal class ClientDiscountDataModel(string clientId, DateTime discountDate, double discountAmount) : IValidation
{
private readonly ClientDataModel? _client;
public string ClientId { get; private set; } = clientId;
public DateTime DiscountDate { get; private set; } = discountDate;
public DateTime DiscountDate { get; private set; } = discountDate.ToUniversalTime();
public double DiscountAmount { get; private set; } = discountAmount;
@@ -21,15 +23,17 @@ public class ClientDiscountDataModel(string clientId, DateTime discountDate, dou
_client = client;
}
public void Validate()
public ClientDiscountDataModel() : this(string.Empty, DateTime.UtcNow, 0) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (ClientId.IsEmpty())
throw new ValidationException("Field ClientId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "EmployeeId"));
if (!ClientId.IsGuid())
throw new ValidationException("The value in the field ClientId is not a unique identifier");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
if (DiscountAmount < 0)
throw new ValidationException("Field DiscountAmount in the field is less than 0");
if (DiscountAmount <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "DiscountAmount"));
}
}

View File

@@ -1,12 +1,12 @@
using CandyHouseContracts.Exceptions;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System.Text.RegularExpressions;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class EmployeeDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
internal class EmployeeDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
{
private readonly PostDataModel? _post;
@@ -14,57 +14,51 @@ public class EmployeeDataModel(string id, string fio, string email, string postI
public string FIO { get; private set; } = fio;
public string Email { get; private set; } = email;
public string PostId { get; private set; } = postId;
public DateTime BirthDate { get; private set; } = birthDate;
public DateTime BirthDate { get; private set; } = birthDate.ToUniversalTime();
public DateTime EmploymentDate { get; private set; } = employmentDate;
public DateTime EmploymentDate { get; private set; } = employmentDate.ToUniversalTime();
public bool IsDeleted { get; private set; } = isDeleted;
public string PostName => _post?.PostName ?? string.Empty;
public EmployeeDataModel(string id, string fio, string email, string postId, DateTime birthDate, DateTime employmentDate,
bool isDeleted, PostDataModel post) : this(id, fio, email, postId, birthDate, employmentDate, isDeleted)
public EmployeeDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted, PostDataModel post) : this(id, fio, postId, birthDate, employmentDate, isDeleted)
{
_post = post;
}
public EmployeeDataModel(string id, string fio, string email, string postId, DateTime birthDate,
DateTime employmentDate) : this(id, fio, email, postId, birthDate, employmentDate, false) { }
public EmployeeDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate) : this(id, fio, postId, birthDate, employmentDate, false) { }
public void Validate()
public EmployeeDataModel() : this(string.Empty, string.Empty, string.Empty, DateTime.UtcNow, DateTime.UtcNow) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
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())
throw new ValidationException("Field FIO is empty");
if (Email.IsEmpty())
throw new ValidationException("Field Email is empty");
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(string.Format(localizer["ValidationExceptionMessageEmptyField"], "FIO"));
if (PostId.IsEmpty())
throw new ValidationException("Field PostId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostId"));
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.UtcNow.AddYears(-18).Date)
throw new ValidationException($"Only adults can be hired (BirthDate = {BirthDate.ToShortDateString()})");
if (BirthDate.Date > DateTime.Now.AddYears(-16).Date)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageMinorsBirthDate"], BirthDate.ToShortDateString()));
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)
throw new ValidationException($"Only adults can be hired (EmploymentDate - {EmploymentDate.ToShortDateString()}, BirthDate - {BirthDate.ToShortDateString()})");
if ((EmploymentDate - BirthDate).TotalDays / 365 < 16)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageMinorsEmploymentDate"],
EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
}
}
}

View File

@@ -0,0 +1,34 @@
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
internal class ManufacturerDataModel(string id, string manufacturerName, string? prevManufacturerName, string? prevPrevManufacturerName) : IValidation
{
public string Id { get; private set; } = id;
public string ManufacturerName { get; private set; } = manufacturerName;
public string? PrevManufacturerName { get; private set; } = prevManufacturerName;
public string? PrevPrevManufacturerName { get; private set; } = prevPrevManufacturerName;
public ManufacturerDataModel() : this(string.Empty, string.Empty, null, null) { }
public ManufacturerDataModel(string id, string manufacturerName) : this(id, manufacturerName, null, null) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "Id"));
if (ManufacturerName.IsEmpty())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ManufacturerName"));
}
}

View File

@@ -1,53 +1,41 @@
using CandyHouseContracts.Enums;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Enums;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using CandyHouseContracts.Infrastructure.PostConfigurations;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CandyHouseContracts.Mapper;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class PostDataModel(string postId, string postName, PostType postType, PostConfiguration configuration) : IValidation
internal class PostDataModel(string postId, string postName, PostType postType, double salary) : IValidation
{
[AlternativeName("PostId")]
public string Id { get; private set; } = postId;
public string PostName { get; private set; } = postName;
public PostType PostType { get; private set; } = postType;
public PostConfiguration ConfigurationModel { get; private set; } = configuration;
public PostDataModel(string postId, string postName, PostType postType, string configurationJson) : this(postId, postName, postType, (PostConfiguration)null)
{
var obj = JToken.Parse(configurationJson);
if (obj is not null)
{
ConfigurationModel = obj.Value<string>("Type") switch
{
nameof(ManagerPostConfiguration) => JsonConvert.DeserializeObject<ManagerPostConfiguration>(configurationJson)!,
nameof(BakerPostConfiguration) => JsonConvert.DeserializeObject<BakerPostConfiguration>(configurationJson)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(configurationJson)!,
};
}
}
public double Salary { get; private set; } = salary;
public void Validate()
public PostDataModel() : this(string.Empty, string.Empty, PostType.None, 0) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
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())
throw new ValidationException("Field PostName is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostName"));
if (PostType == PostType.None)
throw new ValidationException("Field PostType is empty");
if (ConfigurationModel is null)
throw new ValidationException("Field ConfigurationModel is not initialized");
if (ConfigurationModel!.Rate <= 0)
throw new ValidationException("Field Rate is less or equal zero");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostType"));
if (Salary <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Salary"));
}
}
}

View File

@@ -1,38 +1,60 @@
using CandyHouseContracts.Enums;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Enums;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class ProductDataModel(string id, string productName, string productDescription, double price, ProductType productType) : IValidation
internal class ProductDataModel(string id, string productName, ProductType productType, string manufacturerId, double price, bool isDeleted) : IValidation
{
private readonly ManufacturerDataModel? _manufacturer;
public string Id { get; private set; } = id;
public string ProductName { get; private set; } = productName;
public string ProductDescription { get; private set; } = productDescription;
public double Price { get; private set; } = price;
public ProductType ProductType { get; private set; } = productType;
public void Validate()
public string ManufacturerId { get; private set; } = manufacturerId;
public double Price { get; private set; } = price;
public bool IsDeleted { get; private set; } = isDeleted;
public string ManufacturerName => _manufacturer?.ManufacturerName ?? string.Empty;
public ProductDataModel(string id, string productName, ProductType productType, string manufacturerId, double price, bool isDeleted, ManufacturerDataModel manufacturer) : this(id, productName, productType, manufacturerId, price, isDeleted)
{
_manufacturer = manufacturer;
}
public ProductDataModel(string id, string productName, ProductType productType, string manufacturerId, double price) : this(id, productName, productType, manufacturerId, price, false) { }
public ProductDataModel() : this(string.Empty, string.Empty, ProductType.None, string.Empty, 0, false) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
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())
throw new ValidationException("Field ProductName is empty");
if (ProductDescription.IsEmpty())
throw new ValidationException("Field ProductDescription is empty");
if (Price <= 0)
throw new ValidationException("Field Price is less than or equal to 0");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductName"));
if (ProductType == ProductType.None)
throw new ValidationException("Field Type is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductType"));
if (ManufacturerId.IsEmpty())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ManufacturerId"));
if (!ManufacturerId.IsGuid())
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ManufacturerId"));
if (Price <= 0)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Price"));
}
}
}

View File

@@ -1,15 +1,12 @@
using CandyHouseContracts.Exceptions;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class ProductHistoryDataModel(string productId, double oldPrice) : IValidation
internal class ProductHistoryDataModel(string productId, double oldPrice) : IValidation
{
private readonly ProductDataModel? _product;
@@ -27,15 +24,17 @@ public class ProductHistoryDataModel(string productId, double oldPrice) : IValid
_product = product;
}
public void Validate()
public ProductHistoryDataModel() : this(string.Empty, 0, DateTime.UtcNow, null) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (ProductId.IsEmpty())
throw new ValidationException("Field ProductId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductId"));
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)
throw new ValidationException("Field OldPrice is less than or equal to 0");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "OldPrice"));
}
}
}

View File

@@ -1,39 +0,0 @@
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.DataModels;
public class SalaryDataModel(string employeeId, DateTime salaryDate, double employeeSalary) : IValidation
{
private readonly EmployeeDataModel? _employee;
public string EmployeeId { get; private set; } = employeeId;
public DateTime SalaryDate { get; private set; } = salaryDate;
public double Salary { get; private set; } = employeeSalary;
public string EmployeeFIO => _employee?.FIO ?? string.Empty;
public SalaryDataModel(string employeeId, DateTime salaryDate, double employeeSalary, EmployeeDataModel employee) : this(employeeId, salaryDate, employeeSalary)
{
_employee = employee;
}
public void Validate()
{
if (EmployeeId.IsEmpty())
throw new ValidationException("Field EmployeeId is empty");
if (!EmployeeId.IsGuid())
throw new ValidationException("The value in the field EmployeeId is not a unique identifier");
if (Salary <= 0)
throw new ValidationException("Field Salary is less than or equal to 0");
}
}

View File

@@ -1,16 +1,13 @@
using CandyHouseContracts.Enums;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Enums;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class SaleDataModel : IValidation
internal class SaleDataModel : IValidation
{
private readonly ClientDataModel? _client;
@@ -32,7 +29,7 @@ public class SaleDataModel : IValidation
public bool IsCancel { get; private set; }
public List<SaleProductDataModel>? Products { get; private set; }
public List<SaleProductDataModel> Products { get; private set; }
public string ClientFIO => _client?.FIO ?? string.Empty;
@@ -71,8 +68,7 @@ public class SaleDataModel : IValidation
Discount = Sum * percent;
}
public SaleDataModel(string id, string employeeId, string? clientId, double sum, DiscountType discountType, double discount, bool isCancel,
List<SaleProductDataModel> saleProducts, EmployeeDataModel employee, ClientDataModel? client) : this(id, employeeId, clientId, discountType, isCancel, saleProducts)
public SaleDataModel(string id, string employeeId, string? clientId, double sum, DiscountType discountType, double discount, bool isCancel, List<SaleProductDataModel> saleProducts, EmployeeDataModel employee, ClientDataModel? client) : this(id, employeeId, clientId, discountType, isCancel, saleProducts)
{
Sum = sum;
Discount = discount;
@@ -80,30 +76,36 @@ public class SaleDataModel : IValidation
_client = client;
}
public SaleDataModel(string id, string employeeId, string? clientId, int discountType,
List<SaleProductDataModel> products) : this(id, employeeId, clientId, (DiscountType)discountType, false, products) { }
public SaleDataModel(string id, string employeeId, string? clientId, int discountType, List<SaleProductDataModel> products) : this(id, employeeId, clientId, (DiscountType)discountType, false, products) { }
public void Validate()
public SaleDataModel() : this(string.Empty, string.Empty, null, DiscountType.None, false, new List<SaleProductDataModel>()) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "Id"));
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 (EmployeeId.IsEmpty())
throw new ValidationException("Field EmployeeId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "EmployeeId"));
if (!EmployeeId.IsGuid())
throw new ValidationException("The value in the field EmployeeId is not a unique identifier");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
if (!ClientId?.IsGuid() ?? !ClientId?.IsEmpty() ?? false)
throw new ValidationException("The value in the field EmploeerId is not a unique identifier");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ClientId"));
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)
throw new ValidationException("The sale must include products");
if (Products is null)
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotInitialized"], "Products"));
if (Products.Count == 0)
throw new ValidationException(localizer["ValidationExceptionMessageNoProductsInSale"]);
Products.ForEach(x => x.Validate(localizer));
}
}
}

View File

@@ -1,16 +1,12 @@
using CandyHouseContracts.Exceptions;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Exceptions;
using CandyHouseContracts.Extensions;
using CandyHouseContracts.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.DataModels;
public class SaleProductDataModel(string saleId, string productId, int count, double price) : IValidation
internal class SaleProductDataModel(string saleId, string productId, int count, double price) : IValidation
{
private readonly ProductDataModel? _product;
@@ -29,24 +25,26 @@ public class SaleProductDataModel(string saleId, string productId, int count, do
_product = product;
}
public void Validate()
public SaleProductDataModel() : this(string.Empty, string.Empty, 0, 0) { }
public void Validate(IStringLocalizer<Messages> localizer)
{
if (SaleId.IsEmpty())
throw new ValidationException("Field SaleId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "SaleId"));
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())
throw new ValidationException("Field ProductId is empty");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "IProductIdd"));
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)
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("Field Price is less than or equal to 0");
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Price"));
}
}
}

View File

@@ -1,10 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Enums;
namespace CandyHouseContracts.Enums;
[Flags]
public enum DiscountType
{
@@ -12,4 +7,4 @@ public enum DiscountType
OnSale = 1,
RegularCustomer = 2,
Certificate = 4
}
}

View File

@@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Enums;
namespace CandyHouseContracts.Enums;
public enum PostType
{
None = 0,
Manager = 1,
SuperManager = 2,
Baker = 3,
}
Baker = 3
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Enums;
namespace CandyHouseContracts.Enums;
public enum ProductType
{
@@ -12,4 +6,6 @@ public enum ProductType
Candy = 1,
Cake = 2,
Chocolate = 3,
}
Marmalade = 4,
Lollipop = 5
}

View File

@@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Exceptions;
public class ElementDeletedException : Exception
{
public ElementDeletedException(string id) : base($"Cannot modify a deleted item (id: {id})") { }
}
internal class ElementDeletedException(string id, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementDeletedExceptionMessage"], id))
{ }

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Exceptions;
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 ElementExistsException(string paramName, string paramValue) : base($"There is already an element with value{paramValue} of parameter {paramName}")
{
ParamName = paramName;
ParamValue = paramValue;
}
}
public string ParamValue { get; private set; } = paramValue;
}

View File

@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Exceptions;
public class ElementNotFoundException : Exception
{
public string Value { get; private set; }
public ElementNotFoundException(string value) : base($"Element not found at value = {value}")
{
Value = value;
}
}

View File

@@ -0,0 +1,10 @@
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Exceptions;
internal class ElementNotFoundException(string value, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementNotFoundExceptionMessage"], value))
{
public string Value { get; private set; } = value;
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Exceptions;
public class IncorrectDatesException : Exception
{
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

@@ -0,0 +1,8 @@
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Exceptions;
internal class IncorrectDatesException(DateTime start, DateTime end, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["IncorrectDatesExceptionMessage"], start.ToShortDateString(), end.ToShortDateString()))
{ }

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Exceptions;
public class NullListException : Exception
{
public NullListException() : base("The returned list is null") { }
}

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Exceptions;
public class StorageException : Exception
{
public StorageException(Exception ex) : base($"Error while working in storage: {ex.Message}", ex) { }
}

View File

@@ -0,0 +1,8 @@
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Exceptions;
internal class StorageException(Exception ex, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["StorageExceptionMessage"], ex.Message), ex)
{ }

View File

@@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Exceptions;
namespace CandyHouseContracts.Exceptions;
public class ValidationException(string message) : Exception(message)
{
}
{ }

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Extensions;
namespace CandyHouseContracts.Extensions;
public static class DateTimeExtensions
{
@@ -12,4 +6,4 @@ public static class DateTimeExtensions
{
return date >= olderDate;
}
}
}

View File

@@ -1,13 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Extensions;
namespace CandyHouseContracts.Extensions;
public static class StringExtensions
{
public static bool IsEmpty(this string str) => string.IsNullOrWhiteSpace(str);
public static bool IsGuid(this string str) => Guid.TryParse(str, out _);
}
public static bool IsEmpty(this string str)
{
return string.IsNullOrWhiteSpace(str);
}
public static bool IsGuid(this string str)
{
return Guid.TryParse(str, out _);
}
}

View File

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

View File

@@ -0,0 +1,10 @@
using CandyHouseContracts.Infrastructure.ClientConfigurations;
namespace CandyHouseContracts.Infrastructure.ClientConfigurations;
public class GoldenClientConfiguration : ClientConfiguration
{
public override string Type => nameof(GoldenClientConfiguration);
public double GoldenLevel { get; set; }
}

View File

@@ -0,0 +1,12 @@
using CandyHouseContracts.Infrastructure.ClientConfigurations;
namespace CandyHouseContracts.Infrastructure.ClientConfigurations;
public class SilverClientConfiguration : ClientConfiguration
{
public override string Type => nameof(SilverClientConfiguration);
public double SilverLevel { get; set; }
public double BonusForPurchases { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace CandyHouseContracts.Infrastructure;
public interface IConfigurationClientDiscount
{
int MaxParallelThreads { get; }
double ExtraSaleSum { get; }
}

View File

@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Infrastructure;
namespace CandyHouseContracts.Infrastructure;
public interface IConfigurationDatabase
{
string ConnectionString { get; }
}
}

View File

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

View File

@@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using CandyHouseContracts.Resources;
namespace CandyHouseContracts.Infrastructure;
public interface IValidation
internal interface IValidation
{
void Validate();
}
void Validate(IStringLocalizer<Messages> localizer);
}

View File

@@ -1,11 +1,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.Infrastructure;
@@ -14,7 +9,7 @@ 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)
@@ -28,7 +23,6 @@ public class OperationResponse
{
return new StatusCodeResult((int)StatusCode);
}
if (Result is Stream stream)
{
return new FileStreamResult(stream, "application/octet-stream")
@@ -36,24 +30,19 @@ public class OperationResponse
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) 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 NoContent<TResult>() where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.NoContent };
protected static TResult NotFound<TResult>(string? errorMessage = null) where TResult : OperationResponse,
new() => new() { StatusCode = HttpStatusCode.NotFound, Result = errorMessage };
protected static TResult BadRequest<TResult>(string? errorMessage = null) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.BadRequest, Result = errorMessage };
protected static TResult InternalServerError<TResult>(string? errorMessage = null) where TResult : OperationResponse,
new() => new() { StatusCode = HttpStatusCode.InternalServerError, 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

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

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
namespace CandyHouseContracts.Mapper;
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
class AlternativeNameAttribute(string alternativeName) : Attribute
{
public string AlternativeName { get; set; } = alternativeName;
}

View File

@@ -0,0 +1,157 @@
using CandyHouseContracts.Exceptions;
using System.Collections;
using System.Reflection;
namespace CandyHouseContracts.Mapper;
internal static class CustomMapper
{
public static To MapObject<To>(object obj, To newObject)
{
ArgumentNullException.ThrowIfNull(obj);
ArgumentNullException.ThrowIfNull(newObject);
var typeFrom = obj.GetType();
var typeTo = typeof(To);
var propertiesFrom = typeFrom.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var property in typeTo.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p => p.CanWrite && p.GetCustomAttribute<IgnoreAttribute>() == null))
{
var defaultValueAttr = property.GetCustomAttribute<DefaultValueAttribute>();
if (defaultValueAttr != null)
{
FindAndMapDefaultValue(property, newObject);
continue;
}
var propertyFrom = TryGetPropertyFrom(property, propertiesFrom);
object? fromValue = null;
if (propertyFrom != null)
{
fromValue = propertyFrom.GetValue(obj);
if (property.PropertyType.IsGenericType && property.PropertyType.Name.StartsWith("List") && fromValue is not null)
{
fromValue = MapListOfObjects(property, fromValue);
}
var postProcessing = property.GetCustomAttribute<PostProcessingAttribute>();
if ((postProcessing is not null && (fromValue is string || postProcessing.MappingCallMethodName == "ParseConfiguration")))
{
fromValue = PostProcess(fromValue, postProcessing, newObject);
}
fromValue = HandleEnumConversion(property.PropertyType, propertyFrom.PropertyType, fromValue);
if (fromValue is not null)
{
property.SetValue(newObject, fromValue);
}
}
}
var classPostProcessing = typeTo.GetCustomAttribute<PostProcessingAttribute>();
if (classPostProcessing?.MappingCallMethodName is not null)
{
var methodInfo = typeTo.GetMethod(classPostProcessing.MappingCallMethodName, BindingFlags.NonPublic | BindingFlags.Instance);
methodInfo?.Invoke(newObject, []);
}
return newObject;
}
public static To MapObject<To>(object obj)
=> MapObject(obj, Activator.CreateInstance<To>());
public static To? MapObjectWithNull<To>(object? obj)
=> obj is null ? default : MapObject(obj, Activator.CreateInstance<To>()!);
private static PropertyInfo? TryGetPropertyFrom(PropertyInfo targetProp, PropertyInfo[] sourceProps)
{
var altAttr = targetProp.GetCustomAttributes<AlternativeNameAttribute>().FirstOrDefault(a => sourceProps.Any(p => p.Name == a.AlternativeName));
if (altAttr != null)
{
return sourceProps.FirstOrDefault(p => p.Name == altAttr.AlternativeName);
}
return sourceProps.FirstOrDefault(p => p.Name == targetProp.Name);
}
private static object? PostProcess<T>(object? value, PostProcessingAttribute attr, T instance)
{
if (value == null || instance == null) return null;
if (!string.IsNullOrWhiteSpace(attr.MappingCallMethodName))
{
var method = instance.GetType().GetMethod(attr.MappingCallMethodName, BindingFlags.NonPublic | BindingFlags.Instance);
return method?.Invoke(instance, [value]);
}
return attr.ActionType switch
{
PostProcessingType.ToUniversalTime => value is DateTime dt ? dt.ToUniversalTime() : value,
PostProcessingType.ToLocalTime => value is DateTime dt ? dt.ToLocalTime() : value,
_ => value
};
}
private static object? MapListOfObjects(PropertyInfo targetProp, object sourceList)
{
var targetList = Activator.CreateInstance(targetProp.PropertyType);
var itemType = targetProp.PropertyType.GetGenericArguments()[0];
foreach (var item in (IEnumerable)sourceList)
{
var genericMethod = typeof(CustomMapper).GetMethod(nameof(MapObject), 1, new[] { typeof(object) })!;
var constructed = genericMethod.MakeGenericMethod(itemType);
var mapped = constructed.Invoke(null, new[] { item });
targetProp.PropertyType.GetMethod("Add")?.Invoke(targetList, [mapped]);
}
return targetList;
}
private static object? HandleEnumConversion(Type targetType, Type sourceType, object? value)
{
if (value == null) return null;
if (targetType.IsEnum)
{
if (string.IsNullOrEmpty(value.ToString()))
throw new ValidationException($"Value cannot be empty for enum {targetType.Name}");
if (Enum.TryParse(targetType, value.ToString(), true, out var result))
return result;
throw new ValidationException($"Invalid value '{value}' for enum {targetType.Name}");
}
if (!targetType.IsEnum && sourceType.IsEnum)
return value.ToString();
return value;
}
private static void FindAndMapDefaultValue<T>(PropertyInfo prop, T obj)
{
var attr = prop.GetCustomAttribute<DefaultValueAttribute>();
if (attr == null) return;
object? val = attr.DefaultValue;
if (val == null)
{
val = attr.FuncName switch
{
DefaultFuncType.UtcNow => DateTime.UtcNow,
_ => null
};
}
if (val != null)
{
prop.SetValue(obj, val);
}
}
}

View File

@@ -0,0 +1,8 @@
namespace CandyHouseContracts.Mapper;
enum DefaultFuncType
{
None = -1,
UtcNow = 1
}

View File

@@ -0,0 +1,9 @@
namespace CandyHouseContracts.Mapper;
[AttributeUsage(AttributeTargets.Property)]
class DefaultValueAttribute : Attribute
{
public object? DefaultValue { get; set; }
public DefaultFuncType FuncName { get; set; } = DefaultFuncType.None;
}

View File

@@ -0,0 +1,6 @@
namespace CandyHouseContracts.Mapper;
[AttributeUsage(AttributeTargets.Property)]
class IgnoreAttribute : Attribute
{
}

View File

@@ -0,0 +1,9 @@
namespace CandyHouseContracts.Mapper;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
class PostProcessingAttribute : Attribute
{
public string? MappingCallMethodName { get; set; }
public PostProcessingType ActionType { get; set; } = PostProcessingType.None;
}

View File

@@ -0,0 +1,10 @@
namespace CandyHouseContracts.Mapper;
enum PostProcessingType
{
None = -1,
ToUniversalTime = 1,
ToLocalTime = 2
}

View File

@@ -0,0 +1,422 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CandyHouseContracts.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[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>
/// Returns the cached ResourceManager instance used by this class.
/// </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("CandyHouseContracts.Resources.Messages", typeof(Messages).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Элемент по данным: {0} был удален.
/// </summary>
internal static string AdapterMessageElementDeletedException {
get {
return ResourceManager.GetString("AdapterMessageElementDeletedException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Не найден элемент по данным: {0}.
/// </summary>
internal static string AdapterMessageElementNotFoundException {
get {
return ResourceManager.GetString("AdapterMessageElementNotFoundException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Данные пусты.
/// </summary>
internal static string AdapterMessageEmptyDate {
get {
return ResourceManager.GetString("AdapterMessageEmptyDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Неправильные даты: {0}.
/// </summary>
internal static string AdapterMessageIncorrectDatesException {
get {
return ResourceManager.GetString("AdapterMessageIncorrectDatesException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ошибка при обработке данных: {0}.
/// </summary>
internal static string AdapterMessageInvalidOperationException {
get {
return ResourceManager.GetString("AdapterMessageInvalidOperationException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ошибка при работе с хранилищем данных: {0}.
/// </summary>
internal static string AdapterMessageStorageException {
get {
return ResourceManager.GetString("AdapterMessageStorageException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Переданы неверные данные: {0}.
/// </summary>
internal static string AdapterMessageValidationException {
get {
return ResourceManager.GetString("AdapterMessageValidationException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Цена.
/// </summary>
internal static string DocumentDocCaptionPrice {
get {
return ResourceManager.GetString("DocumentDocCaptionPrice", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Продукт.
/// </summary>
internal static string DocumentDocCaptionProduct {
get {
return ResourceManager.GetString("DocumentDocCaptionProduct", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to История цен на продукцию.
/// </summary>
internal static string DocumentDocHeader {
get {
return ResourceManager.GetString("DocumentDocHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Сформировано на дату {0}.
/// </summary>
internal static string DocumentDocSubHeader {
get {
return ResourceManager.GetString("DocumentDocSubHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Кол-во.
/// </summary>
internal static string DocumentExcelCaptionCount {
get {
return ResourceManager.GetString("DocumentExcelCaptionCount", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Дата.
/// </summary>
internal static string DocumentExcelCaptionDate {
get {
return ResourceManager.GetString("DocumentExcelCaptionDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Скидка.
/// </summary>
internal static string DocumentExcelCaptionDiscount {
get {
return ResourceManager.GetString("DocumentExcelCaptionDiscount", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Продавец.
/// </summary>
internal static string DocumentExcelCaptionEmployee {
get {
return ResourceManager.GetString("DocumentExcelCaptionEmployee", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Товар.
/// </summary>
internal static string DocumentExcelCaptionProduct {
get {
return ResourceManager.GetString("DocumentExcelCaptionProduct", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Сумма.
/// </summary>
internal static string DocumentExcelCaptionSum {
get {
return ResourceManager.GetString("DocumentExcelCaptionSum", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Всего.
/// </summary>
internal static string DocumentExcelCaptionTotal {
get {
return ResourceManager.GetString("DocumentExcelCaptionTotal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Продажи за период.
/// </summary>
internal static string DocumentExcelHeader {
get {
return ResourceManager.GetString("DocumentExcelHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to c {0} по {1}.
/// </summary>
internal static string DocumentExcelSubHeader {
get {
return ResourceManager.GetString("DocumentExcelSubHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Начисления.
/// </summary>
internal static string DocumentPdfDiagramCaption {
get {
return ResourceManager.GetString("DocumentPdfDiagramCaption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Скидочная ведомость.
/// </summary>
internal static string DocumentPdfHeader {
get {
return ResourceManager.GetString("DocumentPdfHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to за период с {0} по {1}.
/// </summary>
internal static string DocumentPdfSubHeader {
get {
return ResourceManager.GetString("DocumentPdfSubHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Нельзя изменить удаленный элемент (идентификатор: {0}).
/// </summary>
internal static string ElementDeletedExceptionMessage {
get {
return ResourceManager.GetString("ElementDeletedExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Уже существует элемент со значением {0} параметра {1}.
/// </summary>
internal static string ElementExistsExceptionMessage {
get {
return ResourceManager.GetString("ElementExistsExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Элемент не найден по значению = {0}.
/// </summary>
internal static string ElementNotFoundExceptionMessage {
get {
return ResourceManager.GetString("ElementNotFoundExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Дата окончания должна быть позже даты начала. Дата начала: {0}. ​​Дата окончания: {1}.
/// </summary>
internal static string IncorrectDatesExceptionMessage {
get {
return ResourceManager.GetString("IncorrectDatesExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Недостаточно данных для обработки: {0}.
/// </summary>
internal static string NotEnoughDataToProcessExceptionMessage {
get {
return ResourceManager.GetString("NotEnoughDataToProcessExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Не найдены данные.
/// </summary>
internal static string NotFoundDataMessage {
get {
return ResourceManager.GetString("NotFoundDataMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ошибка при работе в хранилище: {0}.
/// </summary>
internal static string StorageExceptionMessage {
get {
return ResourceManager.GetString("StorageExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Дата трудоустройства не может быть раньше даты рождения ({0}, {1}).
/// </summary>
internal static string ValidationExceptionMessageEmploymentDateAndBirthDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmploymentDateAndBirthDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле {0} пусто.
/// </summary>
internal static string ValidationExceptionMessageEmptyField {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmptyField", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле Электронная почта не является электронной почтой.
/// </summary>
internal static string ValidationExceptionMessageIncorrectEmail {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectEmail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле Телефонный номер не является телефонным номером.
/// </summary>
internal static string ValidationExceptionMessageIncorrectPhoneNumber {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectPhoneNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле {0} меньше или равно 0.
/// </summary>
internal static string ValidationExceptionMessageLessOrEqualZero {
get {
return ResourceManager.GetString("ValidationExceptionMessageLessOrEqualZero", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Несовершеннолетние не могут быть приняты на работу (Дата рождения: {0}).
/// </summary>
internal static string ValidationExceptionMessageMinorsBirthDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorsBirthDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Несовершеннолетние не могут быть приняты на работу (Дата трудоустройства {0}, Дата рождения: {1}).
/// </summary>
internal static string ValidationExceptionMessageMinorsEmploymentDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorsEmploymentDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to В продаже должен быть хотя бы один товар.
/// </summary>
internal static string ValidationExceptionMessageNoProductsInSale {
get {
return ResourceManager.GetString("ValidationExceptionMessageNoProductsInSale", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле {0} не является типом уникального идентификатора.
/// </summary>
internal static string ValidationExceptionMessageNotAId {
get {
return ResourceManager.GetString("ValidationExceptionMessageNotAId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Значение в поле {0} не проинициализировано.
/// </summary>
internal static string ValidationExceptionMessageNotInitialized {
get {
return ResourceManager.GetString("ValidationExceptionMessageNotInitialized", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,240 @@
<?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="DocumentDocCaptionProduct" xml:space="preserve">
<value>Produkt</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Die Geschichte der Produktpreise</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="DocumentExcelCaptionDiscount" xml:space="preserve">
<value>Preisnachlaß</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="DocumentPdfHeader" xml:space="preserve">
<value>Rabattliste</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>für den Zeitraum {0} bis {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Anrechnungen</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>Keine Daten gefunden</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>Der Wert im Feld "{0}" ist kein eindeutiger Bezeichnertyp</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Der Wert im Feld "{0}" ist leer</value>
</data>
<data name="ValidationExceptionMessageIncorrectPhoneNumber" xml:space="preserve">
<value>Der Wert im Feld Telefonnummer ist keine Telefonnummer</value>
</data>
<data name="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>Der Wert im Feld "{0}" wurde nicht initialisiert</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>Der Wert im Feld {0} ist kleiner oder gleich 0</value>
</data>
<data name="ValidationExceptionMessageNoProductsInSale" xml:space="preserve">
<value>Es muss mindestens ein Produkt zum Verkauf stehen</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="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>Das Beschäftigungsdatum darf nicht vor dem Geburtsdatum liegen ({0}, {1})</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Fehler beim Arbeiten mit dem Datenspeicher: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>Die Daten sind leer</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Es wurde kein Datenelement gefunden: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Ungültige Daten wurden übergeben: {0}</value>
</data>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>Element nach Daten: {0} wurde gelöscht</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Fehler bei der Datenverarbeitung: {0}</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Falsche Datumsangaben: {0}</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>Es ist bereits ein Element mit dem Wert vorhanden {0} des Parameters {1} </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="StorageExceptionMessage" xml:space="preserve">
<value>Fehler beim Ausführen im Speicher: {0}</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>Der Wert im Feld E-Mail ist keine E-Mail</value>
</data>
<data name="DocumentDocCaptionPrice" xml:space="preserve">
<value>Preis</value>
</data>
<data name="DocumentExcelCaptionEmployee" xml:space="preserve">
<value>Verkäufer</value>
</data>
</root>

View File

@@ -0,0 +1,240 @@
<?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="DocumentDocCaptionProduct" xml:space="preserve">
<value>Product</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Product price history</value>
</data>
<data name="DocumentDocSubHeader" xml:space="preserve">
<value>Generated on date {0}</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Count</value>
</data>
<data name="DocumentExcelCaptionDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="DocumentExcelCaptionDiscount" xml:space="preserve">
<value>Discount</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="DocumentPdfHeader" xml:space="preserve">
<value>Discount statement</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>for the period from {0} to {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>No data found</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>The value in the {0} field is not a unique identifier type.</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>The value in field {0} is empty</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="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>The value in field {0} is not initialized</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>The value in field {0} is less than or equal to 0</value>
</data>
<data name="ValidationExceptionMessageNoProductsInSale" xml:space="preserve">
<value>There must be at least one item on sale</value>
</data>
<data name="ValidationExceptionMessageMinorsBirthDate" xml:space="preserve">
<value>Minors cannot be hired (BirthDate = {0})</value>
</data>
<data name="ValidationExceptionMessageMinorsEmploymentDate" xml:space="preserve">
<value>Minors cannot be hired (EmploymentDate: {0}, BirthDate {1})</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>Date of employment cannot be earlier than date of birth ({0}, {1})</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Error while working with data storage: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>Data is empty</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Not found element by data: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Incorrect data transmitted: {0}</value>
</data>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>Element by data: {0} was deleted</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Error processing data: {0}</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Incorrect dates: {0}</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Cannot modify a deleted item (id: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>There is already an element with value {0} of parameter {1}</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Element not found at value = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>The end date must be later than the start date.. StartDate: {0}. EndDate: {1}</value>
</data>
<data name="NotEnoughDataToProcessExceptionMessage" xml:space="preserve">
<value>Not enough data to process: {0}</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Error while working in storage: {0}</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>The value in the Email field is not a email.</value>
</data>
<data name="DocumentDocCaptionPrice" xml:space="preserve">
<value>Price</value>
</data>
<data name="DocumentExcelCaptionEmployee" xml:space="preserve">
<value>Employee</value>
</data>
</root>

View File

@@ -0,0 +1,240 @@
<?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="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="DocumentExcelCaptionDiscount" 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="DocumentPdfHeader" xml:space="preserve">
<value>Скидочная ведомость</value>
</data>
<data name="DocumentPdfSubHeader" xml:space="preserve">
<value>за период с {0} по {1}</value>
</data>
<data name="DocumentPdfDiagramCaption" xml:space="preserve">
<value>Начисления</value>
</data>
<data name="NotFoundDataMessage" xml:space="preserve">
<value>Не найдены данные</value>
</data>
<data name="ValidationExceptionMessageNotAId" xml:space="preserve">
<value>Значение в поле {0} не является типом уникального идентификатора</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Значение в поле {0} пусто</value>
</data>
<data name="ValidationExceptionMessageIncorrectPhoneNumber" xml:space="preserve">
<value>Значение в поле Телефонный номер не является телефонным номером</value>
</data>
<data name="ValidationExceptionMessageNotInitialized" xml:space="preserve">
<value>Значение в поле {0} не проинициализировано</value>
</data>
<data name="ValidationExceptionMessageLessOrEqualZero" xml:space="preserve">
<value>Значение в поле {0} меньше или равно 0</value>
</data>
<data name="ValidationExceptionMessageNoProductsInSale" xml:space="preserve">
<value>В продаже должен быть хотя бы один товар</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="ValidationExceptionMessageEmploymentDateAndBirthDate" xml:space="preserve">
<value>Дата трудоустройства не может быть раньше даты рождения ({0}, {1})</value>
</data>
<data name="AdapterMessageStorageException" xml:space="preserve">
<value>Ошибка при работе с хранилищем данных: {0}</value>
</data>
<data name="AdapterMessageEmptyDate" xml:space="preserve">
<value>Данные пусты</value>
</data>
<data name="AdapterMessageElementNotFoundException" xml:space="preserve">
<value>Не найден элемент по данным: {0}</value>
</data>
<data name="AdapterMessageValidationException" xml:space="preserve">
<value>Переданы неверные данные: {0}</value>
</data>
<data name="AdapterMessageElementDeletedException" xml:space="preserve">
<value>Элемент по данным: {0} был удален</value>
</data>
<data name="AdapterMessageInvalidOperationException" xml:space="preserve">
<value>Ошибка при обработке данных: {0}</value>
</data>
<data name="AdapterMessageIncorrectDatesException" xml:space="preserve">
<value>Неправильные даты: {0}</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="StorageExceptionMessage" xml:space="preserve">
<value>Ошибка при работе в хранилище: {0}</value>
</data>
<data name="ValidationExceptionMessageIncorrectEmail" xml:space="preserve">
<value>Значение в поле Электронная почта не является электронной почтой</value>
</data>
<data name="DocumentDocCaptionPrice" xml:space="preserve">
<value>Цена</value>
</data>
<data name="DocumentExcelCaptionEmployee" xml:space="preserve">
<value>Продавец</value>
</data>
</root>

View File

@@ -2,7 +2,7 @@
namespace CandyHouseContracts.StoragesContracts;
public interface IClientDiscountStorageContract
internal interface IClientDiscountStorageContract
{
List<ClientDiscountDataModel> GetList(DateTime startDate, DateTime endDate, string? clientId = null);

View File

@@ -1,21 +1,18 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface IClientStorageContract
internal interface IClientStorageContract
{
List<ClientDataModel> GetList();
ClientDataModel? GetElementById(string id);
ClientDataModel? GetElementByFIO(string fio);
ClientDataModel? GetElementByPhoneNumber(string phoneNumber);
ClientDataModel? GetElementByFIO(string fio);
ClientDataModel? GetElementByEmail(string email);
void AddElement(ClientDataModel clientDataModel);

View File

@@ -1,28 +1,18 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface IEmployeeStorageContract
internal interface IEmployeeStorageContract
{
List<EmployeeDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null,
DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null);
List<EmployeeDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null);
EmployeeDataModel? GetElementById(string id);
EmployeeDataModel? GetElementByFIO(string fio);
EmployeeDataModel? GetElementByEmail(string email);
void AddElement(EmployeeDataModel employeeDataModel);
void UpdElement(EmployeeDataModel employeeDataModel);
void DelElement(string id);
int GetEmployeeTrend(DateTime fromPeriod, DateTime toPeriod);
}
}

View File

@@ -0,0 +1,20 @@
using CandyHouseContracts.DataModels;
namespace CandyHouseContracts.StoragesContracts;
internal interface IManufacturerStorageContract
{
List<ManufacturerDataModel> GetList();
ManufacturerDataModel? GetElementById(string id);
ManufacturerDataModel? GetElementByName(string name);
ManufacturerDataModel? GetElementByOldName(string name);
void AddElement(ManufacturerDataModel manufacturerDataModel);
void UpdElement(ManufacturerDataModel manufacturerDataModel);
void DelElement(string id);
}

View File

@@ -1,20 +1,22 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface IPostStorageContract
internal interface IPostStorageContract
{
List<PostDataModel> GetList();
List<PostDataModel> GetPostWithHistory(string postId);
PostDataModel? GetElementById(string id);
PostDataModel? GetElementByName(string name);
void AddElement(PostDataModel postDataModel);
void UpdElement(PostDataModel postDataModel);
void DelElement(string id);
void ResElement(string id);
}
}

View File

@@ -1,20 +1,22 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface IProductStorageContract
internal interface IProductStorageContract
{
List<ProductDataModel> GetList();
List<ProductHistoryDataModel> GetHistoryByProductId(string productId);
ProductDataModel? GetElementById(string id);
ProductDataModel? GetElementByName(string name);
void AddElement(ProductDataModel productDataModel);
void UpdElement(ProductDataModel productDataModel);
void DelElement(string id);
List<ProductDataModel> GetList(bool onlyActive = true, string? manufacturerId = null);
Task<List<ProductDataModel>> GetListAsync(CancellationToken ct);
}
List<ProductHistoryDataModel> GetHistoryByProductId(string productId);
ProductDataModel? GetElementById(string id);
ProductDataModel? GetElementByName(string name);
void AddElement(ProductDataModel productDataModel);
void UpdElement(ProductDataModel productDataModel);
void DelElement(string id);
}

View File

@@ -1,15 +0,0 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface ISalaryStorageContract
{
List<SalaryDataModel> GetList(DateTime? startDate, DateTime? endDate, string? employeeId = null);
void AddElement(SalaryDataModel salaryDataModel);
}

View File

@@ -1,22 +1,16 @@
using CandyHouseContracts.DataModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CandyHouseContracts.StoragesContracts;
public interface ISaleStorageContract
internal interface ISaleStorageContract
{
List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string? employeeId = null,
string? clientId = null, string? productId = null);
List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string? employeeId = null, string? clientId = null, string? productId = null);
Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
SaleDataModel? GetElementById(string id);
void AddElement(SaleDataModel saleDataModel);
void DelElement(string id);
Task<List<SaleDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
}

View File

@@ -0,0 +1,12 @@
namespace CandyHouseContracts.ViewModels;
public class ClientDiscountViewModel
{
public required string ClientId { get; set; }
public required string ClientFIO { get; set; }
public DateTime DiscountDate { get; set; }
public double DiscountAmount { get; set; }
}

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