Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7fdf6e526 | |||
| b331b2f885 | |||
| b03e6322c0 | |||
| 76c62c737f | |||
| 8fa02a428f | |||
| 00a8846f33 | |||
| c692f50d0d | |||
| e7dcfd6f30 | |||
| a3e1230e5c | |||
| 8f5c38d239 | |||
| dbc3fb8394 | |||
| 524bfca4d0 | |||
| 6b7212a13d | |||
| 4113d2ab9e | |||
| d295b50e32 | |||
| f9966ae73d | |||
| d84b3850d6 | |||
| 6449c0df73 | |||
| 7beb84b967 | |||
| 082111e301 | |||
| 14b48e3a30 | |||
| f649754da7 | |||
| cec7b9240e | |||
| d2f7afae63 | |||
| b7c31860e1 | |||
| 79cdd4b5d7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,7 +10,7 @@
|
|||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
*.idea
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
|
|
||||||
@@ -414,3 +414,4 @@ FodyWeavers.xsd
|
|||||||
# Built Visual Studio Code Extensions
|
# Built Visual Studio Code Extensions
|
||||||
*.vsix
|
*.vsix
|
||||||
|
|
||||||
|
/.idea/
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
|
|
||||||
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{5DF70B46-31F7-4D15-8C60-52C0A0A364F0}</ProjectGuid>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>CandyHouseBase</RootNamespace>
|
|
||||||
<AssemblyName>CandyHouseBase</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System"/>
|
|
||||||
<Reference Include="System.Core"/>
|
|
||||||
<Reference Include="System.Data"/>
|
|
||||||
<Reference Include="System.Xml"/>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="DataModels\IngredientDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\OrderDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\PekarDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\PekarHistoryDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\PositionDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\ProductDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\RecipeDataModel.cs" />
|
|
||||||
<Compile Include="DataModels\SalaryDataModel.cs" />
|
|
||||||
<Compile Include="Enums\PositionType.cs" />
|
|
||||||
<Compile Include="Enums\StatusType.cs" />
|
|
||||||
<Compile Include="Exceptions\ValidationException.cs" />
|
|
||||||
<Compile Include="Extensions\StringExtensions.cs" />
|
|
||||||
<Compile Include="Infrastructure\IValidation.cs" />
|
|
||||||
<Compile Include="Program.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class IngredientDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; private set; }
|
|
||||||
public string Name { get; private set; }
|
|
||||||
public string Unit { get; private set; }
|
|
||||||
public decimal Cost { get; private set; }
|
|
||||||
|
|
||||||
public IngredientDataModel(string id, string name, string unit, decimal cost)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Name = name;
|
|
||||||
Unit = unit;
|
|
||||||
Cost = cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (Name.IsEmpty()) throw new ValidationException("Field Name is empty");
|
|
||||||
if (Unit.IsEmpty()) throw new ValidationException("Field Unit is empty");
|
|
||||||
if (Cost < 0) throw new ValidationException("Cost must be non-negative");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using CandyHouseBase.Enums;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class OrderDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; private set; }
|
|
||||||
public string CustomerName { get; private set; } // Может быть null, если клиент разовый
|
|
||||||
public DateTime OrderDate { get; private set; }
|
|
||||||
public decimal TotalAmount { get; private set; }
|
|
||||||
public decimal DiscountAmount { get; private set; }
|
|
||||||
public string OrderId { get; private set; }
|
|
||||||
public string PekarId { get; private set; }
|
|
||||||
public StatusType StatusType { get; private set; }
|
|
||||||
|
|
||||||
public OrderDataModel(string id, string customerName, DateTime orderDate, decimal totalAmount,
|
|
||||||
decimal discountAmount, string orderId, string pekarId, StatusType statusType)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
CustomerName = customerName;
|
|
||||||
OrderDate = orderDate;
|
|
||||||
TotalAmount = totalAmount;
|
|
||||||
DiscountAmount = discountAmount;
|
|
||||||
OrderId = orderId;
|
|
||||||
PekarId = pekarId;
|
|
||||||
StatusType = statusType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (CustomerName.IsEmpty())
|
|
||||||
throw new ValidationException("CustomerName is empty");
|
|
||||||
if (TotalAmount < 0) throw new ValidationException("TotalAmount cannot be negative");
|
|
||||||
if (DiscountAmount < 0) throw new ValidationException("DiscountAmount cannot be negative");
|
|
||||||
if (OrderId.IsEmpty()) throw new ValidationException("Field OrderId is empty");
|
|
||||||
if (!OrderId.IsGuid()) throw new ValidationException("OrderId must be a GUID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class PekarDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; private set; }
|
|
||||||
public string FIO { get; private set; }
|
|
||||||
public string Position { get; private set; }
|
|
||||||
public decimal BonusCoefficient { get; private set; }
|
|
||||||
public List<ProductDataModel> ProductsItems { get; private set; }
|
|
||||||
|
|
||||||
|
|
||||||
public PekarDataModel(string id, string fio, string position, decimal bonusCoefficient,
|
|
||||||
List<ProductDataModel> productsItems)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
FIO = fio;
|
|
||||||
Position = position;
|
|
||||||
BonusCoefficient = bonusCoefficient;
|
|
||||||
ProductsItems = productsItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (FIO.IsEmpty()) throw new ValidationException("Field FIO is empty");
|
|
||||||
var fioPattern = @"^[A-Za-zА-Яа-яЁё\s\-]+$";
|
|
||||||
if (!Regex.IsMatch(FIO, fioPattern))
|
|
||||||
throw new ValidationException("FIO contains invalid characters");
|
|
||||||
|
|
||||||
if (Position.IsEmpty()) throw new ValidationException("Field Position is empty");
|
|
||||||
if (!Position.IsGuid()) throw new ValidationException("Field must be a GUID");
|
|
||||||
if (BonusCoefficient <= 0) throw new ValidationException("BonusCoefficient must be positive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class PekarHistoryDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string PekarId { get; private set; }
|
|
||||||
public string FIO { get; private set; }
|
|
||||||
public string PositionId { get; private set; }
|
|
||||||
public DateTime Date { get; private set; }
|
|
||||||
public decimal BonusCoefficient { get; private set; }
|
|
||||||
|
|
||||||
public PekarHistoryDataModel(string peKarId, string fio, string positionId, decimal bonusCoefficient, DateTime dateTime)
|
|
||||||
{
|
|
||||||
PekarId = peKarId;
|
|
||||||
FIO = fio;
|
|
||||||
PositionId = positionId;
|
|
||||||
BonusCoefficient = bonusCoefficient;
|
|
||||||
Date = dateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (PekarId.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!PekarId.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (FIO.IsEmpty()) throw new ValidationException("Field FIO is empty");
|
|
||||||
if (PositionId.IsEmpty()) throw new ValidationException("Field Position is empty");
|
|
||||||
if (!PositionId.IsGuid()) throw new ValidationException("Field must be a GUID");
|
|
||||||
if (BonusCoefficient <= 0) throw new ValidationException("BonusCoefficient must be positive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using CandyHouseBase.Enums;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class PositionDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; set; }
|
|
||||||
public PositionType Type { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
public PositionDataModel(string id, PositionType type, string title)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Type = type;
|
|
||||||
Title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
var titlePattern = @"^[A-Za-zА-Яа-яЁё\s\-]+$";
|
|
||||||
if (!Regex.IsMatch(Title, titlePattern))
|
|
||||||
throw new ValidationException("FIO contains invalid characters");
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Title)) throw new ValidationException("Field Title is empty");
|
|
||||||
if (!Enum.IsDefined(typeof(PositionType), Type)) throw new ValidationException("Invalid PositionType");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class ProductDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; private set; }
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => name;
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (!name.IsEmpty()) OldName = name;
|
|
||||||
name = value.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Description
|
|
||||||
{
|
|
||||||
get => description;
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (!description.IsEmpty()) OldDescription = description;
|
|
||||||
description = value.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string OldName { get; private set; }
|
|
||||||
|
|
||||||
public string OldDescription { get; private set; }
|
|
||||||
|
|
||||||
private string name;
|
|
||||||
private string description;
|
|
||||||
|
|
||||||
public List<IngredientDataModel> IngredientsItems { get; private set; }
|
|
||||||
|
|
||||||
public ProductDataModel(string id, string name, string description, List<IngredientDataModel> ingredients)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Name = name;
|
|
||||||
Description = description;
|
|
||||||
IngredientsItems = ingredients;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (Name.IsEmpty()) throw new ValidationException("Field Name is empty");
|
|
||||||
if (Description.IsEmpty()) throw new ValidationException("Field Description is empty");
|
|
||||||
if (IngredientsItems.Count == 0) throw new ValidationException("Field IngredientsItems is empty");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class RecipeDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string ProductId { get; private set; }
|
|
||||||
public string IngredientId { get; private set; }
|
|
||||||
public int Quantity { get; private set; }
|
|
||||||
|
|
||||||
public RecipeDataModel(string productId, string ingredientId, int quantity)
|
|
||||||
{
|
|
||||||
ProductId = productId;
|
|
||||||
IngredientId = ingredientId;
|
|
||||||
Quantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (!ProductId.IsGuid()) throw new ValidationException("ProductId must be a GUID");
|
|
||||||
if (!IngredientId.IsGuid()) throw new ValidationException("IngredientId must be a GUID");
|
|
||||||
if (Quantity <= 0) throw new ValidationException("Quantity must be positive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using CandyHouseBase.Exceptions;
|
|
||||||
using CandyHouseBase.Extensions;
|
|
||||||
using CandyHouseBase.Infrastructure;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.DataModels
|
|
||||||
{
|
|
||||||
public class SalaryDataModel : IValidation
|
|
||||||
{
|
|
||||||
public string Id { get; private set; }
|
|
||||||
public string PekarId { get; private set; }
|
|
||||||
public DateTime Period { get; private set; }
|
|
||||||
public decimal BaseRate { get; private set; }
|
|
||||||
public decimal BonusRate { get; private set; }
|
|
||||||
public decimal TotalSalary { get; private set; }
|
|
||||||
|
|
||||||
public SalaryDataModel(string id, string pekarId, DateTime period, decimal baseRate, decimal bonusRate, decimal totalSalary)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
PekarId = pekarId;
|
|
||||||
Period = period;
|
|
||||||
BaseRate = baseRate;
|
|
||||||
BonusRate = bonusRate;
|
|
||||||
TotalSalary = totalSalary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate()
|
|
||||||
{
|
|
||||||
if (Id.IsEmpty()) throw new ValidationException("Field Id is empty");
|
|
||||||
if (!Id.IsGuid()) throw new ValidationException("Id must be a GUID");
|
|
||||||
if (PekarId.IsEmpty()) throw new ValidationException("Field PekarId is empty");
|
|
||||||
if (!PekarId.IsGuid()) throw new ValidationException("PekarId must be a GUID");
|
|
||||||
if (BaseRate < 0) throw new ValidationException("BaseRate cannot be negative");
|
|
||||||
if (BonusRate < 0) throw new ValidationException("BonusRate cannot be negative");
|
|
||||||
if (TotalSalary < 0) throw new ValidationException("TotalSalary cannot be negative");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace CandyHouseBase.Enums
|
|
||||||
{
|
|
||||||
public enum PositionType
|
|
||||||
{
|
|
||||||
None = 1,
|
|
||||||
Small = 2,
|
|
||||||
Medium = 3,
|
|
||||||
Cool = 4,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace CandyHouseBase.Enums
|
|
||||||
{
|
|
||||||
public enum StatusType
|
|
||||||
{
|
|
||||||
Pending,
|
|
||||||
Completed,
|
|
||||||
Cancelled,
|
|
||||||
InProgress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.Exceptions
|
|
||||||
{
|
|
||||||
public class ValidationException : Exception
|
|
||||||
{
|
|
||||||
public ValidationException(string message) : base(message) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace CandyHouseBase.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 _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace CandyHouseBase.Infrastructure
|
|
||||||
{
|
|
||||||
public interface IValidation
|
|
||||||
{
|
|
||||||
void Validate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace CandyHouseBase
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +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.4" />
|
||||||
|
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CandyHouseContracts\CandyHouseContracts.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
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;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace CandyHouseBusinessLogic.Implementations;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientDataModel GetClientByData(string data)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get element by data: {data}", data);
|
||||||
|
if (data.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
if (data.IsGuid())
|
||||||
|
{
|
||||||
|
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, _localizer);
|
||||||
|
}
|
||||||
|
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(_localizer);
|
||||||
|
_clientStorageContract.AddElement(clientDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateClient(ClientDataModel clientDataModel)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(clientDataModel));
|
||||||
|
ArgumentNullException.ThrowIfNull(clientDataModel);
|
||||||
|
clientDataModel.Validate(_localizer);
|
||||||
|
_clientStorageContract.UpdElement(clientDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteClient(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"));
|
||||||
|
}
|
||||||
|
_clientStorageContract.DelElement(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
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 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmployeeDataModel> GetAllEmployeesByPost(string postId, bool onlyActive = true)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllEmployees params: {postId}, {onlyActive},", postId, onlyActive);
|
||||||
|
if (postId.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(postId));
|
||||||
|
}
|
||||||
|
if (!postId.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "PostId"));
|
||||||
|
}
|
||||||
|
return _employeeStorageContract.GetList(onlyActive, postId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmployeeDataModel> GetAllEmployeesByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllEmployees params: {onlyActive}, {fromDate}, {toDate}", onlyActive, fromDate, toDate);
|
||||||
|
if (fromDate.IsDateNotOlder(toDate))
|
||||||
|
{
|
||||||
|
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||||||
|
}
|
||||||
|
return _employeeStorageContract.GetList(onlyActive, fromBirthDate: fromDate, toBirthDate: toDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmployeeDataModel> GetAllEmployeesByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllEmployees params: {onlyActive}, {fromDate}, {toDate}", onlyActive, fromDate, toDate);
|
||||||
|
if (fromDate.IsDateNotOlder(toDate))
|
||||||
|
{
|
||||||
|
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||||||
|
}
|
||||||
|
return _employeeStorageContract.GetList(onlyActive, fromEmploymentDate: fromDate, toEmploymentDate: toDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmployeeDataModel GetEmployeeByData(string data)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get element by data: {data}", data);
|
||||||
|
if (data.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
if (data.IsGuid())
|
||||||
|
{
|
||||||
|
return _employeeStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
|
||||||
|
}
|
||||||
|
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(_localizer);
|
||||||
|
_employeeStorageContract.AddElement(employeeDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateEmployee(EmployeeDataModel employeeDataModel)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(employeeDataModel));
|
||||||
|
ArgumentNullException.ThrowIfNull(employeeDataModel);
|
||||||
|
employeeDataModel.Validate(_localizer);
|
||||||
|
_employeeStorageContract.UpdElement(employeeDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteEmployee(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"));
|
||||||
|
}
|
||||||
|
_employeeStorageContract.DelElement(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
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 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PostDataModel> GetAllDataOfPost(string postId)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllDataOfPost for {postId}", postId);
|
||||||
|
if (postId.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(postId));
|
||||||
|
}
|
||||||
|
if (!postId.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "PostId"));
|
||||||
|
}
|
||||||
|
return _postStorageContract.GetPostWithHistory(postId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostDataModel GetPostByData(string data)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get element by data: {data}", data);
|
||||||
|
if (data.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
if (data.IsGuid())
|
||||||
|
{
|
||||||
|
return _postStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
|
||||||
|
}
|
||||||
|
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(_localizer);
|
||||||
|
_postStorageContract.AddElement(postDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdatePost(PostDataModel postDataModel)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(postDataModel));
|
||||||
|
ArgumentNullException.ThrowIfNull(postDataModel);
|
||||||
|
postDataModel.Validate(_localizer);
|
||||||
|
_postStorageContract.UpdElement(postDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeletePost(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"));
|
||||||
|
}
|
||||||
|
_postStorageContract.DelElement(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RestorePost(string id)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Restore by id: {id}", id);
|
||||||
|
if (id.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(id));
|
||||||
|
}
|
||||||
|
if (!id.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
|
||||||
|
}
|
||||||
|
_postStorageContract.ResElement(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
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 ProductBusinessLogicContract(IProductStorageContract productStorageContract, IStringLocalizer<Messages> localizer, ILogger logger) : IProductBusinessLogicContract
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger = logger;
|
||||||
|
private readonly IProductStorageContract _productStorageContract = productStorageContract;
|
||||||
|
private readonly IStringLocalizer<Messages> _localizer = localizer;
|
||||||
|
|
||||||
|
public List<ProductDataModel> GetAllProducts(bool onlyActive)
|
||||||
|
{
|
||||||
|
_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)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetProductHistoryByProduct for {productId}", productId);
|
||||||
|
if (productId.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(productId));
|
||||||
|
}
|
||||||
|
if (!productId.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "ProductId"));
|
||||||
|
}
|
||||||
|
return _productStorageContract.GetHistoryByProductId(productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductDataModel GetProductByData(string data)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get element by data: {data}", data);
|
||||||
|
if (data.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
if (data.IsGuid())
|
||||||
|
{
|
||||||
|
return _productStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
|
||||||
|
}
|
||||||
|
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(_localizer);
|
||||||
|
_productStorageContract.AddElement(productDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProduct(ProductDataModel productDataModel)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(productDataModel));
|
||||||
|
ArgumentNullException.ThrowIfNull(productDataModel);
|
||||||
|
productDataModel.Validate(_localizer);
|
||||||
|
_productStorageContract.UpdElement(productDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteProduct(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"));
|
||||||
|
}
|
||||||
|
_productStorageContract.DelElement(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
namespace CandyHouseBusinessLogic.Implementations;
|
||||||
|
|
||||||
|
internal class ReportContract : IReportContract
|
||||||
|
{
|
||||||
|
private readonly IProductStorageContract _productStorageContract;
|
||||||
|
|
||||||
|
private readonly ISaleStorageContract _saleStorageContract;
|
||||||
|
|
||||||
|
private readonly IClientDiscountStorageContract _clientDiscountStorageContract;
|
||||||
|
|
||||||
|
private readonly BaseWordBuilder _baseWordBuilder;
|
||||||
|
|
||||||
|
private readonly BaseExcelBuilder _baseExcelBuilder;
|
||||||
|
|
||||||
|
private readonly BasePdfBuilder _basePdfBuilder;
|
||||||
|
|
||||||
|
private readonly IStringLocalizer<Messages> _localizer;
|
||||||
|
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
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(_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)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Create report SalesByPeriod from {dateStart} to {dateFinish}", dateStart, dateFinish);
|
||||||
|
var data = await GetDataBySalesAsync(dateStart, dateFinish, ct) ?? throw new InvalidOperationException("No found data");
|
||||||
|
return _baseExcelBuilder
|
||||||
|
.AddHeader(_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)
|
||||||
|
{
|
||||||
|
_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(_localizer["DocumentPdfHeader"])
|
||||||
|
.AddParagraph(string.Format(_localizer["DocumentPdfSubHeader"], dateStart.ToLocalTime().ToShortDateString(), dateFinish.ToLocalTime().ToShortDateString()))
|
||||||
|
.AddPieChart("Начисления", [.. data.Select(x => (x.ClientFIO, x.TotalDiscount))])
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<List<ProductHistoryPricesDataModel>> GetDataProductHistoryPricesAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get data ProductHistoryPrices");
|
||||||
|
return GetDataByHistoryPricesAsync(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)
|
||||||
|
{
|
||||||
|
_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<SaleDataModel>> GetDataBySalesAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (dateStart.IsDateNotOlder(dateFinish))
|
||||||
|
{
|
||||||
|
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
|
||||||
|
}
|
||||||
|
return [.. (await _saleStorageContract.GetListAsync(dateStart, dateFinish, ct)).OrderBy(x => x.SaleDate)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<ClientDiscountByPeriodDataModel>> GetDataByClientDiscountAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (dateStart.IsDateNotOlder(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)];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
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 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, _localizer);
|
||||||
|
}
|
||||||
|
return _saleStorageContract.GetList(fromDate, toDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleDataModel> GetAllSalesByEmployeeByPeriod(string employeeId, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllSales params: {employeeId}, {fromDate}, {toDate}", employeeId, fromDate, toDate);
|
||||||
|
if (fromDate.IsDateNotOlder(toDate))
|
||||||
|
{
|
||||||
|
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||||||
|
}
|
||||||
|
if (employeeId.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(employeeId));
|
||||||
|
}
|
||||||
|
if (!employeeId.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
|
||||||
|
}
|
||||||
|
return _saleStorageContract.GetList(fromDate, toDate, employeeId: employeeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleDataModel> GetAllSalesByClientByPeriod(string clientId, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllSales params: {clientId}, {fromDate}, {toDate}", clientId, fromDate, toDate);
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
return _saleStorageContract.GetList(fromDate, toDate, clientId: clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleDataModel> GetAllSalesByProductByPeriod(string productId, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("GetAllSales params: {productId}, {fromDate}, {toDate}", productId, fromDate, toDate);
|
||||||
|
if (fromDate.IsDateNotOlder(toDate))
|
||||||
|
{
|
||||||
|
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||||||
|
}
|
||||||
|
if (productId.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(productId));
|
||||||
|
}
|
||||||
|
if (!productId.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "ProductId"));
|
||||||
|
}
|
||||||
|
return _saleStorageContract.GetList(fromDate, toDate, productId: productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaleDataModel GetSaleByData(string data)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Get element by data: {data}", data);
|
||||||
|
if (data.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
if (!data.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
|
||||||
|
}
|
||||||
|
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(_localizer);
|
||||||
|
_saleStorageContract.AddElement(saleDataModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelSale(string id)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Cancel by id: {id}", id);
|
||||||
|
if (id.IsEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(id));
|
||||||
|
}
|
||||||
|
if (!id.IsGuid())
|
||||||
|
{
|
||||||
|
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "Id"));
|
||||||
|
}
|
||||||
|
_saleStorageContract.DelElement(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
public abstract class BaseExcelBuilder
|
||||||
|
{
|
||||||
|
public abstract BaseExcelBuilder AddHeader(string header, int startIndex, int count);
|
||||||
|
|
||||||
|
public abstract BaseExcelBuilder AddParagraph(string text, int columnIndex);
|
||||||
|
|
||||||
|
public abstract BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data);
|
||||||
|
|
||||||
|
public abstract Stream Build();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
public abstract class BasePdfBuilder
|
||||||
|
{
|
||||||
|
public abstract BasePdfBuilder AddHeader(string header);
|
||||||
|
|
||||||
|
public abstract BasePdfBuilder AddParagraph(string text);
|
||||||
|
|
||||||
|
public abstract BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data);
|
||||||
|
|
||||||
|
public abstract Stream Build();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
public abstract class BaseWordBuilder
|
||||||
|
{
|
||||||
|
public abstract BaseWordBuilder AddHeader(string header);
|
||||||
|
|
||||||
|
public abstract BaseWordBuilder AddParagraph(string text);
|
||||||
|
|
||||||
|
public abstract BaseWordBuilder AddTable(int[] widths, List<string[]> data);
|
||||||
|
|
||||||
|
public abstract Stream Build();
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using MigraDoc.DocumentObjectModel;
|
||||||
|
using MigraDoc.DocumentObjectModel.Shapes.Charts;
|
||||||
|
using MigraDoc.Rendering;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
internal class MigraDocPdfBuilder : BasePdfBuilder
|
||||||
|
{
|
||||||
|
private readonly Document _document;
|
||||||
|
|
||||||
|
public MigraDocPdfBuilder()
|
||||||
|
{
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
_document = new Document();
|
||||||
|
DefineStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BasePdfBuilder AddHeader(string header)
|
||||||
|
{
|
||||||
|
_document.AddSection().AddParagraph(header, "NormalBold");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BasePdfBuilder AddParagraph(string text)
|
||||||
|
{
|
||||||
|
_document.LastSection.AddParagraph(text, "Normal");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
|
||||||
|
{
|
||||||
|
if (data == null || data.Count == 0)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var chart = new Chart(ChartType.Pie2D);
|
||||||
|
var series = chart.SeriesCollection.AddSeries();
|
||||||
|
series.Add(data.Select(x => x.Value).ToArray());
|
||||||
|
|
||||||
|
var xseries = chart.XValues.AddXSeries();
|
||||||
|
xseries.Add(data.Select(x => x.Caption).ToArray());
|
||||||
|
|
||||||
|
chart.DataLabel.Type = DataLabelType.Percent;
|
||||||
|
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
|
||||||
|
|
||||||
|
chart.Width = Unit.FromCentimeter(16);
|
||||||
|
chart.Height = Unit.FromCentimeter(12);
|
||||||
|
|
||||||
|
chart.TopArea.AddParagraph(title);
|
||||||
|
|
||||||
|
chart.XAxis.MajorTickMark = TickMarkType.Outside;
|
||||||
|
|
||||||
|
chart.YAxis.MajorTickMark = TickMarkType.Outside;
|
||||||
|
chart.YAxis.HasMajorGridlines = true;
|
||||||
|
|
||||||
|
chart.PlotArea.LineFormat.Width = 1;
|
||||||
|
chart.PlotArea.LineFormat.Visible = true;
|
||||||
|
|
||||||
|
chart.TopArea.AddLegend();
|
||||||
|
|
||||||
|
_document.LastSection.Add(chart);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Stream Build()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var renderer = new PdfDocumentRenderer(true)
|
||||||
|
{
|
||||||
|
Document = _document
|
||||||
|
};
|
||||||
|
renderer.RenderDocument();
|
||||||
|
renderer.PdfDocument.Save(stream);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DefineStyles()
|
||||||
|
{
|
||||||
|
var style = _document.Styles.AddStyle("NormalBold", "Normal");
|
||||||
|
style.Font.Bold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
using DocumentFormat.OpenXml.Packaging;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using DocumentFormat.OpenXml;
|
||||||
|
|
||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
internal class OpenXmlExcelBuilder : BaseExcelBuilder
|
||||||
|
{
|
||||||
|
private readonly SheetData _sheetData;
|
||||||
|
|
||||||
|
private readonly MergeCells _mergeCells;
|
||||||
|
|
||||||
|
private readonly Columns _columns;
|
||||||
|
|
||||||
|
private uint _rowIndex = 0;
|
||||||
|
|
||||||
|
public OpenXmlExcelBuilder()
|
||||||
|
{
|
||||||
|
_sheetData = new SheetData();
|
||||||
|
_mergeCells = new MergeCells();
|
||||||
|
_columns = new Columns();
|
||||||
|
_rowIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseExcelBuilder AddHeader(string header, int startIndex, int count)
|
||||||
|
{
|
||||||
|
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
|
||||||
|
for (int i = startIndex + 1; i < startIndex + count; ++i)
|
||||||
|
{
|
||||||
|
CreateCell(i, _rowIndex, "", StyleIndex.SimpleTextWithoutBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mergeCells.Append(new MergeCell()
|
||||||
|
{
|
||||||
|
Reference =
|
||||||
|
new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
|
||||||
|
});
|
||||||
|
|
||||||
|
_rowIndex++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseExcelBuilder AddParagraph(string text, int columnIndex)
|
||||||
|
{
|
||||||
|
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
|
||||||
|
{
|
||||||
|
if (columnsWidths == null || columnsWidths.Length == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(columnsWidths));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == null || data.Count == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.Any(x => x.Length != columnsWidths.Length))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("widths.Length != data.Length");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint counter = 1;
|
||||||
|
int coef = 2;
|
||||||
|
_columns.Append(columnsWidths.Select(x => new Column
|
||||||
|
{
|
||||||
|
Min = counter,
|
||||||
|
Max = counter++,
|
||||||
|
Width = x * coef,
|
||||||
|
CustomWidth = true
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (var j = 0; j < data.First().Length; ++j)
|
||||||
|
{
|
||||||
|
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rowIndex++;
|
||||||
|
for (var i = 1; i < data.Count - 1; ++i)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < data[i].Length; ++j)
|
||||||
|
{
|
||||||
|
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rowIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var j = 0; j < data.Last().Length; ++j)
|
||||||
|
{
|
||||||
|
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
_rowIndex++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Stream Build()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
using var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);
|
||||||
|
var workbookpart = spreadsheetDocument.AddWorkbookPart();
|
||||||
|
GenerateStyle(workbookpart);
|
||||||
|
workbookpart.Workbook = new Workbook();
|
||||||
|
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
|
||||||
|
worksheetPart.Worksheet = new Worksheet();
|
||||||
|
if (_columns.HasChildren)
|
||||||
|
{
|
||||||
|
worksheetPart.Worksheet.Append(_columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheetPart.Worksheet.Append(_sheetData);
|
||||||
|
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
|
||||||
|
var sheet = new Sheet()
|
||||||
|
{
|
||||||
|
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
|
||||||
|
SheetId = 1,
|
||||||
|
Name = "Лист 1"
|
||||||
|
};
|
||||||
|
|
||||||
|
sheets.Append(sheet);
|
||||||
|
if (_mergeCells.HasChildren)
|
||||||
|
{
|
||||||
|
worksheetPart.Worksheet.InsertAfter(_mergeCells, worksheetPart.Worksheet.Elements<SheetData>().First());
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateStyle(WorkbookPart workbookPart)
|
||||||
|
{
|
||||||
|
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
|
||||||
|
workbookStylesPart.Stylesheet = new Stylesheet();
|
||||||
|
|
||||||
|
var fonts = new Fonts() { Count = 2, KnownFonts = BooleanValue.FromBoolean(true) };
|
||||||
|
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
|
||||||
|
{
|
||||||
|
FontSize = new FontSize() { Val = 11 },
|
||||||
|
FontName = new FontName() { Val = "Calibri" },
|
||||||
|
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
|
||||||
|
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) }
|
||||||
|
});
|
||||||
|
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
|
||||||
|
{
|
||||||
|
FontSize = new FontSize() { Val = 11 },
|
||||||
|
FontName = new FontName() { Val = "Calibri" },
|
||||||
|
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
|
||||||
|
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) },
|
||||||
|
Bold = new Bold()
|
||||||
|
});
|
||||||
|
workbookStylesPart.Stylesheet.Append(fonts);
|
||||||
|
|
||||||
|
// Default Fill
|
||||||
|
var fills = new Fills() { Count = 1 };
|
||||||
|
fills.Append(new Fill
|
||||||
|
{
|
||||||
|
PatternFill = new PatternFill() { PatternType = new EnumValue<PatternValues>(PatternValues.None) }
|
||||||
|
});
|
||||||
|
workbookStylesPart.Stylesheet.Append(fills);
|
||||||
|
|
||||||
|
// Default Border
|
||||||
|
var borders = new Borders() { Count = 2 };
|
||||||
|
borders.Append(new Border
|
||||||
|
{
|
||||||
|
LeftBorder = new LeftBorder(),
|
||||||
|
RightBorder = new RightBorder(),
|
||||||
|
TopBorder = new TopBorder(),
|
||||||
|
BottomBorder = new BottomBorder(),
|
||||||
|
DiagonalBorder = new DiagonalBorder()
|
||||||
|
});
|
||||||
|
borders.Append(new Border
|
||||||
|
{
|
||||||
|
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
|
||||||
|
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
|
||||||
|
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
|
||||||
|
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin }
|
||||||
|
});
|
||||||
|
workbookStylesPart.Stylesheet.Append(borders);
|
||||||
|
|
||||||
|
// Default cell format and a date cell format
|
||||||
|
var cellFormats = new CellFormats() { Count = 4 };
|
||||||
|
cellFormats.Append(new CellFormat
|
||||||
|
{
|
||||||
|
NumberFormatId = 0,
|
||||||
|
FormatId = 0,
|
||||||
|
FontId = 0,
|
||||||
|
BorderId = 0,
|
||||||
|
FillId = 0,
|
||||||
|
Alignment = new Alignment()
|
||||||
|
{
|
||||||
|
Horizontal = HorizontalAlignmentValues.Left,
|
||||||
|
Vertical = VerticalAlignmentValues.Center,
|
||||||
|
WrapText = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cellFormats.Append(new CellFormat
|
||||||
|
{
|
||||||
|
NumberFormatId = 0,
|
||||||
|
FormatId = 0,
|
||||||
|
FontId = 0,
|
||||||
|
BorderId = 1,
|
||||||
|
FillId = 0,
|
||||||
|
Alignment = new Alignment()
|
||||||
|
{
|
||||||
|
Horizontal = HorizontalAlignmentValues.Left,
|
||||||
|
Vertical = VerticalAlignmentValues.Center,
|
||||||
|
WrapText = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cellFormats.Append(new CellFormat
|
||||||
|
{
|
||||||
|
NumberFormatId = 0,
|
||||||
|
FormatId = 0,
|
||||||
|
FontId = 1,
|
||||||
|
BorderId = 0,
|
||||||
|
FillId = 0,
|
||||||
|
Alignment = new Alignment()
|
||||||
|
{
|
||||||
|
Horizontal = HorizontalAlignmentValues.Center,
|
||||||
|
Vertical = VerticalAlignmentValues.Center,
|
||||||
|
WrapText = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cellFormats.Append(new CellFormat
|
||||||
|
{
|
||||||
|
NumberFormatId = 0,
|
||||||
|
FormatId = 0,
|
||||||
|
FontId = 1,
|
||||||
|
BorderId = 1,
|
||||||
|
FillId = 0,
|
||||||
|
Alignment = new Alignment()
|
||||||
|
{
|
||||||
|
Horizontal = HorizontalAlignmentValues.Center,
|
||||||
|
Vertical = VerticalAlignmentValues.Center,
|
||||||
|
WrapText = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
workbookStylesPart.Stylesheet.Append(cellFormats);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum StyleIndex
|
||||||
|
{
|
||||||
|
SimpleTextWithoutBorder = 0,
|
||||||
|
SimpleTextWithBorder = 1,
|
||||||
|
BoldTextWithoutBorder = 2,
|
||||||
|
BoldTextWithBorder = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
|
||||||
|
{
|
||||||
|
var columnName = GetExcelColumnName(columnIndex);
|
||||||
|
var cellReference = columnName + rowIndex;
|
||||||
|
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
|
||||||
|
if (row == null)
|
||||||
|
{
|
||||||
|
row = new Row() { RowIndex = rowIndex };
|
||||||
|
_sheetData.Append(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
var newCell = row.Elements<Cell>()
|
||||||
|
.FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex);
|
||||||
|
if (newCell == null)
|
||||||
|
{
|
||||||
|
Cell? refCell = null;
|
||||||
|
foreach (Cell cell in row.Elements<Cell>())
|
||||||
|
{
|
||||||
|
if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length)
|
||||||
|
{
|
||||||
|
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
|
||||||
|
{
|
||||||
|
refCell = cell;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newCell = new Cell() { CellReference = cellReference };
|
||||||
|
row.InsertBefore(newCell, refCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
newCell.CellValue = new CellValue(text);
|
||||||
|
newCell.DataType = CellValues.String;
|
||||||
|
newCell.StyleIndex = (uint)styleIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetExcelColumnName(int columnNumber)
|
||||||
|
{
|
||||||
|
columnNumber += 1;
|
||||||
|
int dividend = columnNumber;
|
||||||
|
string columnName = string.Empty;
|
||||||
|
int modulo;
|
||||||
|
|
||||||
|
while (dividend > 0)
|
||||||
|
{
|
||||||
|
modulo = (dividend - 1) % 26;
|
||||||
|
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
||||||
|
dividend = (dividend - modulo) / 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
using DocumentFormat.OpenXml.Packaging;
|
||||||
|
using DocumentFormat.OpenXml.Wordprocessing;
|
||||||
|
using DocumentFormat.OpenXml;
|
||||||
|
|
||||||
|
namespace CandyHouseBusinessLogic.OfficePackage;
|
||||||
|
|
||||||
|
internal class OpenXmlWordBuilder : BaseWordBuilder
|
||||||
|
{
|
||||||
|
private readonly Document _document;
|
||||||
|
|
||||||
|
private readonly Body _body;
|
||||||
|
|
||||||
|
public OpenXmlWordBuilder()
|
||||||
|
{
|
||||||
|
_document = new Document();
|
||||||
|
_body = _document.AppendChild(new Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseWordBuilder AddHeader(string header)
|
||||||
|
{
|
||||||
|
var paragraph = _body.AppendChild(new Paragraph());
|
||||||
|
var run = paragraph.AppendChild(new Run());
|
||||||
|
run.AppendChild(new RunProperties(new Bold()));
|
||||||
|
run.AppendChild(new Text(header));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseWordBuilder AddParagraph(string text)
|
||||||
|
{
|
||||||
|
var paragraph = _body.AppendChild(new Paragraph());
|
||||||
|
var run = paragraph.AppendChild(new Run());
|
||||||
|
run.AppendChild(new Text(text));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BaseWordBuilder AddTable(int[] widths, List<string[]> data)
|
||||||
|
{
|
||||||
|
if (widths == null || widths.Length == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(widths));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == null || data.Count == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.Any(x => x.Length != widths.Length))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("widths.Length != data.Length");
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = new Table();
|
||||||
|
table.AppendChild(new TableProperties(
|
||||||
|
new TableBorders(
|
||||||
|
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
|
||||||
|
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
|
||||||
|
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
|
||||||
|
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
|
||||||
|
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
|
||||||
|
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
// Заголовок
|
||||||
|
var tr = new TableRow();
|
||||||
|
for (var j = 0; j < widths.Length; ++j)
|
||||||
|
{
|
||||||
|
tr.Append(new TableCell(
|
||||||
|
new TableCellProperties(new TableCellWidth() { Width = widths[j].ToString() }),
|
||||||
|
new Paragraph(new Run(new RunProperties(new Bold()), new Text(data.First()[j])))));
|
||||||
|
}
|
||||||
|
table.Append(tr);
|
||||||
|
|
||||||
|
// Данные
|
||||||
|
table.Append(data.Skip(1).Select(x =>
|
||||||
|
new TableRow(x.Select(y => new TableCell(new Paragraph(new Run(new Text(y))))))));
|
||||||
|
|
||||||
|
_body.Append(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Stream Build()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
using var wordDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);
|
||||||
|
var mainPart = wordDocument.AddMainDocumentPart();
|
||||||
|
mainPart.Document = _document;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
using CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface IClientAdapter
|
||||||
|
{
|
||||||
|
ClientOperationResponse GetList();
|
||||||
|
|
||||||
|
ClientOperationResponse GetElement(string data);
|
||||||
|
|
||||||
|
ClientOperationResponse RegisterClient(ClientBindingModel clientModel);
|
||||||
|
|
||||||
|
ClientOperationResponse ChangeClientInfo(ClientBindingModel clientModel);
|
||||||
|
|
||||||
|
ClientOperationResponse RemoveClient(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
using CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface IEmployeeAdapter
|
||||||
|
{
|
||||||
|
EmployeeOperationResponse GetList(bool includeDeleted);
|
||||||
|
|
||||||
|
EmployeeOperationResponse GetPostList(string id, bool includeDeleted);
|
||||||
|
|
||||||
|
EmployeeOperationResponse GetListByBirthDate(DateTime fromDate, DateTime toDate, bool includeDeleted);
|
||||||
|
|
||||||
|
EmployeeOperationResponse GetListByEmploymentDate(DateTime fromDate, DateTime toDate, bool includeDeleted);
|
||||||
|
|
||||||
|
EmployeeOperationResponse GetElement(string data);
|
||||||
|
|
||||||
|
EmployeeOperationResponse RegisterEmployee(EmployeeBindingModel employeeModel);
|
||||||
|
|
||||||
|
EmployeeOperationResponse ChangeEmployeeInfo(EmployeeBindingModel employeeModel);
|
||||||
|
|
||||||
|
EmployeeOperationResponse RemoveEmployee(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
using CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface IPostAdapter
|
||||||
|
{
|
||||||
|
PostOperationResponse GetList();
|
||||||
|
|
||||||
|
PostOperationResponse GetHistory(string id);
|
||||||
|
|
||||||
|
PostOperationResponse GetElement(string data);
|
||||||
|
|
||||||
|
PostOperationResponse RegisterPost(PostBindingModel postModel);
|
||||||
|
|
||||||
|
PostOperationResponse ChangePostInfo(PostBindingModel postModel);
|
||||||
|
|
||||||
|
PostOperationResponse RemovePost(string id);
|
||||||
|
|
||||||
|
PostOperationResponse RestorePost(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
using CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface IProductAdapter
|
||||||
|
{
|
||||||
|
ProductOperationResponse GetList(bool includeDeleted);
|
||||||
|
|
||||||
|
ProductOperationResponse GetManufacturerList(string id, bool includeDeleted);
|
||||||
|
|
||||||
|
ProductOperationResponse GetHistory(string id);
|
||||||
|
|
||||||
|
ProductOperationResponse GetElement(string data);
|
||||||
|
|
||||||
|
ProductOperationResponse RegisterProduct(ProductBindingModel productModel);
|
||||||
|
|
||||||
|
ProductOperationResponse ChangeProductInfo(ProductBindingModel productModel);
|
||||||
|
|
||||||
|
ProductOperationResponse RemoveProduct(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface IReportAdapter
|
||||||
|
{
|
||||||
|
Task<ReportOperationResponse> GetDataProductHistoryPricesAsync(CancellationToken ct);
|
||||||
|
|
||||||
|
Task<ReportOperationResponse> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<ReportOperationResponse> GetDataClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<ReportOperationResponse> CreateDocumentProductHistoryPricesAsync(CancellationToken ct);
|
||||||
|
|
||||||
|
Task<ReportOperationResponse> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<ReportOperationResponse> CreateDocumentClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
using CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts;
|
||||||
|
|
||||||
|
public interface ISaleAdapter
|
||||||
|
{
|
||||||
|
SaleOperationResponse GetList(DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
SaleOperationResponse GetEmployeeList(string id, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
SaleOperationResponse GetClientList(string id, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
SaleOperationResponse GetProductList(string id, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
SaleOperationResponse GetElement(string id);
|
||||||
|
|
||||||
|
SaleOperationResponse MakeSale(SaleBindingModel saleModel);
|
||||||
|
|
||||||
|
SaleOperationResponse CancelSale(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class ClientOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static ClientOperationResponse OK(List<ClientViewModel> data) => OK<ClientOperationResponse, List<ClientViewModel>>(data);
|
||||||
|
|
||||||
|
public static ClientOperationResponse OK(ClientViewModel data) => OK<ClientOperationResponse, ClientViewModel>(data);
|
||||||
|
|
||||||
|
public static ClientOperationResponse NoContent() => NoContent<ClientOperationResponse>();
|
||||||
|
|
||||||
|
public static ClientOperationResponse BadRequest(string message) => BadRequest<ClientOperationResponse>(message);
|
||||||
|
|
||||||
|
public static ClientOperationResponse NotFound(string message) => NotFound<ClientOperationResponse>(message);
|
||||||
|
|
||||||
|
public static ClientOperationResponse InternalServerError(string message) => InternalServerError<ClientOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class EmployeeOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static EmployeeOperationResponse OK(List<EmployeeViewModel> data) => OK<EmployeeOperationResponse, List<EmployeeViewModel>>(data);
|
||||||
|
|
||||||
|
public static EmployeeOperationResponse OK(EmployeeViewModel data) => OK<EmployeeOperationResponse, EmployeeViewModel>(data);
|
||||||
|
|
||||||
|
public static EmployeeOperationResponse NoContent() => NoContent<EmployeeOperationResponse>();
|
||||||
|
|
||||||
|
public static EmployeeOperationResponse NotFound(string message) => NotFound<EmployeeOperationResponse>(message);
|
||||||
|
|
||||||
|
public static EmployeeOperationResponse BadRequest(string message) => BadRequest<EmployeeOperationResponse>(message);
|
||||||
|
|
||||||
|
public static EmployeeOperationResponse InternalServerError(string message) => InternalServerError<EmployeeOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class PostOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static PostOperationResponse OK(List<PostViewModel> data) => OK<PostOperationResponse, List<PostViewModel>>(data);
|
||||||
|
|
||||||
|
public static PostOperationResponse OK(PostViewModel data) => OK<PostOperationResponse, PostViewModel>(data);
|
||||||
|
|
||||||
|
public static PostOperationResponse NoContent() => NoContent<PostOperationResponse>();
|
||||||
|
|
||||||
|
public static PostOperationResponse NotFound(string message) => NotFound<PostOperationResponse>(message);
|
||||||
|
|
||||||
|
public static PostOperationResponse BadRequest(string message) => BadRequest<PostOperationResponse>(message);
|
||||||
|
|
||||||
|
public static PostOperationResponse InternalServerError(string message) => InternalServerError<PostOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class ProductOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static ProductOperationResponse OK(List<ProductViewModel> data) => OK<ProductOperationResponse, List<ProductViewModel>>(data);
|
||||||
|
|
||||||
|
public static ProductOperationResponse OK(List<ProductHistoryViewModel> data) => OK<ProductOperationResponse, List<ProductHistoryViewModel>>(data);
|
||||||
|
|
||||||
|
public static ProductOperationResponse OK(ProductViewModel data) => OK<ProductOperationResponse, ProductViewModel>(data);
|
||||||
|
|
||||||
|
public static ProductOperationResponse NoContent() => NoContent<ProductOperationResponse>();
|
||||||
|
|
||||||
|
public static ProductOperationResponse NotFound(string message) => NotFound<ProductOperationResponse>(message);
|
||||||
|
|
||||||
|
public static ProductOperationResponse BadRequest(string message) => BadRequest<ProductOperationResponse>(message);
|
||||||
|
|
||||||
|
public static ProductOperationResponse InternalServerError(string message) => InternalServerError<ProductOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class ReportOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static ReportOperationResponse OK(List<ProductHistoryPricesViewModel> data) => OK<ReportOperationResponse, List<ProductHistoryPricesViewModel>>(data);
|
||||||
|
|
||||||
|
public static ReportOperationResponse OK(List<SaleViewModel> data) => OK<ReportOperationResponse, List<SaleViewModel>>(data);
|
||||||
|
|
||||||
|
public static ReportOperationResponse OK(List<ClientDiscountByPeriodViewModel> data) => OK<ReportOperationResponse, List<ClientDiscountByPeriodViewModel>>(data);
|
||||||
|
|
||||||
|
public static ReportOperationResponse OK(Stream data, string fileName) => OK<ReportOperationResponse, Stream>(data, fileName);
|
||||||
|
|
||||||
|
public static ReportOperationResponse BadRequest(string message) => BadRequest<ReportOperationResponse>(message);
|
||||||
|
|
||||||
|
public static ReportOperationResponse InternalServerError(string message) => InternalServerError<ReportOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.ViewModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.AdapterContracts.OperationResponses;
|
||||||
|
|
||||||
|
public class SaleOperationResponse : OperationResponse
|
||||||
|
{
|
||||||
|
public static SaleOperationResponse OK(List<SaleViewModel> data) => OK<SaleOperationResponse, List<SaleViewModel>>(data);
|
||||||
|
|
||||||
|
public static SaleOperationResponse OK(SaleViewModel data) => OK<SaleOperationResponse, SaleViewModel>(data);
|
||||||
|
|
||||||
|
public static SaleOperationResponse NoContent() => NoContent<SaleOperationResponse>();
|
||||||
|
|
||||||
|
public static SaleOperationResponse NotFound(string message) => NotFound<SaleOperationResponse>(message);
|
||||||
|
|
||||||
|
public static SaleOperationResponse BadRequest(string message) => BadRequest<SaleOperationResponse>(message);
|
||||||
|
|
||||||
|
public static SaleOperationResponse InternalServerError(string message) => InternalServerError<SaleOperationResponse>(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class ClientBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? FIO { get; set; }
|
||||||
|
|
||||||
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? ConfigurationJson { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class EmployeeBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? FIO { get; set; }
|
||||||
|
|
||||||
|
public string? PostId { get; set; }
|
||||||
|
|
||||||
|
public DateTime BirthDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime EmploymentDate { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class ManufacturerBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? ManufacturerName { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class PostBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? PostId => Id;
|
||||||
|
|
||||||
|
public string? PostName { get; set; }
|
||||||
|
|
||||||
|
public string? PostType { get; set; }
|
||||||
|
|
||||||
|
public double Salary { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class ProductBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? ProductName { get; set; }
|
||||||
|
|
||||||
|
public string? ProductType { get; set; }
|
||||||
|
|
||||||
|
public string? ManufacturerId { get; set; }
|
||||||
|
|
||||||
|
public double Price { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class SaleBindingModel
|
||||||
|
{
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
public string? EmployeeId { get; set; }
|
||||||
|
|
||||||
|
public string? ClientId { get; set; }
|
||||||
|
|
||||||
|
public int DiscountType { get; set; }
|
||||||
|
|
||||||
|
public List<SaleProductBindingModel>? Products { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CandyHouseContracts.BindingModels;
|
||||||
|
|
||||||
|
public class SaleProductBindingModel
|
||||||
|
{
|
||||||
|
public string? SaleId { get; set; }
|
||||||
|
|
||||||
|
public string? ProductId { get; set; }
|
||||||
|
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
public double Price { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface IClientBusinessLogicContract
|
||||||
|
{
|
||||||
|
List<ClientDataModel> GetAllClients();
|
||||||
|
|
||||||
|
ClientDataModel GetClientByData(string data);
|
||||||
|
|
||||||
|
void InsertClient(ClientDataModel clientDataModel);
|
||||||
|
|
||||||
|
void UpdateClient(ClientDataModel clientDataModel);
|
||||||
|
|
||||||
|
void DeleteClient(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface IEmployeeBusinessLogicContract
|
||||||
|
{
|
||||||
|
List<EmployeeDataModel> GetAllEmployees(bool onlyActive = true);
|
||||||
|
|
||||||
|
List<EmployeeDataModel> GetAllEmployeesByPost(string postId, bool onlyActive = true);
|
||||||
|
|
||||||
|
List<EmployeeDataModel> GetAllEmployeesByBirthDate(DateTime fromDate, DateTime toDate, bool onlyActive = true);
|
||||||
|
|
||||||
|
List<EmployeeDataModel> GetAllEmployeesByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true);
|
||||||
|
|
||||||
|
EmployeeDataModel GetEmployeeByData(string data);
|
||||||
|
|
||||||
|
void InsertEmployee(EmployeeDataModel employeeDataModel);
|
||||||
|
|
||||||
|
void UpdateEmployee(EmployeeDataModel employeeDataModel);
|
||||||
|
|
||||||
|
void DeleteEmployee(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface IPostBusinessLogicContract
|
||||||
|
{
|
||||||
|
List<PostDataModel> GetAllPosts();
|
||||||
|
|
||||||
|
List<PostDataModel> GetAllDataOfPost(string postId);
|
||||||
|
|
||||||
|
PostDataModel GetPostByData(string data);
|
||||||
|
|
||||||
|
void InsertPost(PostDataModel postDataModel);
|
||||||
|
|
||||||
|
void UpdatePost(PostDataModel postDataModel);
|
||||||
|
|
||||||
|
void DeletePost(string id);
|
||||||
|
|
||||||
|
void RestorePost(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface IProductBusinessLogicContract
|
||||||
|
{
|
||||||
|
List<ProductDataModel> GetAllProducts(bool onlyActive = true);
|
||||||
|
|
||||||
|
List<ProductDataModel> GetAllProductsByManufacturer(string manufacturerId, bool onlyActive = true);
|
||||||
|
|
||||||
|
List<ProductHistoryDataModel> GetProductHistoryByProduct(string productId);
|
||||||
|
|
||||||
|
ProductDataModel GetProductByData(string data);
|
||||||
|
|
||||||
|
void InsertProduct(ProductDataModel productDataModel);
|
||||||
|
|
||||||
|
void UpdateProduct(ProductDataModel productDataModel);
|
||||||
|
|
||||||
|
void DeleteProduct(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface IReportContract
|
||||||
|
{
|
||||||
|
Task<List<ProductHistoryPricesDataModel>> GetDataProductHistoryPricesAsync(CancellationToken ct);
|
||||||
|
|
||||||
|
Task<List<SaleDataModel>> GetDataSaleByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<List<ClientDiscountByPeriodDataModel>> GetDataClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<Stream> CreateDocumentProductHistoryPricesAsync(CancellationToken ct);
|
||||||
|
|
||||||
|
Task<Stream> CreateDocumentSalesByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
|
||||||
|
Task<Stream> CreateDocumentClientDiscountByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.BusinessLogicsContracts;
|
||||||
|
|
||||||
|
internal interface ISaleBusinessLogicContract
|
||||||
|
{
|
||||||
|
List<SaleDataModel> GetAllSalesByPeriod(DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
List<SaleDataModel> GetAllSalesByEmployeeByPeriod(string employeeId, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
List<SaleDataModel> GetAllSalesByClientByPeriod(string clientId, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
List<SaleDataModel> GetAllSalesByProductByPeriod(string productId, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
SaleDataModel GetSaleByData(string data);
|
||||||
|
|
||||||
|
void InsertSale(SaleDataModel saleDataModel);
|
||||||
|
|
||||||
|
void CancelSale(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<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>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Infrastructure.ClientConfigurations;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using CandyHouseContracts.Infrastructure.ClientConfigurations;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
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 PhoneNumber { get; private set; } = phoneNumber;
|
||||||
|
|
||||||
|
public string Email { get; private set; } = email;
|
||||||
|
|
||||||
|
public ClientConfiguration ConfigurationModel { get; private set; } = configuration;
|
||||||
|
|
||||||
|
public ClientDataModel(string id, string fio, string phoneNumber, string email, string configurationJson) : this(id, fio, phoneNumber, email, (ClientConfiguration)null)
|
||||||
|
{
|
||||||
|
var obj = JToken.Parse(configurationJson);
|
||||||
|
if (obj is not null)
|
||||||
|
{
|
||||||
|
ConfigurationModel = obj.Value<string>("Type") switch
|
||||||
|
{
|
||||||
|
nameof(SilverClientConfiguration) => JsonConvert.DeserializeObject<SilverClientConfiguration>(configurationJson)!,
|
||||||
|
nameof(GoldenClientConfiguration) => JsonConvert.DeserializeObject<GoldenClientConfiguration>(configurationJson)!,
|
||||||
|
_ => JsonConvert.DeserializeObject<ClientConfiguration>(configurationJson)!,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (FIO.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "FIO"));
|
||||||
|
|
||||||
|
if (PhoneNumber.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PhoneNumber"));
|
||||||
|
|
||||||
|
if (!Regex.IsMatch(PhoneNumber, @"^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$"))
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
public class ClientDiscountByPeriodDataModel
|
||||||
|
{
|
||||||
|
public required string ClientFIO { get; set; }
|
||||||
|
|
||||||
|
public double TotalDiscount { get; set; }
|
||||||
|
|
||||||
|
public DateTime FromPeriod { get; set; }
|
||||||
|
|
||||||
|
public DateTime ToPeriod { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
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.ToUniversalTime();
|
||||||
|
|
||||||
|
public double DiscountAmount { get; private set; } = discountAmount;
|
||||||
|
|
||||||
|
public string ClientFIO => _client?.FIO ?? string.Empty;
|
||||||
|
|
||||||
|
public ClientDiscountDataModel(string clientId, DateTime discountDate, double discountAmount, ClientDataModel client) : this(clientId, discountDate, discountAmount)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(IStringLocalizer<Messages> localizer)
|
||||||
|
{
|
||||||
|
if (ClientId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "EmployeeId"));
|
||||||
|
|
||||||
|
if (!ClientId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
|
||||||
|
|
||||||
|
if (DiscountAmount <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "DiscountAmount"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
internal class EmployeeDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
|
||||||
|
{
|
||||||
|
private readonly PostDataModel? _post;
|
||||||
|
|
||||||
|
public string Id { get; private set; } = id;
|
||||||
|
|
||||||
|
public string FIO { get; private set; } = fio;
|
||||||
|
|
||||||
|
public string PostId { get; private set; } = postId;
|
||||||
|
|
||||||
|
public DateTime BirthDate { get; private set; } = birthDate.ToUniversalTime();
|
||||||
|
|
||||||
|
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 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 postId, DateTime birthDate, DateTime employmentDate) : this(id, fio, postId, birthDate, employmentDate, false) { }
|
||||||
|
|
||||||
|
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 (FIO.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "FIO"));
|
||||||
|
|
||||||
|
if (PostId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostId"));
|
||||||
|
|
||||||
|
if (!PostId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "PostId"));
|
||||||
|
|
||||||
|
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(string.Format(localizer["ValidationExceptionMessageEmploymentDateAndBirthDate"],
|
||||||
|
EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
|
||||||
|
|
||||||
|
if ((EmploymentDate - BirthDate).TotalDays / 365 < 16)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageMinorsEmploymentDate"],
|
||||||
|
EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
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(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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Enums;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
internal class PostDataModel(string postId, string postName, PostType postType, double salary) : IValidation
|
||||||
|
{
|
||||||
|
public string Id { get; private set; } = postId;
|
||||||
|
|
||||||
|
public string PostName { get; private set; } = postName;
|
||||||
|
|
||||||
|
public PostType PostType { get; private set; } = postType;
|
||||||
|
|
||||||
|
public double Salary { get; private set; } = salary;
|
||||||
|
|
||||||
|
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 (PostName.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostName"));
|
||||||
|
|
||||||
|
if (PostType == PostType.None)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "PostType"));
|
||||||
|
|
||||||
|
if (Salary <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Salary"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Enums;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
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 ProductType ProductType { get; private set; } = productType;
|
||||||
|
|
||||||
|
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 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 (ProductName.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductName"));
|
||||||
|
|
||||||
|
if (ProductType == ProductType.None)
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
internal class ProductHistoryDataModel(string productId, double oldPrice) : IValidation
|
||||||
|
{
|
||||||
|
private readonly ProductDataModel? _product;
|
||||||
|
|
||||||
|
public string ProductId { get; private set; } = productId;
|
||||||
|
|
||||||
|
public double OldPrice { get; private set; } = oldPrice;
|
||||||
|
|
||||||
|
public DateTime ChangeDate { get; private set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
public string ProductName => _product?.ProductName ?? string.Empty;
|
||||||
|
|
||||||
|
public ProductHistoryDataModel(string productId, double oldPrice, DateTime changeDate, ProductDataModel product) : this(productId, oldPrice)
|
||||||
|
{
|
||||||
|
ChangeDate = changeDate;
|
||||||
|
_product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(IStringLocalizer<Messages> localizer)
|
||||||
|
{
|
||||||
|
if (ProductId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "ProductId"));
|
||||||
|
|
||||||
|
if (!ProductId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ProductId"));
|
||||||
|
|
||||||
|
if (OldPrice <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "OldPrice"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
public class ProductHistoryPricesDataModel
|
||||||
|
{
|
||||||
|
public required string ProductName { get; set; }
|
||||||
|
|
||||||
|
public required List<string> Prices { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Enums;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
internal class SaleDataModel : IValidation
|
||||||
|
{
|
||||||
|
private readonly ClientDataModel? _client;
|
||||||
|
|
||||||
|
private readonly EmployeeDataModel? _employee;
|
||||||
|
|
||||||
|
public string Id { get; private set; }
|
||||||
|
|
||||||
|
public string EmployeeId { get; private set; }
|
||||||
|
|
||||||
|
public string? ClientId { get; private set; }
|
||||||
|
|
||||||
|
public DateTime SaleDate { get; private set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
public double Sum { get; private set; }
|
||||||
|
|
||||||
|
public DiscountType DiscountType { get; private set; }
|
||||||
|
|
||||||
|
public double Discount { get; private set; }
|
||||||
|
|
||||||
|
public bool IsCancel { get; private set; }
|
||||||
|
|
||||||
|
public List<SaleProductDataModel> Products { get; private set; }
|
||||||
|
|
||||||
|
public string ClientFIO => _client?.FIO ?? string.Empty;
|
||||||
|
|
||||||
|
public string EmployeeFIO => _employee?.FIO ?? string.Empty;
|
||||||
|
|
||||||
|
public SaleDataModel(string id, string employeeId, string? clientId, DiscountType discountType, bool isCancel, List<SaleProductDataModel> saleProducts)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
EmployeeId = employeeId;
|
||||||
|
ClientId = clientId;
|
||||||
|
DiscountType = discountType;
|
||||||
|
IsCancel = isCancel;
|
||||||
|
Products = saleProducts;
|
||||||
|
var percent = 0.0;
|
||||||
|
foreach (DiscountType elem in Enum.GetValues<DiscountType>())
|
||||||
|
{
|
||||||
|
if ((elem & discountType) != 0)
|
||||||
|
{
|
||||||
|
switch (elem)
|
||||||
|
{
|
||||||
|
case DiscountType.None:
|
||||||
|
break;
|
||||||
|
case DiscountType.OnSale:
|
||||||
|
percent += 0.1;
|
||||||
|
break;
|
||||||
|
case DiscountType.RegularCustomer:
|
||||||
|
percent += 0.5;
|
||||||
|
break;
|
||||||
|
case DiscountType.Certificate:
|
||||||
|
percent += 0.3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sum = Products?.Sum(x => x.Price * x.Count) ?? 0;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Sum = sum;
|
||||||
|
Discount = discount;
|
||||||
|
_employee = employee;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaleDataModel(string id, string employeeId, string? clientId, int discountType, List<SaleProductDataModel> products) : this(id, employeeId, clientId, (DiscountType)discountType, false, products) { }
|
||||||
|
|
||||||
|
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 (EmployeeId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "EmployeeId"));
|
||||||
|
|
||||||
|
if (!EmployeeId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "EmployeeId"));
|
||||||
|
|
||||||
|
if (!ClientId?.IsGuid() ?? !ClientId?.IsEmpty() ?? false)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ClientId"));
|
||||||
|
|
||||||
|
if (Sum <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Sum"));
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Exceptions;
|
||||||
|
using CandyHouseContracts.Extensions;
|
||||||
|
using CandyHouseContracts.Infrastructure;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
internal class SaleProductDataModel(string saleId, string productId, int count, double price) : IValidation
|
||||||
|
{
|
||||||
|
private readonly ProductDataModel? _product;
|
||||||
|
|
||||||
|
public string SaleId { get; private set; } = saleId;
|
||||||
|
|
||||||
|
public string ProductId { get; private set; } = productId;
|
||||||
|
|
||||||
|
public int Count { get; private set; } = count;
|
||||||
|
|
||||||
|
public double Price { get; private set; } = price;
|
||||||
|
|
||||||
|
public string ProductName => _product?.ProductName ?? string.Empty;
|
||||||
|
|
||||||
|
public SaleProductDataModel(string saleId, string productId, int count, double price, ProductDataModel product) : this(saleId, productId, count, price)
|
||||||
|
{
|
||||||
|
_product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(IStringLocalizer<Messages> localizer)
|
||||||
|
{
|
||||||
|
if (SaleId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "SaleId"));
|
||||||
|
|
||||||
|
if (!SaleId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "SaleId"));
|
||||||
|
|
||||||
|
if (ProductId.IsEmpty())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageEmptyField"], "IProductIdd"));
|
||||||
|
|
||||||
|
if (!ProductId.IsGuid())
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageNotAId"], "ProductId"));
|
||||||
|
|
||||||
|
if (Count <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Count"));
|
||||||
|
|
||||||
|
if (Price <= 0)
|
||||||
|
throw new ValidationException(string.Format(localizer["ValidationExceptionMessageLessOrEqualZero"], "Price"));
|
||||||
|
}
|
||||||
|
}
|
||||||
10
CandyHouseSolution/CandyHouseContracts/Enums/DiscountType.cs
Normal file
10
CandyHouseSolution/CandyHouseContracts/Enums/DiscountType.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace CandyHouseContracts.Enums;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum DiscountType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
OnSale = 1,
|
||||||
|
RegularCustomer = 2,
|
||||||
|
Certificate = 4
|
||||||
|
}
|
||||||
9
CandyHouseSolution/CandyHouseContracts/Enums/PostType.cs
Normal file
9
CandyHouseSolution/CandyHouseContracts/Enums/PostType.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace CandyHouseContracts.Enums;
|
||||||
|
|
||||||
|
public enum PostType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Manager = 1,
|
||||||
|
SuperManager = 2,
|
||||||
|
Baker = 3
|
||||||
|
}
|
||||||
11
CandyHouseSolution/CandyHouseContracts/Enums/ProductType.cs
Normal file
11
CandyHouseSolution/CandyHouseContracts/Enums/ProductType.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace CandyHouseContracts.Enums;
|
||||||
|
|
||||||
|
public enum ProductType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Candy = 1,
|
||||||
|
Cake = 2,
|
||||||
|
Chocolate = 3,
|
||||||
|
Marmalade = 4,
|
||||||
|
Lollipop = 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.Exceptions;
|
||||||
|
|
||||||
|
internal class ElementDeletedException(string id, IStringLocalizer<Messages> localizer) :
|
||||||
|
Exception(string.Format(localizer["ElementDeletedExceptionMessage"], id))
|
||||||
|
{ }
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.Exceptions;
|
||||||
|
|
||||||
|
internal class ElementExistsException(string paramName, string paramValue, IStringLocalizer<Messages> localizer) :
|
||||||
|
Exception(string.Format(localizer["ElementExistsExceptionMessage"], paramValue, paramName))
|
||||||
|
{
|
||||||
|
public string ParamName { get; private set; } = paramName;
|
||||||
|
|
||||||
|
public string ParamValue { get; private set; } = paramValue;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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()))
|
||||||
|
{ }
|
||||||
@@ -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)
|
||||||
|
{ }
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace CandyHouseContracts.Exceptions;
|
||||||
|
|
||||||
|
public class ValidationException(string message) : Exception(message)
|
||||||
|
{ }
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace CandyHouseContracts.Extensions;
|
||||||
|
|
||||||
|
public static class DateTimeExtensions
|
||||||
|
{
|
||||||
|
public static bool IsDateNotOlder(this DateTime date, DateTime olderDate)
|
||||||
|
{
|
||||||
|
return date >= olderDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace CandyHouseContracts.Extensions;
|
||||||
|
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static bool IsEmpty(this string str)
|
||||||
|
{
|
||||||
|
return string.IsNullOrWhiteSpace(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsGuid(this string str)
|
||||||
|
{
|
||||||
|
return Guid.TryParse(str, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CandyHouseContracts.Infrastructure;
|
||||||
|
|
||||||
|
public interface IConfigurationClientDiscount
|
||||||
|
{
|
||||||
|
int MaxParallelThreads { get; }
|
||||||
|
|
||||||
|
double ExtraSaleSum { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace CandyHouseContracts.Infrastructure;
|
||||||
|
|
||||||
|
public interface IConfigurationDatabase
|
||||||
|
{
|
||||||
|
string ConnectionString { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using CandyHouseContracts.Resources;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.Infrastructure;
|
||||||
|
|
||||||
|
internal interface IValidation
|
||||||
|
{
|
||||||
|
void Validate(IStringLocalizer<Messages> localizer);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.Infrastructure;
|
||||||
|
|
||||||
|
public class OperationResponse
|
||||||
|
{
|
||||||
|
protected HttpStatusCode StatusCode { get; set; }
|
||||||
|
|
||||||
|
protected object? Result { get; set; }
|
||||||
|
|
||||||
|
protected string? FileName { get; set; }
|
||||||
|
|
||||||
|
public IActionResult GetResponse(HttpRequest request, HttpResponse response)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(request);
|
||||||
|
ArgumentNullException.ThrowIfNull(response);
|
||||||
|
|
||||||
|
response.StatusCode = (int)StatusCode;
|
||||||
|
|
||||||
|
if (Result is null)
|
||||||
|
{
|
||||||
|
return new StatusCodeResult((int)StatusCode);
|
||||||
|
}
|
||||||
|
if (Result is Stream stream)
|
||||||
|
{
|
||||||
|
return new FileStreamResult(stream, "application/octet-stream")
|
||||||
|
{
|
||||||
|
FileDownloadName = FileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ObjectResult(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static TResult OK<TResult, TData>(TData data) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.OK, Result = data };
|
||||||
|
|
||||||
|
protected static TResult OK<TResult, TData>(TData data, string fileName) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.OK, Result = data, FileName = fileName };
|
||||||
|
|
||||||
|
protected static TResult NoContent<TResult>() where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.NoContent };
|
||||||
|
|
||||||
|
protected static TResult BadRequest<TResult>(string? errorMessage = null) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.BadRequest, Result = errorMessage };
|
||||||
|
|
||||||
|
protected static TResult NotFound<TResult>(string? errorMessage = null) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.NotFound, Result = errorMessage };
|
||||||
|
|
||||||
|
protected static TResult InternalServerError<TResult>(string? errorMessage = null) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.InternalServerError, Result = errorMessage };
|
||||||
|
}
|
||||||
422
CandyHouseSolution/CandyHouseContracts/Resources/Messages.Designer.cs
generated
Normal file
422
CandyHouseSolution/CandyHouseContracts/Resources/Messages.Designer.cs
generated
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
240
CandyHouseSolution/CandyHouseContracts/Resources/Messages.resx
Normal file
240
CandyHouseSolution/CandyHouseContracts/Resources/Messages.resx
Normal 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>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.StoragesContracts;
|
||||||
|
|
||||||
|
internal interface IClientDiscountStorageContract
|
||||||
|
{
|
||||||
|
List<ClientDiscountDataModel> GetList(DateTime startDate, DateTime endDate, string? clientId = null);
|
||||||
|
|
||||||
|
Task<List<ClientDiscountDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
|
||||||
|
|
||||||
|
void AddElement(ClientDiscountDataModel clientDiscountDataModel);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.StoragesContracts;
|
||||||
|
|
||||||
|
internal interface IClientStorageContract
|
||||||
|
{
|
||||||
|
List<ClientDataModel> GetList();
|
||||||
|
|
||||||
|
ClientDataModel? GetElementById(string id);
|
||||||
|
|
||||||
|
ClientDataModel? GetElementByFIO(string fio);
|
||||||
|
|
||||||
|
ClientDataModel? GetElementByPhoneNumber(string phoneNumber);
|
||||||
|
|
||||||
|
ClientDataModel? GetElementByEmail(string email);
|
||||||
|
|
||||||
|
void AddElement(ClientDataModel clientDataModel);
|
||||||
|
|
||||||
|
void UpdElement(ClientDataModel clientDataModel);
|
||||||
|
|
||||||
|
void DelElement(string id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using CandyHouseContracts.DataModels;
|
||||||
|
|
||||||
|
namespace CandyHouseContracts.StoragesContracts;
|
||||||
|
|
||||||
|
internal interface IEmployeeStorageContract
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
void AddElement(EmployeeDataModel employeeDataModel);
|
||||||
|
|
||||||
|
void UpdElement(EmployeeDataModel employeeDataModel);
|
||||||
|
|
||||||
|
void DelElement(string id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user