доделаны контракты и бизнес логика

This commit is contained in:
goldfest 2024-04-30 00:12:46 +04:00
parent b4005174f2
commit 3a07a73c50
32 changed files with 1459 additions and 91 deletions

View File

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CarCenterDataModels", "CarC
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CarCenterContracts", "CarCenterContracts\CarCenterContracts.csproj", "{DA8738DD-3CB5-46D7-AF56-B7ABBFD6EFDC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CarCenterBusinessLogic", "CarCenterBusinessLogic\CarCenterBusinessLogic.csproj", "{9A855C6A-5CBC-49A7-A749-FD3E472D19CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{DA8738DD-3CB5-46D7-AF56-B7ABBFD6EFDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA8738DD-3CB5-46D7-AF56-B7ABBFD6EFDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA8738DD-3CB5-46D7-AF56-B7ABBFD6EFDC}.Release|Any CPU.Build.0 = Release|Any CPU
{9A855C6A-5CBC-49A7-A749-FD3E472D19CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A855C6A-5CBC-49A7-A749-FD3E472D19CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A855C6A-5CBC-49A7-A749-FD3E472D19CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A855C6A-5CBC-49A7-A749-FD3E472D19CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,178 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using CarCenterContracts.BusinessLogicsContracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class AdministratorLogic : IAdministratorLogic
{
private readonly int _loginMaxLength = 50;
private readonly int _passwordMaxLength = 50;
private readonly int _passwordMinLength = 10;
private readonly ILogger _logger;
private readonly IAdministratorStorage _administratorStorage;
public AdministratorLogic(ILogger<AdministratorLogic> logger, IAdministratorStorage administratorStorage)
{
_logger = logger;
_administratorStorage = administratorStorage;
}
public bool Create(AdministratorBindingModel model)
{
CheckModel(model);
if (_administratorStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(AdministratorBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id: {Id}", model.Id);
if (_administratorStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public AdministratorViewModel? ReadElement(AdministratorSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. AdministratorFIO: {AdministratorFIO}. AdministratorLogin: {AdministratorLogin}. Id: {Id}.", model.AdministratorFIO, model.AdministratorLogin, model.Id);
var element = _administratorStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id: {Id}", element.Id);
return element;
}
public List<AdministratorViewModel>? ReadList(AdministratorSearchModel? model)
{
_logger.LogInformation("ReadList. AdministratorFIO: {AdministratorFIO}. AdministratorLogin: {AdministratorLogin}. Id: {Id}.", model?.AdministratorFIO, model?.AdministratorLogin, model?.Id);
var list = model == null ? _administratorStorage.GetFullList() : _administratorStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public bool Update(AdministratorBindingModel model)
{
CheckModel(model);
if (_administratorStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(AdministratorBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.AdministratorFIO))
{
throw new ArgumentNullException("Нет ФИО администратора", nameof(model.AdministratorFIO));
}
if (string.IsNullOrEmpty(model.AdministratorLogin))
{
throw new ArgumentNullException("Нет логина администратора", nameof(model.AdministratorLogin));
}
if (model.AdministratorLogin.Length > _loginMaxLength)
{
throw new ArgumentNullException("Логин слишком длинный", nameof(model.AdministratorLogin));
}
if (string.IsNullOrEmpty(model.AdministratorNumber))
{
throw new ArgumentNullException("Нет номера телефона администратора", nameof(model.AdministratorNumber));
}
if (model.AdministratorEmail.Length > _loginMaxLength || !Regex.IsMatch(model.AdministratorEmail, @"([a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+)"))
{
throw new Exception($"В качестве логина должна быть указана почта и иметь длинну не более {_loginMaxLength} символов");
}
if (string.IsNullOrEmpty(model.AdministratorEmail))
{
throw new ArgumentNullException("Нет почты администратора", nameof(model.AdministratorEmail));
}
if (string.IsNullOrEmpty(model.AdministratorPassword))
{
throw new ArgumentNullException("Нет пароля администратора", nameof(model.AdministratorPassword));
}
if (model.AdministratorPassword.Length > _passwordMaxLength || model.AdministratorPassword.Length < _passwordMinLength
|| !Regex.IsMatch(model.AdministratorPassword, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$"))
{
throw new Exception($"Пароль длиной от {_passwordMinLength} до {_passwordMaxLength} должен состоять из цифр, букв и небуквенных символов");
}
_logger.LogInformation("Administrator. AdministratorFIO: {AdministratorFIO}. AdministratorLogin: {AdministratorLogin}. Id: {Id}", model.AdministratorFIO, model.AdministratorLogin, model.Id);
var element = _administratorStorage.GetElement(new AdministratorSearchModel
{
AdministratorEmail = model.AdministratorEmail
});
if (element != null && element.Id != model.Id)
{
throw new InvalidOperationException("администратор с таким логином уже есть");
}
}
}
}

View File

@ -0,0 +1,141 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class CarSalesLogic : ICarSalesLogic
{
private readonly ILogger _logger;
private readonly ICarSalesStorage _carStorage;
private readonly IAdministratorLogic _administratorLogic;
public CarSalesLogic(ILogger<CarSalesLogic> logger, ICarSalesStorage carStorage, IAdministratorLogic administratorLogic)
{
_logger = logger;
_carStorage = carStorage;
_administratorLogic = administratorLogic;
}
public bool Create(CarSalesBindingModel model)
{
CheckModel(model);
var result = _carStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(CarSalesBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _carStorage.Delete(model);
if (result == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public CarSalesViewModel? ReadElement(CarSalesSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. CarBrand:{CarBrand}.Id:{Id}", model.CarBrand, model.Id);
var element = _carStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<CarSalesViewModel>? ReadList(CarSalesSearchModel? model)
{
_logger.LogInformation("ReadList. CarBrand:{CarBrand}.Id:{ Id}", model?.CarBrand, model?.Id);
var list = model == null ? _carStorage.GetFullList() : _carStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Update(CarSalesBindingModel model)
{
CheckModel(model);
if (_carStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(CarSalesBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.CarBrand))
{
throw new ArgumentNullException("Нет названия бренда", nameof(model.CarBrand));
}
if (string.IsNullOrEmpty(model.CarModel))
{
throw new ArgumentNullException("Нет названия модели", nameof(model.CarModel));
}
if (decimal.Equals(model.CarCost, 0))
{
throw new ArgumentNullException("Нет стоимости модели", nameof(model.CarCost));
}
_logger.LogInformation("Car. CarBrand:{CarBrand}.CarModel:{ CarModel}.CarCost:{CarCost}. Id: { Id}", model.CarBrand, model.CarModel, model.CarCost, model.Id);
}
}
}

View File

@ -0,0 +1,179 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using CarCenterDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class CompletionsLogic : ICompletionsLogic
{
private readonly ILogger _logger;
private readonly ICompletionsStorage _CompletionsStorage;
public CompletionsLogic(ILogger<CompletionsLogic> logger, ICompletionsStorage CompletionsStorage)
{
_logger = logger;
_CompletionsStorage = CompletionsStorage;
}
public bool Create(CompletionsBindingModel model)
{
CheckModel(model);
model.СompletionCars = new();
var result = _CompletionsStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(CompletionsBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _CompletionsStorage.Delete(model);
if (result == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public CompletionsViewModel? ReadElement(CopletionsSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. CompletionName:{CompletionName}.Id:{Id}", model.СompletionName, model.Id);
var element = _CompletionsStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<CompletionsViewModel>? ReadList(CopletionsSearchModel? model)
{
_logger.LogInformation("ReadList. CompletionName:{CompletionName}.Id:{ Id}", model?.СompletionName, model?.Id);
var list = model == null ? _CompletionsStorage.GetFullList() : _CompletionsStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Update(CompletionsBindingModel model)
{
CheckModel(model);
if (_CompletionsStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool AddCarToCompletions(CopletionsSearchModel model, ICarSalesModel car)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("AddCarToCompletions. CompletionName:{CompletionName}.Id:{ Id}", model.СompletionName, model.Id);
var element = _CompletionsStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddCarToCompletions element not found");
return false;
}
_logger.LogInformation("AddCarToCompletions find. Id:{Id}", element.Id);
element.СompletionCars[car.Id] = car;
_CompletionsStorage.Update(new()
{
Id = element.Id,
СompletionName = element.СompletionName,
СompletionFeatures = element.СompletionFeatures,
СompletionPrice = element.СompletionPrice,
AdministratorId = element.AdministratorId,
СompletionCars = element.СompletionCars,
});
return true;
}
private void CheckModel(CompletionsBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (decimal.Equals(model.СompletionPrice, 0))
{
throw new ArgumentNullException("Нет стоимости комплектации", nameof(model.СompletionPrice));
}
if (string.IsNullOrEmpty(model.СompletionName))
{
throw new ArgumentNullException("Нет названия комплектации", nameof(model.СompletionName));
}
if (string.IsNullOrEmpty(model.СompletionFeatures))
{
throw new ArgumentNullException("Нет особенностей комплектации", nameof(model.СompletionFeatures));
}
if (model.СompletionPrice < 0)
{
throw new ArgumentNullException("Стоимость не может быть меньше 0", nameof(model.СompletionPrice));
}
_logger.LogInformation("Completions. CompletionName:{CompletionName}.CompletionPrice:{ CompletionPrice}.СompletionFeatures:{ СompletionFeatures}. Id: { Id}", model.СompletionName, model.СompletionPrice, model.СompletionFeatures, model.Id);
}
}
}

View File

@ -0,0 +1,163 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using CarCenterDataModels.Models;
using Microsoft.Extensions.Logging;
using System.IO.Packaging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class EmployeeLogic : IEmployeeLogic
{
private readonly ILogger _logger;
private readonly IEmployeeStorage _employeeStorage;
private readonly IManagerLogic _managerLogic;
public EmployeeLogic(ILogger<EmployeeLogic> logger, IEmployeeStorage EmployeeStorage, IManagerLogic ManagerLogic)
{
_logger = logger;
_employeeStorage = EmployeeStorage;
_managerLogic = ManagerLogic;
}
public bool Create(EmployeeBindingModel model)
{
CheckModel(model);
model.EmployeeSales = new();
var result = _employeeStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(EmployeeBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _employeeStorage.Delete(model);
if (result == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public EmployeeViewModel? ReadElement(EmployeeSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. EmployeeFIO:{EmployeeFIO}.Id:{Id}", model.EmployeeFIO, model.Id);
var element = _employeeStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<EmployeeViewModel>? ReadList(EmployeeSearchModel? model)
{
_logger.LogInformation("ReadList. EmployeeFIO:{EmployeeFIO}.Id:{ Id}", model?.EmployeeFIO, model?.Id);
var list = model == null ? _employeeStorage.GetFullList() : _employeeStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool AddSaleToEmployee(EmployeeSearchModel model, ISaleModel Sale)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("AddSaleToEmployee. EmployeeFIO:{EmployeeFIO}.Id:{ Id}", model.EmployeeFIO, model.Id);
var element = _employeeStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddSaleToEmployee element not found");
return false;
}
_logger.LogInformation("AddSaleToEmployee find. Id:{Id}", element.Id);
element.EmployeeSales[Sale.Id] = Sale;
_employeeStorage.Update(new()
{
Id = element.Id,
EmployeeFIO = element.EmployeeFIO,
EmployeePost = element.EmployeePost,
EmployeeSalary = element.EmployeeSalary,
ManagerId = element.ManagerId,
EmployeeSales = element.EmployeeSales,
});
return true;
}
public bool Update(EmployeeBindingModel model)
{
CheckModel(model);
if (_employeeStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(EmployeeBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.EmployeeFIO))
{
throw new ArgumentNullException("Нет ФИО сотрудника", nameof(model.EmployeeFIO));
}
_logger.LogInformation("Employee. EmployeeFIO:{EmployeeFIO}.EmployeePost:{ EmployeePost}. Id: { Id}", model.EmployeeFIO, model.EmployeePost, model.Id);
}
}
}

View File

@ -0,0 +1,172 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using CarCenterDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class InspectionLogic : IInspectionLogic
{
private readonly ILogger _logger;
private readonly IInspectionStorage _inspectionStorage;
public InspectionLogic(ILogger<InspectionLogic> logger, IInspectionStorage inspectionStorage)
{
_logger = logger;
_inspectionStorage = inspectionStorage;
}
public bool Create(InspectionBindingModel model)
{
CheckModel(model);
model.InspectionCars = new();
var result = _inspectionStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(InspectionBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _inspectionStorage.Delete(model);
if (result == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public InspectionViewModel? ReadElement(InspectionSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. Id:{Id}", model.Id);
var element = _inspectionStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<InspectionViewModel>? ReadList(InspectionSearchModel? model)
{
_logger.LogInformation("ReadList. Id:{ Id}", model?.Id);
var list = model == null ? _inspectionStorage.GetFullList() : _inspectionStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Update(InspectionBindingModel model)
{
CheckModel(model);
if (_inspectionStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool AddCarToInspection(InspectionSearchModel model, ICarSalesModel car)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("AddCarToInspection. InspectionName:{InspectionName}.Id:{ Id}", model.InspectionName, model.Id);
var element = _inspectionStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddCarToInspection element not found");
return false;
}
_logger.LogInformation("AddCarToInspection find. Id:{Id}", element.Id);
element.InspectionCars[car.Id] = car;
_inspectionStorage.Update(new()
{
Id = element.Id,
InspectionName = element.InspectionName,
InspectionCost = element.InspectionCost,
InspectionDate = element.InspectionDate,
AdministratorId = element.AdministratorId,
EmployeeId = element.EmployeeId,
InspectionCars = element.InspectionCars
});
return true;
}
private void CheckModel(InspectionBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.InspectionName))
{
throw new ArgumentNullException("Нет названия осмотра", nameof(model.InspectionName));
}
if ((model.InspectionCost) < 0)
{
throw new ArgumentNullException("Стоимость не может быть меньше нуля", nameof(model.InspectionCost));
}
_logger.LogInformation("Inspection. Id: { Id}", model.Id);
}
}
}

View File

@ -0,0 +1,173 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class ManagerLogic : IManagerLogic
{
private readonly int _loginMaxLength = 50;
private readonly int _passwordMaxLength = 50;
private readonly int _passwordMinLength = 10;
private readonly ILogger _logger;
private readonly IManagerStorage _managerStorage;
public ManagerLogic(ILogger<ManagerLogic> logger, IManagerStorage ManagerStorage)
{
_logger = logger;
_managerStorage = ManagerStorage;
}
public bool Create(ManagerBindingModel model)
{
CheckModel(model);
if (_managerStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(ManagerBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id: {Id}", model.Id);
if (_managerStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public ManagerViewModel? ReadElement(ManagerSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. ManagerFIO: {ManagerFIO}. ManagerLogin: {ManagerLogin}. Id: {Id}.", model.ManagerFIO, model.ManagerLogin, model.Id);
var element = _managerStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id: {Id}", element.Id);
return element;
}
public List<ManagerViewModel>? ReadList(ManagerSearchModel? model)
{
_logger.LogInformation("ReadList. ManagerFIO: {ManagerFIO}. ManagerLogin: {ManagerLogin}. Id: {Id}.", model?.ManagerFIO, model?.ManagerLogin, model?.Id);
var list = model == null ? _managerStorage.GetFullList() : _managerStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public bool Update(ManagerBindingModel model)
{
CheckModel(model);
if (_managerStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(ManagerBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ManagerFIO))
{
throw new ArgumentNullException("Нет ФИО менеджера", nameof(model.ManagerFIO));
}
if (string.IsNullOrEmpty(model.ManagerLogin))
{
throw new ArgumentNullException("Нет логина менеджера", nameof(model.ManagerLogin));
}
if (model.ManagerLogin.Length>_loginMaxLength)
{
throw new ArgumentNullException("Логин слишком длинный", nameof(model.ManagerLogin));
}
if (string.IsNullOrEmpty(model.ManagerNumber))
{
throw new ArgumentNullException("Нет номера телефона менеджера", nameof(model.ManagerNumber));
}
if (model.ManagerEmail.Length > _loginMaxLength || !Regex.IsMatch(model.ManagerEmail, @"([a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+)"))
{
throw new Exception($"В качестве логина должна быть указана почта и иметь длинну не более {_loginMaxLength} символов");
}
if (string.IsNullOrEmpty(model.ManagerEmail))
{
throw new ArgumentNullException("Нет почты менеджера", nameof(model.ManagerEmail));
}
if (string.IsNullOrEmpty(model.ManagerPassword))
{
throw new ArgumentNullException("Нет пароля менеджера", nameof(model.ManagerPassword));
}
if (model.ManagerPassword.Length > _passwordMaxLength || model.ManagerPassword.Length < _passwordMinLength
|| !Regex.IsMatch(model.ManagerPassword, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$"))
{
throw new Exception($"Пароль длиной от {_passwordMinLength} до {_passwordMaxLength} должен состоять из цифр, букв и небуквенных символов");
}
_logger.LogInformation("Manager. ManagerFIO: {ManagerFIO}. ManagerLogin: {ManagerLogin}. Id: {Id}", model.ManagerFIO, model.ManagerLogin, model.Id);
var element = _managerStorage.GetElement(new ManagerSearchModel
{
ManagerEmail = model.ManagerEmail
});
if (element != null && element.Id != model.Id)
{
throw new InvalidOperationException("менеджер с таким логином уже есть");
}
}
}
}

View File

@ -0,0 +1,178 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using CarCenterDataModels.Models;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class PreSaleWorkLogic : IPreSaleWorkLogic
{
private readonly ILogger _logger;
private readonly IPreSaleWorkStorage _PreSaleWorkStorage;
private readonly IManagerLogic _managerLogic;
public PreSaleWorkLogic(ILogger<PreSaleWorkLogic> logger, IPreSaleWorkStorage PreSaleWorkStorage, IManagerLogic ManagerLogic)
{
_logger = logger;
_PreSaleWorkStorage = PreSaleWorkStorage;
_managerLogic = ManagerLogic;
}
public bool AddSaleToPreSaleWork(PreSaleWorkSearchModel model, ISaleModel Sale)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("AddSaleToPreSaleWork. PreSaleWorkType:{PreSaleWorkType}.Id:{ Id}", model.PreSaleWorkType, model.Id);
var element = _PreSaleWorkStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddSaleToPreSaleWork element not found");
return false;
}
_logger.LogInformation("AddSaleToPreSaleWork find. Id:{Id}", element.Id);
element.PreSaleWorkSales[Sale.Id] = Sale;
_PreSaleWorkStorage.Update(new()
{
Id = element.Id,
PreSaleWorkType = element.PreSaleWorkType,
PreSaleWorkPrice = element.PreSaleWorkPrice,
PreSaleWorkDate = element.PreSaleWorkDate,
ManagerId = element.ManagerId,
CompletionsId = element.CompletionsId,
PreSaleWorkSales = element.PreSaleWorkSales
});
return true;
}
public bool Create(PreSaleWorkBindingModel model)
{
CheckModel(model);
model.PreSaleWorkSales = new();
var result = _PreSaleWorkStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(PreSaleWorkBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _PreSaleWorkStorage.Delete(model);
if (result== null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public PreSaleWorkViewModel? ReadElement(PreSaleWorkSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. PreSaleWorkType:{PreSaleWorkType}.Id:{Id}", model.PreSaleWorkType, model.Id);
var element = _PreSaleWorkStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<PreSaleWorkViewModel>? ReadList(PreSaleWorkSearchModel? model)
{
_logger.LogInformation("ReadList. PreSaleWorkType:{PreSaleWorkType}.Id:{ Id}", model?.PreSaleWorkType, model?.Id);
var list = model == null ? _PreSaleWorkStorage.GetFullList() : _PreSaleWorkStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Update(PreSaleWorkBindingModel model)
{
CheckModel(model);
if (_PreSaleWorkStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(PreSaleWorkBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.PreSaleWorkType))
{
throw new ArgumentNullException("Нет такого типа предпродажной работы", nameof(model.PreSaleWorkType));
}
if (model.PreSaleWorkPrice<0)
{
throw new ArgumentNullException("Стоимость предпродажной работы не может быть меньше 0", nameof(model.PreSaleWorkPrice));
}
_logger.LogInformation("PreSaleWork. PreSaleWorkType:{PreSaleWorkType}.PreSaleWorkPrice:{ PreSaleWorkPrice}. Id: { Id}", model.PreSaleWorkType, model.PreSaleWorkPrice, model.Id);
var element = _PreSaleWorkStorage.GetElement(new PreSaleWorkSearchModel
{
PreSaleWorkType = model.PreSaleWorkType
});
if (element != null && element.Id != model.Id)
{
throw new InvalidOperationException("Предпродажная работа с таким типом уже есть");
}
}
}
}

View File

@ -0,0 +1,131 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterContracts.StoragesContracts;
using CarCenterContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace CarCenterBusinessLogic.BusinessLogics
{
public class SaleLogic : ISaleLogic
{
private readonly ILogger _logger;
private readonly ISaleStorage _SaleStorage;
private readonly IManagerLogic _managerLogic;
public SaleLogic(ILogger<SaleLogic> logger, ISaleStorage SaleStorage, IManagerLogic ManagerLogic)
{
_logger = logger;
_SaleStorage = SaleStorage;
_managerLogic = ManagerLogic;
}
public bool Create(SaleBindingModel model)
{
CheckModel(model);
var result = _SaleStorage.Insert(model);
if (result == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Delete(SaleBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
var result = _SaleStorage.Delete(model);
if (result == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public SaleViewModel? ReadElement(SaleSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. SaleFIO:{SaleFIO}.Id:{Id}", model.SaleDate, model.Id);
var element = _SaleStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public List<SaleViewModel>? ReadList(SaleSearchModel? model)
{
_logger.LogInformation("ReadList. SaleFIO:{SaleFIO}.Id:{ Id}", model?.SaleDate, model?.Id);
var list = model == null ? _SaleStorage.GetFullList() : _SaleStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Update(SaleBindingModel model)
{
CheckModel(model);
if (_SaleStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
private void CheckModel(SaleBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.SaleName))
{
throw new ArgumentNullException("Не указано название продажи", nameof(model.SalePrice));
}
if (model.SalePrice < 0)
{
throw new ArgumentNullException("Стоимость продажи не может быть меньше нуля", nameof(model.SalePrice));
}
_logger.LogInformation("Sale. SaleDate:{SaleDate}.SalePrice:{ SalePrice}. Id: { Id}", model.SaleDate, model.SalePrice, model.Id);
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CarCenterContracts\CarCenterContracts.csproj" />
<ProjectReference Include="..\CarCenterDataModels\CarCenterDataModels.csproj" />
</ItemGroup>
</Project>

View File

@ -10,7 +10,7 @@ namespace CarCenterContracts.BindingModels
public string EmployeePost { get; set; } = string.Empty;
public string EmployeeSalary { get; set; } = string.Empty;
public decimal EmployeeSalary { get; set; }
public int ManagerId { get; set; }

View File

@ -9,10 +9,10 @@ using System.Threading.Tasks;
namespace CarCenterContracts.BusinessLogicsContracts
{
public interface ICarLogic
public interface ICarSalesLogic
{
List<CarViewModel>? ReadList(CarSearchModel? model);
CarViewModel? ReadElement(CarSearchModel model);
List<CarSalesViewModel>? ReadList(CarSalesSearchModel? model);
CarSalesViewModel? ReadElement(CarSalesSearchModel model);
bool Create(CarSalesBindingModel model);
bool Update(CarSalesBindingModel model);
bool Delete(CarSalesBindingModel model);

View File

@ -10,13 +10,13 @@ using System.Threading.Tasks;
namespace CarCenterContracts.BusinessLogicsContracts
{
public interface IEquipmentLogic
public interface ICompletionsLogic
{
List<EquipmentViewModel>? ReadList(EquipmentSearchModel? model);
EquipmentViewModel? ReadElement(EquipmentSearchModel model);
List<CompletionsViewModel>? ReadList(CopletionsSearchModel? model);
CompletionsViewModel? ReadElement(CopletionsSearchModel model);
bool Create(CompletionsBindingModel model);
bool Update(CompletionsBindingModel model);
bool Delete(CompletionsBindingModel model);
bool AddCarToEquipment(EquipmentSearchModel model, ICarModel car);
bool AddCarToCompletions(CopletionsSearchModel model, ICarSalesModel car);
}
}

View File

@ -17,6 +17,6 @@ namespace CarCenterContracts.BusinessLogicsContracts
bool Create(InspectionBindingModel model);
bool Update(InspectionBindingModel model);
bool Delete(InspectionBindingModel model);
bool AddCarToInspection(InspectionSearchModel model, ICarModel car);
bool AddCarToInspection(InspectionSearchModel model, ICarSalesModel car);
}
}

View File

@ -6,6 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CarCenterDataModels\CarCenterDataModels.csproj" />
</ItemGroup>

View File

@ -6,11 +6,12 @@ using System.Threading.Tasks;
namespace CarCenterContracts.SearchModels
{
public class CarSearchModel
public class CarSalesSearchModel
{
public int? Id { get; set; }
public string? BrandCar { get; set; }
public string? Model { get; set; }
public string? CarBrand { get; set; }
public string? CarModel { get; set; }
public decimal? CarCost { get; set; }
public int? AdministratorId { get; set; }
}
}

View File

@ -6,11 +6,12 @@ using System.Threading.Tasks;
namespace CarCenterContracts.SearchModels
{
public class EquipmentSearchModel
public class CopletionsSearchModel
{
public int? Id { get; set; }
public string? EquipmentName { get; set; }
public string? СompletionName { get; set; }
public string? СompletionFeatures { get; set; }
public decimal? СompletionPrice { get; set; }
public int? AdministratorId { get; set; }
public int? PreSaleWorkId { get; set; }
}
}

View File

@ -4,9 +4,8 @@
{
public int? Id { get; set; }
public string? EmployeeFIO { get; set; }
public string? Specialization { get; set; }
public string? EmployeePost { get; set; }
public string? EmployeeSalary { get; set; }
public int? ManagerId { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
}
}

View File

@ -11,6 +11,7 @@ namespace CarCenterContracts.SearchModels
{
public int? Id { get; set; }
public string? InspectionName { get; set; }
public decimal? InspectionCost { get; set; }
public DateTime? InspectionDate { get; set; }
public int? AdministratorId { get; set; }
public int? EmployeeId { get; set; }

View File

@ -4,8 +4,9 @@
{
public int? Id { get; set; }
public string? PreSaleWorkType { get; set; }
public decimal? PreSaleWorkPrice { get; set; }
public DateTime? PreSaleWorkDate { get; set; }
public int? ManagerId { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
public int? CompletionsId { get; set; }
}
}

View File

@ -3,6 +3,8 @@
public class SaleSearchModel
{
public int? Id { get; set; }
public string? SaleName { get; set; }
public decimal? SalePrice { get; set; }
public DateTime? SaleDate { get; set; }
public int? ManagerId { get; set; }
}

View File

@ -0,0 +1,26 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.SearchModels;
using CarCenterContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CarCenterContracts.StoragesContracts
{
public interface ICarSalesStorage
{
List<CarSalesViewModel> GetFullList();
List<CarSalesViewModel> GetFilteredList(CarSalesSearchModel model);
CarSalesViewModel? GetElement(CarSalesSearchModel model);
CarSalesViewModel? Insert(CarSalesBindingModel model);
CarSalesViewModel? Update(CarSalesBindingModel model);
CarSalesViewModel? Delete(CarSalesBindingModel model);
}
}

View File

@ -1,26 +0,0 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.SearchModels;
using CarCenterContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CarCenterContracts.StoragesContracts
{
public interface ICarStorage
{
List<CarViewModel> GetFullList();
List<CarViewModel> GetFilteredList(CarSearchModel model);
CarViewModel? GetElement(CarSearchModel model);
CarViewModel? Insert(CarSalesBindingModel model);
CarViewModel? Update(CarSalesBindingModel model);
CarViewModel? Delete(CarSalesBindingModel model);
}
}

View File

@ -0,0 +1,26 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.SearchModels;
using CarCenterContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CarCenterContracts.StoragesContracts
{
public interface ICompletionsStorage
{
List<CompletionsViewModel> GetFullList();
List<CompletionsViewModel> GetFilteredList(CopletionsSearchModel model);
CompletionsViewModel? GetElement(CopletionsSearchModel model);
CompletionsViewModel? Insert(CompletionsBindingModel model);
CompletionsViewModel? Update(CompletionsBindingModel model);
CompletionsViewModel? Delete(CompletionsBindingModel model);
}
}

View File

@ -1,26 +0,0 @@
using CarCenterContracts.BindingModels;
using CarCenterContracts.SearchModels;
using CarCenterContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CarCenterContracts.StoragesContracts
{
public interface IEquipmentStorage
{
List<EquipmentViewModel> GetFullList();
List<EquipmentViewModel> GetFilteredList(EquipmentSearchModel model);
EquipmentViewModel? GetElement(EquipmentSearchModel model);
EquipmentViewModel? Insert(CompletionsBindingModel model);
EquipmentViewModel? Update(CompletionsBindingModel model);
EquipmentViewModel? Delete(CompletionsBindingModel model);
}
}

View File

@ -8,15 +8,18 @@ using System.Threading.Tasks;
namespace CarCenterContracts.ViewModels
{
public class CarViewModel : ICarModel
public class CarSalesViewModel : ICarSalesModel
{
public int Id { get; set; }
[DisplayName("Бренд машины")]
public string BrandCar { get; set; } = string.Empty;
public string CarBrand { get; set; } = string.Empty;
[DisplayName("Модель машины")]
public string Model { get; set; } = string.Empty;
public string CarModel { get; set; } = string.Empty;
[DisplayName("Стоимость машины")]
public decimal CarCost { get; set; }
public int AdministratorId { get; set; }
}
}

View File

@ -8,17 +8,20 @@ using System.Threading.Tasks;
namespace CarCenterContracts.ViewModels
{
public class EquipmentViewModel : IEquipmentModel
public class CompletionsViewModel : IСompletionsModel
{
public int Id { get; set; }
[DisplayName("Название комплектации")]
public string EquipmentName { get; set; } = string.Empty;
public string СompletionName { get; set; } = string.Empty;
[DisplayName("Особенности комплектации")]
public string СompletionFeatures { get; set; } = string.Empty;
[DisplayName("Цена комплектации")]
public double EquipmentPrice { get; set; }
public decimal СompletionPrice { get; set; }
public int AdministratorId { get; set; }
public int? PreSaleWorkId { get; set; }
public Dictionary<int, ICarModel> EquipmentCars { get; set; } = new();
public Dictionary<int, ICarSalesModel> СompletionCars { get; set; } = new();
}
}

View File

@ -9,8 +9,11 @@ namespace CarCenterContracts.ViewModels
[DisplayName("ФИО Сотрудника")]
public string EmployeeFIO { get; set; } = string.Empty;
[DisplayName("Специализация")]
public string Specialization { get; set; } = string.Empty;
[DisplayName("Должность")]
public string EmployeePost { get; set; } = string.Empty;
[DisplayName("Заработная плата")]
public decimal EmployeeSalary { get; set; }
public int ManagerId { get; set; }

View File

@ -15,12 +15,15 @@ namespace CarCenterContracts.ViewModels
[DisplayName("Название осмотра")]
public string InspectionName { get; set; } = string.Empty;
[DisplayName("Стоимость осмотра")]
public decimal InspectionCost { get; set; }
[DisplayName("Дата осмотра")]
public DateTime? InspectionDate { get; set; }
public int AdministratorId { get; set; }
public int? EmployeeId { get; set; }
public int EmployeeId { get; set; }
public string EmployeeName { get; set; } = string.Empty;
public Dictionary<int, ICarModel> InspectionCars { get; set; } = new();
public Dictionary<int, ICarSalesModel> InspectionCars { get; set; } = new();
}
}

View File

@ -10,22 +10,27 @@ namespace CarCenterContracts.ViewModels
public string PreSaleWorkType { get; set; } = string.Empty;
[DisplayName("Стоимость предпродажной работы")]
public double PreSaleWorkPrice { get; set; }
public decimal PreSaleWorkPrice { get; set; }
[DisplayName("Дата предпродажной работы")]
public DateTime? PreSaleWorkDate { get; set; }
public int ManagerId { get; set; }
public int CompletionsId { get; set; }
public int Id { get; set; }
public Dictionary<int, ISaleModel> PreSaleWorkSales { get; set; } = new();
public Dictionary<int, ICarModel> PreSaleWorkCars { get; set; } = new();
public Dictionary<int, ICarSalesModel> PreSaleWorkCars { get; set; } = new();
public PreSaleWorkViewModel() { }
[JsonConstructor]
public PreSaleWorkViewModel(Dictionary<int, SaleViewModel> PreSaleWorkSales, Dictionary<int, CarViewModel> PreSaleWorkCars)
public PreSaleWorkViewModel(Dictionary<int, SaleViewModel> PreSaleWorkSales, Dictionary<int, CarSalesViewModel> PreSaleWorkCars)
{
this.PreSaleWorkSales = PreSaleWorkSales.ToDictionary(x => x.Key, x => x.Value as ISaleModel);
this.PreSaleWorkCars = PreSaleWorkCars.ToDictionary(x => x.Key, x => x.Value as ICarModel);
this.PreSaleWorkCars = PreSaleWorkCars.ToDictionary(x => x.Key, x => x.Value as ICarSalesModel);
}
}
}

View File

@ -7,12 +7,15 @@ namespace CarCenterContracts.ViewModels
{
public int Id { get; set; }
[DisplayName("Название продажи")]
public string SaleName { get; set; } = string.Empty;
[DisplayName("Стоимость продажи")]
public decimal SalePrice { get; set; }
[DisplayName("Дата продажи")]
public DateTime? SaleDate { get; set; }
[DisplayName("Цена продажи")]
public string SalePrice { get; set; } = string.Empty;
public int ManagerId { get; set; }
}
}

View File

@ -4,7 +4,7 @@
{
string EmployeeFIO { get; }
string EmployeePost { get; }
string EmployeeSalary { get; }
decimal EmployeeSalary { get; }
int ManagerId { get; }
public Dictionary<int, ISaleModel> EmployeeSales { get; }
}