Compare commits

2 Commits
main ... Roman

Author SHA1 Message Date
73b45216f8 База данных 2025-06-03 12:04:08 +04:00
ec374a18a4 чето 2025-05-22 19:44:56 +04:00
48 changed files with 2981 additions and 204 deletions

View File

@@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -9,19 +9,19 @@ namespace HookArmsBusinessLogic.Implemetations;
public class MaintenanceBusinessLogic : IMaintenanceBusinessLogic public class MaintenanceBusinessLogic : IMaintenanceBusinessLogic
{ {
private readonly IMaintenanceStorageContract _storage; private readonly IMaintenanceStorageContract _maintenanceStorage;
private readonly ICarStorageContract _machineStorage; private readonly ICarStorageContract _carStorage;
private readonly IWorkStorageContract _workStorage; private readonly IWorkStorageContract _workStorage;
private readonly ILogger<MaintenanceBusinessLogic> _logger; private readonly ILogger<MaintenanceBusinessLogic> _logger;
public MaintenanceBusinessLogic( public MaintenanceBusinessLogic(
IMaintenanceStorageContract storage, IMaintenanceStorageContract maintenanceStorage,
ICarStorageContract machineStorage, ICarStorageContract carStorage,
IWorkStorageContract workStorage, IWorkStorageContract workStorage,
ILogger<MaintenanceBusinessLogic> logger) ILogger<MaintenanceBusinessLogic> logger)
{ {
_storage = storage; _maintenanceStorage = maintenanceStorage;
_machineStorage = machineStorage; _carStorage = carStorage;
_workStorage = workStorage; _workStorage = workStorage;
_logger = logger; _logger = logger;
} }
@@ -29,74 +29,157 @@ public class MaintenanceBusinessLogic : IMaintenanceBusinessLogic
public List<MaintenanceDataModel> GetAll() public List<MaintenanceDataModel> GetAll()
{ {
_logger.LogInformation("Запрос всех ТО"); _logger.LogInformation("Запрос всех ТО");
return _storage.GetList(); return _maintenanceStorage.GetList();
} }
public MaintenanceDataModel GetById(string id) public MaintenanceDataModel GetById(string id)
{ {
if (id.IsEmpty() || !id.IsGuid()) if (id.IsEmpty() || !id.IsGuid())
{
_logger.LogError($"Некорректный ID ТО: {id}");
throw new ValidationException("Некорректный ID ТО"); throw new ValidationException("Некорректный ID ТО");
}
var maintenance = _storage.GetById(id); var maintenance = _maintenanceStorage.GetById(id);
return maintenance ?? throw new ElementNotFoundException($"ТО с ID {id} не найден"); if (maintenance == null)
{
_logger.LogError($"ТО с ID {id} не найдено");
throw new ElementNotFoundException($"ТО с ID {id} не найдено");
}
return maintenance;
} }
public void Add(MaintenanceDataModel maintenance) public void Add(MaintenanceDataModel maintenance)
{ {
// Валидация модели try
maintenance.Validate();
// Проверка существования машины
var machine = _machineStorage.GetById(maintenance.MachineId);
if (machine == null)
throw new ElementNotFoundException($"Машина {maintenance.MachineId} не найдена");
// Проверка существования работ
foreach (var work in maintenance.Works)
{ {
var existingWork = _workStorage.GetById(work.Id); _logger.LogInformation($"Добавление ТО с ID {maintenance.Id}");
if (existingWork == null)
throw new ElementNotFoundException($"Работа {work.Id} не найдена");
}
// Добавление в хранилище // Валидация модели
_storage.Add(maintenance); maintenance.Validate();
_logger.LogInformation($"Добавлено ТО: {maintenance.Id}");
// Проверка существования машины
var car = _carStorage.GetById(maintenance.MachineId);
if (car == null)
{
_logger.LogError($"Автомобиль с ID {maintenance.MachineId} не найден");
throw new ElementNotFoundException($"Автомобиль с ID {maintenance.MachineId} не найден");
}
// Проверка существования заказчика
if (!_maintenanceStorage.GetList().Any(c => c.CustomerId == maintenance.CustomerId))
{
_logger.LogError($"Заказчик с ID {maintenance.CustomerId} не найден");
throw new ElementNotFoundException($"Заказчик с ID {maintenance.CustomerId} не найден");
}
// Проверка и добавление работ
if (maintenance.MaintenanceWorks != null && maintenance.MaintenanceWorks.Any())
{
foreach (var maintenanceWork in maintenance.MaintenanceWorks)
{
var work = _workStorage.GetById(maintenanceWork.WorkId);
if (work == null)
{
_logger.LogError($"Работа с ID {maintenanceWork.WorkId} не найдена");
throw new ElementNotFoundException($"Работа с ID {maintenanceWork.WorkId} не найдена");
}
maintenanceWork.Validate();
}
}
else
{
_logger.LogWarning("ТО не содержит работ");
throw new ValidationException("ТО должно включать хотя бы одну работу");
}
// Добавление в хранилище
_maintenanceStorage.Add(maintenance);
_logger.LogInformation($"ТО с ID {maintenance.Id} успешно добавлено");
}
catch (Exception ex)
{
_logger.LogError($"Ошибка при добавлении ТО с ID {maintenance.Id}: {ex.Message}");
throw;
}
} }
public void Update(MaintenanceDataModel maintenance) public void Update(MaintenanceDataModel maintenance)
{ {
// Проверка существования записи try
var existingMaintenance = GetById(maintenance.Id);
// Валидация модели
maintenance.Validate();
// Обновление машины (если изменился ID)
if (existingMaintenance.MachineId != maintenance.MachineId)
{ {
var newMachine = _machineStorage.GetById(maintenance.MachineId); _logger.LogInformation($"Обновление ТО с ID {maintenance.Id}");
if (newMachine == null)
throw new ElementNotFoundException($"Машина {maintenance.MachineId} не найдена");
}
// Обновление работ // Проверка существования записи
foreach (var work in maintenance.Works) var existingMaintenance = GetById(maintenance.Id);
// Валидация модели
maintenance.Validate();
// Проверка автомобиля
if (existingMaintenance.MachineId != maintenance.MachineId)
{
var newCar = _carStorage.GetById(maintenance.MachineId);
if (newCar == null)
{
_logger.LogError($"Автомобиль с ID {maintenance.MachineId} не найден");
throw new ElementNotFoundException($"Автомобиль с ID {maintenance.MachineId} не найден");
}
}
// Проверка заказчика
if (!_maintenanceStorage.GetList().Any(c => c.CustomerId == maintenance.CustomerId))
{
_logger.LogError($"Заказчик с ID {maintenance.CustomerId} не найден");
throw new ElementNotFoundException($"Заказчик с ID {maintenance.CustomerId} не найден");
}
// Обновление работ
if (maintenance.MaintenanceWorks != null && maintenance.MaintenanceWorks.Any())
{
foreach (var maintenanceWork in maintenance.MaintenanceWorks)
{
var work = _workStorage.GetById(maintenanceWork.WorkId);
if (work == null)
{
_logger.LogError($"Работа с ID {maintenanceWork.WorkId} не найдена");
throw new ElementNotFoundException($"Работа с ID {maintenanceWork.WorkId} не найдена");
}
maintenanceWork.Validate();
}
}
else
{
_logger.LogWarning("ТО не содержит работ");
throw new ValidationException("ТО должно включать хотя бы одну работу");
}
// Сохранение изменений
_maintenanceStorage.Update(maintenance);
_logger.LogInformation($"ТО с ID {maintenance.Id} успешно обновлено");
}
catch (Exception ex)
{ {
var existingWork = _workStorage.GetById(work.Id); _logger.LogError($"Ошибка при обновлении ТО с ID {maintenance.Id}: {ex.Message}");
if (existingWork == null) throw;
throw new ElementNotFoundException($"Работа {work.Id} не найдена");
} }
// Сохранение изменений
_storage.Update(maintenance);
_logger.LogInformation($"Обновлено ТО: {maintenance.Id}");
} }
public void Delete(string id) public void Delete(string id)
{ {
var maintenance = GetById(id); try
_storage.Delete(id); {
_logger.LogInformation($"Удалено ТО: {id}"); _logger.LogInformation($"Удаление ТО с ID {id}");
var maintenance = GetById(id);
_maintenanceStorage.Delete(id);
_logger.LogInformation($"ТО с ID {id} успешно удалено");
}
catch (Exception ex)
{
_logger.LogError($"Ошибка при удалении ТО с ID {id}: {ex.Message}");
throw;
}
} }
} }

View File

@@ -9,59 +9,179 @@ namespace HookArmsBusinessLogic.Implemetations;
public class RepairBusinessLogic : IRepairBusinessLogic public class RepairBusinessLogic : IRepairBusinessLogic
{ {
private readonly IRepairStorageContract _storage; private readonly IRepairStorageContract _repairStorage;
private readonly ISparePartStorageContract _sparePartStorage; private readonly ISparePartStorageContract _sparePartStorage;
private readonly IExecutorStorageContract _executorStorage;
private readonly ILogger<RepairBusinessLogic> _logger; private readonly ILogger<RepairBusinessLogic> _logger;
public RepairBusinessLogic( public RepairBusinessLogic(
IRepairStorageContract storage, IRepairStorageContract repairStorage,
ISparePartStorageContract sparePartStorage, ISparePartStorageContract sparePartStorage,
IExecutorStorageContract executorStorage,
ILogger<RepairBusinessLogic> logger) ILogger<RepairBusinessLogic> logger)
{ {
_storage = storage; _repairStorage = repairStorage;
_sparePartStorage = sparePartStorage; _sparePartStorage = sparePartStorage;
_executorStorage = executorStorage;
_logger = logger; _logger = logger;
} }
public void Add(RepairDataModel repair) public void Add(RepairDataModel repair)
{ {
repair.Validate(); try
foreach (var part in repair.SpareParts)
{ {
var existingPart = _sparePartStorage.GetById(part.Id); _logger.LogInformation($"Добавление ремонта с ID {repair.Id}");
if (existingPart == null || existingPart.Stock < existingPart.Stock - 1)
throw new ValidationException($"Недостаточно запчасти: {part.Name}");
}
_storage.Add(repair); // Валидация модели
_logger.LogInformation($"Добавлен ремонт: {repair.Id}"); repair.Validate();
// Проверка существования исполнителя
var executor = _executorStorage.GetById(repair.WorkerId);
if (executor == null)
{
_logger.LogError($"Исполнитель с ID {repair.WorkerId} не найден");
throw new ElementNotFoundException($"Исполнитель с ID {repair.WorkerId} не найден");
}
// Проверка запасных частей
if (repair.RepairSpareParts != null && repair.RepairSpareParts.Any())
{
foreach (var repairSparePart in repair.RepairSpareParts)
{
var sparePart = _sparePartStorage.GetById(repairSparePart.SparePartId);
if (sparePart == null)
{
_logger.LogError($"Запасная часть с ID {repairSparePart.SparePartId} не найдена");
throw new ElementNotFoundException($"Запасная часть с ID {repairSparePart.SparePartId} не найдена");
}
if (sparePart.Stock < repairSparePart.Quantity)
{
_logger.LogError($"Недостаточно запасной части {sparePart.Name} на складе: {sparePart.Stock} < {repairSparePart.Quantity}");
throw new ValidationException($"Недостаточно запасной части: {sparePart.Name}");
}
repairSparePart.Validate();
}
}
else
{
_logger.LogWarning("Ремонт не содержит запасных частей");
throw new ValidationException("Ремонт должен включать хотя бы одну запасную часть");
}
// Добавление ремонта
_repairStorage.Add(repair);
_logger.LogInformation($"Ремонт с ID {repair.Id} успешно добавлен");
}
catch (Exception ex)
{
_logger.LogError($"Ошибка при добавлении ремонта с ID {repair.Id}: {ex.Message}");
throw;
}
} }
public List<RepairDataModel> GetAll() => _storage.GetList(); public List<RepairDataModel> GetAll()
{
_logger.LogInformation("Запрос всех ремонтов");
return _repairStorage.GetList();
}
public RepairDataModel GetById(string id) public RepairDataModel GetById(string id)
{ {
if (string.IsNullOrEmpty(id) || !id.IsGuid()) if (id.IsEmpty() || !id.IsGuid())
throw new ValidationException("Некорректный ID"); {
_logger.LogError($"Некорректный ID ремонта: {id}");
throw new ValidationException("Некорректный ID ремонта");
}
return _storage.GetById(id) ?? throw new ElementNotFoundException("Неисправность не найдена"); var repair = _repairStorage.GetById(id);
if (repair == null)
{
_logger.LogError($"Ремонт с ID {id} не найден");
throw new ElementNotFoundException($"Ремонт с ID {id} не найден");
}
return repair;
} }
public void Update(RepairDataModel malfunction) public void Update(RepairDataModel repair)
{ {
malfunction.Validate(); try
_storage.Update(malfunction); {
_logger.LogInformation($"Обновлена неисправность: {malfunction.Id}"); _logger.LogInformation($"Обновление ремонта с ID {repair.Id}");
// Проверка существования записи
var existingRepair = GetById(repair.Id);
// Валидация модели
repair.Validate();
// Проверка исполнителя
if (existingRepair.WorkerId != repair.WorkerId)
{
var newExecutor = _executorStorage.GetById(repair.WorkerId);
if (newExecutor == null)
{
_logger.LogError($"Исполнитель с ID {repair.WorkerId} не найден");
throw new ElementNotFoundException($"Исполнитель с ID {repair.WorkerId} не найден");
}
}
// Проверка запасных частей
if (repair.RepairSpareParts != null && repair.RepairSpareParts.Any())
{
foreach (var repairSparePart in repair.RepairSpareParts)
{
var sparePart = _sparePartStorage.GetById(repairSparePart.SparePartId);
if (sparePart == null)
{
_logger.LogError($"Запасная часть с ID {repairSparePart.SparePartId} не найдена");
throw new ElementNotFoundException($"Запасная часть с ID {repairSparePart.SparePartId} не найдена");
}
if (sparePart.Stock < repairSparePart.Quantity)
{
_logger.LogError($"Недостаточно запасной части {sparePart.Name} на складе: {sparePart.Stock} < {repairSparePart.Quantity}");
throw new ValidationException($"Недостаточно запасной части: {sparePart.Name}");
}
repairSparePart.Validate();
}
}
else
{
_logger.LogWarning("Ремонт не содержит запасных частей");
throw new ValidationException("Ремонт должен включать хотя бы одну запасную часть");
}
// Обновление ремонта
_repairStorage.Update(repair);
_logger.LogInformation($"Ремонт с ID {repair.Id} успешно обновлён");
}
catch (Exception ex)
{
_logger.LogError($"Ошибка при обновлении ремонта с ID {repair.Id}: {ex.Message}");
throw;
}
} }
public void Delete(string id) public void Delete(string id)
{ {
if (string.IsNullOrEmpty(id) || !id.IsGuid()) try
throw new ValidationException("Некорректный ID"); {
_logger.LogInformation($"Удаление ремонта с ID {id}");
_storage.Delete(id); if (id.IsEmpty() || !id.IsGuid())
_logger.LogInformation($"Удалена неисправность: {id}"); {
_logger.LogError($"Некорректный ID ремонта: {id}");
throw new ValidationException("Некорректный ID ремонта");
}
var repair = GetById(id);
_repairStorage.Delete(id);
_logger.LogInformation($"Ремонт с ID {id} успешно удалён");
}
catch (Exception ex)
{
_logger.LogError($"Ошибка при удалении ремонта с ID {id}: {ex.Message}");
throw;
}
} }
} }

View File

@@ -5,10 +5,12 @@ VisualStudioVersion = 17.13.35931.197
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsContract", "HookArmsContract\HookArmsContract.csproj", "{4C45A966-16A2-408B-9037-A73954965D11}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsContract", "HookArmsContract\HookArmsContract.csproj", "{4C45A966-16A2-408B-9037-A73954965D11}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsDatabase", "HookArmsDatabase\HookArmsDatabase.csproj", "{23DCE4A6-B06B-44E5-ACCF-C85EAC80178F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsBusinessLogic", "HookArmsBusinessLogic\HookArmsBusinessLogic.csproj", "{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsBusinessLogic", "HookArmsBusinessLogic\HookArmsBusinessLogic.csproj", "{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsDataBase", "HookArmsDataBase\HookArmsDataBase.csproj", "{B41CCA3E-34B0-4B29-90BC-1BE2A3EFF4BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HookArmsWebApi", "HookArmsWebApi\HookArmsWebApi.csproj", "{ACD38119-D0AD-4903-B96C-C8B64C3F5AC6}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -19,14 +21,18 @@ Global
{4C45A966-16A2-408B-9037-A73954965D11}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C45A966-16A2-408B-9037-A73954965D11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C45A966-16A2-408B-9037-A73954965D11}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C45A966-16A2-408B-9037-A73954965D11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C45A966-16A2-408B-9037-A73954965D11}.Release|Any CPU.Build.0 = Release|Any CPU {4C45A966-16A2-408B-9037-A73954965D11}.Release|Any CPU.Build.0 = Release|Any CPU
{23DCE4A6-B06B-44E5-ACCF-C85EAC80178F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23DCE4A6-B06B-44E5-ACCF-C85EAC80178F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23DCE4A6-B06B-44E5-ACCF-C85EAC80178F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23DCE4A6-B06B-44E5-ACCF-C85EAC80178F}.Release|Any CPU.Build.0 = Release|Any CPU
{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Debug|Any CPU.Build.0 = Debug|Any CPU {08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Release|Any CPU.ActiveCfg = Release|Any CPU {08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Release|Any CPU.Build.0 = Release|Any CPU {08047FFC-2F9B-4BA8-B1B4-F0AC40F0C111}.Release|Any CPU.Build.0 = Release|Any CPU
{B41CCA3E-34B0-4B29-90BC-1BE2A3EFF4BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B41CCA3E-34B0-4B29-90BC-1BE2A3EFF4BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B41CCA3E-34B0-4B29-90BC-1BE2A3EFF4BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B41CCA3E-34B0-4B29-90BC-1BE2A3EFF4BD}.Release|Any CPU.Build.0 = Release|Any CPU
{ACD38119-D0AD-4903-B96C-C8B64C3F5AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACD38119-D0AD-4903-B96C-C8B64C3F5AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACD38119-D0AD-4903-B96C-C8B64C3F5AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACD38119-D0AD-4903-B96C-C8B64C3F5AC6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -10,7 +10,9 @@ public class CarDataModel : IValidation
public string Id { get; set; } public string Id { get; set; }
public string LicensePlate { get; set; } public string LicensePlate { get; set; }
public string Model { get; set; } public string Model { get; set; }
public string CustomerId { get; set; } // Добавленное свойство public string CustomerId { get; set; }
public CustomerDataModel? Customer { get; set; } // Навигационное свойство
public List<MalfunctionCarDataModel>? MalfunctionCars { get; set; }
public void Validate() public void Validate()
{ {
@@ -20,6 +22,9 @@ public class CarDataModel : IValidation
if (LicensePlate.IsEmpty()) if (LicensePlate.IsEmpty())
throw new ValidationException("Номерной знак обязателен"); throw new ValidationException("Номерной знак обязателен");
if (Model.IsEmpty())
throw new ValidationException("Модель автомобиля обязательна");
if (CustomerId.IsEmpty() || !CustomerId.IsGuid()) if (CustomerId.IsEmpty() || !CustomerId.IsGuid())
throw new ValidationException("Некорректный ID заказчика"); throw new ValidationException("Некорректный ID заказчика");
} }

View File

@@ -5,34 +5,36 @@ using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class CustomerDataModel( public class CustomerDataModel : IValidation
string id,
string fullName,
string login,
string password,
string email,
string phone,
List<CarDataModel> machines,
List<MaintenanceDataModel> maintenances) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public string FullName { get; } = fullName; public string FullName { get; set; }
public string Login { get; } = login; public string Login { get; set; }
public string Password { get; } = password; public string Password { get; set; }
public string Email { get; } = email; public string Email { get; set; }
public string Phone { get; } = phone; public string Phone { get; set; }
public List<CarDataModel> Machines { get; } = machines; public List<CarDataModel>? Cars { get; set; }
public List<MaintenanceDataModel> Maintenances { get; } = maintenances; public List<MaintenanceDataModel>? Maintenances { get; set; }
public List<MalfunctionDataModel>? Malfunctions { get; set; }
public void Validate() public void Validate()
{ {
if (id.IsEmpty() || !id.IsGuid()) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Некорректный ID заказчика"); throw new ValidationException("Некорректный ID заказчика");
if (fullName.IsEmpty()) if (FullName.IsEmpty())
throw new ValidationException("ФИО обязательно"); throw new ValidationException("ФИО обязательно");
if (!Regex.IsMatch(phone, @"^\+7\d{10}$")) if (Login.IsEmpty())
throw new ValidationException("Логин обязателен");
if (Password.IsEmpty())
throw new ValidationException("Пароль обязателен");
if (Email.IsEmpty() || !Regex.IsMatch(Email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"))
throw new ValidationException("Неверный формат email");
if (!Regex.IsMatch(Phone, @"^\+7\d{10}$"))
throw new ValidationException("Неверный формат телефона"); throw new ValidationException("Неверный формат телефона");
} }
} }

View File

@@ -5,27 +5,35 @@ using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class ExecutorDataModel(string id, public class ExecutorDataModel : IValidation
string fullName,
string login,
string password,
string email,
string phone,
List<RepairDataModel> repairs,
List<WorkDataModel> works) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public string FullName { get; } = fullName; public string FullName { get; set; }
public string Login { get; } = login; public string Login { get; set; }
public string Password { get; } = password; public string Password { get; set; }
public string Email { get; } = email; public string Email { get; set; }
public string Phone { get; } = phone; public string Phone { get; set; }
public List<RepairDataModel> Repairs { get; } = repairs; public List<WorkDataModel>? Works { get; set; }
public List<WorkDataModel> Works { get; } = works; public List<RepairDataModel>? Repairs { get; set; }
public void Validate() public void Validate()
{ {
if (!Regex.IsMatch(phone, @"^\+7\d{10}$")) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Некорректный ID исполнителя");
if (FullName.IsEmpty())
throw new ValidationException("ФИО обязательно");
if (Login.IsEmpty())
throw new ValidationException("Логин обязателен");
if (Password.IsEmpty())
throw new ValidationException("Пароль обязателен");
if (Email.IsEmpty() || !Regex.IsMatch(Email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"))
throw new ValidationException("Неверный формат email");
if (!Regex.IsMatch(Phone, @"^\+7\d{10}$"))
throw new ValidationException("Неверный формат телефона"); throw new ValidationException("Неверный формат телефона");
} }
} }

View File

@@ -4,20 +4,16 @@ using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class MaintenanceDataModel( public class MaintenanceDataModel : IValidation
string id,
DateTime date,
string description,
string machineId,
string customerId,
List<WorkDataModel> works) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public DateTime Date { get; } = date; public DateTime Date { get; set; }
public string Description { get; } = description; public string Description { get; set; }
public string MachineId { get; } = machineId; public string MachineId { get; set; }
public string CustomerId { get; } = customerId; public string CustomerId { get; set; }
public List<WorkDataModel> Works { get; } = works; public CarDataModel? Machine { get; set; }
public CustomerDataModel? Customer { get; set; }
public List<MaintenanceWorkDataModel>? MaintenanceWorks { get; set; }
public void Validate() public void Validate()
{ {
@@ -33,7 +29,7 @@ public class MaintenanceDataModel(
if (MachineId.IsEmpty() || !MachineId.IsGuid()) if (MachineId.IsEmpty() || !MachineId.IsGuid())
throw new ValidationException("Некорректный ID машины"); throw new ValidationException("Некорректный ID машины");
if (Works.Count == 0) if (CustomerId.IsEmpty() || !CustomerId.IsGuid())
throw new ValidationException("Обслуживание должно включать работы"); throw new ValidationException("Некорректный ID заказчика");
} }
} }

View File

@@ -0,0 +1,27 @@
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsContract.DataModels;
public class MaintenanceWorkDataModel : IValidation
{
public string MaintenanceId { get; set; }
public string WorkId { get; set; }
public MaintenanceDataModel? Maintenance { get; set; }
public WorkDataModel? Work { get; set; }
public void Validate()
{
if (MaintenanceId.IsEmpty() || !MaintenanceId.IsGuid())
throw new ValidationException("Некорректный ID обслуживания");
if (WorkId.IsEmpty() || !WorkId.IsGuid())
throw new ValidationException("Некорректный ID работы");
}
}

View File

@@ -0,0 +1,27 @@
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsContract.DataModels;
public class MalfunctionCarDataModel : IValidation
{
public string MalfunctionId { get; set; }
public string CarId { get; set; }
public MalfunctionDataModel? Malfunction { get; set; }
public CarDataModel? Car { get; set; }
public void Validate()
{
if (MalfunctionId.IsEmpty() || !MalfunctionId.IsGuid())
throw new ValidationException("Некорректный ID неисправности");
if (CarId.IsEmpty() || !CarId.IsGuid())
throw new ValidationException("Некорректный ID автомобиля");
}
}

View File

@@ -5,30 +5,25 @@ using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class MalfunctionDataModel( public class MalfunctionDataModel : IValidation
string id,
string description,
MalfunctionType type,
string customerId,
List<RepairDataModel> repairs,
List<CarDataModel> machines) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public string Description { get; } = description; public string Description { get; set; }
public MalfunctionType Type { get; } = type; public MalfunctionType Type { get; set; }
public string CustomerId { get; } = customerId; public string CustomerId { get; set; }
public List<RepairDataModel> Repairs { get; } = repairs; public CustomerDataModel? Customer { get; set; }
public List<CarDataModel> Machines { get; } = machines; public List<MalfunctionRepairDataModel>? MalfunctionRepairs { get; set; }
public List<MalfunctionCarDataModel>? MalfunctionCars { get; set; }
public void Validate() public void Validate()
{ {
if (id.IsEmpty() || !id.IsGuid()) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Некорректный ID неисправности"); throw new ValidationException("Некорректный ID неисправности");
if (description.IsEmpty()) if (Description.IsEmpty())
throw new ValidationException("Описание обязательно"); throw new ValidationException("Описание обязательно");
if (repairs.Count == 0) if (CustomerId.IsEmpty() || !CustomerId.IsGuid())
throw new ValidationException("Необходим хотя бы один ремонт"); throw new ValidationException("Некорректный ID заказчика");
} }
} }

View File

@@ -0,0 +1,28 @@
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsContract.DataModels;
public class MalfunctionRepairDataModel : IValidation
{
public string MalfunctionId { get; set; }
public string RepairId { get; set; }
public MalfunctionDataModel? Malfunction { get; set; }
public RepairDataModel? Repair { get; set; }
public void Validate()
{
if (MalfunctionId.IsEmpty() || !MalfunctionId.IsGuid())
throw new ValidationException("Некорректный ID неисправности");
if (RepairId.IsEmpty() || !RepairId.IsGuid())
throw new ValidationException("Некорректный ID ремонта");
}
}

View File

@@ -5,27 +5,29 @@ using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class RepairDataModel( public class RepairDataModel : IValidation
string id,
string description,
RepairType type,
DateTime repairDate,
string workerId,
List<SparePartDataModel> spareParts) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public string Description { get; } = description; public string Description { get; set; }
public RepairType Type { get; } = type; public RepairType Type { get; set; }
public DateTime RepairDate { get; } = repairDate; public DateTime RepairDate { get; set; }
public string WorkerId { get; } = workerId; public string WorkerId { get; set; }
public List<SparePartDataModel> SpareParts { get; } = spareParts; public ExecutorDataModel? Worker { get; set; }
public List<RepairSparePartDataModel>? RepairSpareParts { get; set; }
public List<MalfunctionRepairDataModel>? MalfunctionRepairs { get; set; }
public void Validate() public void Validate()
{ {
if (repairDate > DateTime.UtcNow) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Дата ремонта в будущем"); throw new ValidationException("Некорректный ID ремонта");
if (spareParts.Count == 0) if (Description.IsEmpty())
throw new ValidationException("Необходимы запчасти для ремонта"); throw new ValidationException("Описание обязательно");
if (RepairDate > DateTime.UtcNow)
throw new ValidationException("Дата ремонта не может быть в будущем");
if (WorkerId.IsEmpty() || !WorkerId.IsGuid())
throw new ValidationException("Некорректный ID исполнителя");
} }
} }

View File

@@ -0,0 +1,31 @@
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsContract.DataModels;
public class RepairSparePartDataModel : IValidation
{
public string RepairId { get; set; }
public string SparePartId { get; set; }
public int Quantity { get; set; }
public RepairDataModel? Repair { get; set; }
public SparePartDataModel? SparePart { get; set; }
public void Validate()
{
if (RepairId.IsEmpty() || !RepairId.IsGuid())
throw new ValidationException("Некорректный ID ремонта");
if (SparePartId.IsEmpty() || !SparePartId.IsGuid())
throw new ValidationException("Некорректный ID запасной части");
if (Quantity <= 0)
throw new ValidationException("Количество должно быть больше 0");
}
}

View File

@@ -1,34 +1,39 @@
using HookArmsContract.Enums; using HookArmsContract.Enums;
using HookArmsContract.Exceptions; using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure; using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class SparePartDataModel( public class SparePartDataModel : IValidation
string id,
string name,
SparePartType type,
decimal price,
string manufacturer,
string article,
int stock,
List<RepairDataModel> repairs) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public string Name { get; } = name; public string Name { get; set; }
public SparePartType Type { get; } = type; public SparePartType Type { get; set; }
public decimal Price { get; } = price; public decimal Price { get; set; }
public string Manufacturer { get; } = manufacturer; public string Manufacturer { get; set; }
public string Article { get; } = article; public string Article { get; set; }
public int Stock { get; } = stock; public int Stock { get; set; }
public List<RepairDataModel> Repairs { get; } = repairs; public List<RepairSparePartDataModel>? RepairSpareParts { get; set; }
public void Validate() public void Validate()
{ {
if (price <= 0) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Цена должна быть > 0"); throw new ValidationException("Некорректный ID запасной части");
if (stock < 0) if (Name.IsEmpty())
throw new ValidationException("Название обязательно");
if (Price <= 0)
throw new ValidationException("Цена должна быть больше 0");
if (Manufacturer.IsEmpty())
throw new ValidationException("Производитель обязателен");
if (Article.IsEmpty())
throw new ValidationException("Артикул обязателен");
if (Stock < 0)
throw new ValidationException("Наличие не может быть отрицательным"); throw new ValidationException("Наличие не может быть отрицательным");
} }
} }

View File

@@ -1,25 +1,32 @@
using HookArmsContract.Enums; using HookArmsContract.Enums;
using HookArmsContract.Exceptions; using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.Infrastructure; using HookArmsContract.Infrastructure;
namespace HookArmsContract.DataModels; namespace HookArmsContract.DataModels;
public class WorkDataModel( public class WorkDataModel : IValidation
string id,
WorkType type,
string description,
DateTime workDate,
ExecutorDataModel worker) : IValidation
{ {
public string Id { get; } = id; public string Id { get; set; }
public WorkType Type { get; } = type; public WorkType Type { get; set; }
public string Description { get; } = description; public string Description { get; set; }
public DateTime WorkDate { get; } = workDate; public DateTime WorkDate { get; set; }
public ExecutorDataModel Executor { get; } = worker; public string ExecutorId { get; set; }
public ExecutorDataModel? Executor { get; set; }
public List<MaintenanceWorkDataModel>? MaintenanceWorks { get; set; }
public void Validate() public void Validate()
{ {
if (workDate > DateTime.UtcNow) if (Id.IsEmpty() || !Id.IsGuid())
throw new ValidationException("Дата работы в будущем"); throw new ValidationException("Некорректный ID работы");
if (Description.IsEmpty())
throw new ValidationException("Описание обязательно");
if (WorkDate > DateTime.UtcNow)
throw new ValidationException("Дата работы не может быть в будущем");
if (ExecutorId.IsEmpty() || !ExecutorId.IsGuid())
throw new ValidationException("Некорректный ID исполнителя");
} }
} }

View File

@@ -0,0 +1,221 @@
using HookArmsContract.Enums;
using HookArmsContract.Infrastructure;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using Npgsql.EntityFrameworkCore.PostgreSQL;
namespace HookArmsDataBase;
public class AutoRepairShopDbContext : DbContext
{
private readonly IConfigurationDatabase? _configurationDatabase;
public AutoRepairShopDbContext(IConfigurationDatabase configurationDatabase)
{
_configurationDatabase = configurationDatabase;
}
public AutoRepairShopDbContext(DbContextOptions<AutoRepairShopDbContext> options)
: base(options)
{
_configurationDatabase = null;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (_configurationDatabase != null && !optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(_configurationDatabase.ConnectionString, o => o.SetPostgresVersion(16, 0));
}
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("hook_arms");
// Настройка первичных ключей
modelBuilder.Entity<Car>().HasKey(c => c.Id);
modelBuilder.Entity<Customer>().HasKey(c => c.Id);
modelBuilder.Entity<Executor>().HasKey(e => e.Id);
modelBuilder.Entity<Work>().HasKey(w => w.Id);
modelBuilder.Entity<Maintenance>().HasKey(m => m.Id);
modelBuilder.Entity<SparePart>().HasKey(sp => sp.Id);
modelBuilder.Entity<Repair>().HasKey(r => r.Id);
modelBuilder.Entity<Malfunction>().HasKey(m => m.Id);
// Настройка составных ключей для связующих таблиц
modelBuilder.Entity<MaintenanceWork>().HasKey(mw => new { mw.MaintenanceId, mw.WorkId });
modelBuilder.Entity<RepairSparePart>().HasKey(rsp => new { rsp.RepairId, rsp.SparePartId });
modelBuilder.Entity<MalfunctionRepair>().HasKey(mr => new { mr.MalfunctionId, mr.RepairId });
modelBuilder.Entity<MalfunctionCar>().HasKey(mc => new { mc.MalfunctionId, mc.CarId });
// Настройка связей "один-ко-многим"
// Customer
modelBuilder.Entity<Customer>()
.HasMany(c => c.Cars)
.WithOne(c => c.Customer)
.HasForeignKey(c => c.CustomerId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Customer>()
.HasMany(c => c.Maintenances)
.WithOne(m => m.Customer)
.HasForeignKey(m => m.CustomerId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Customer>()
.HasMany(c => c.Malfunctions)
.WithOne(m => m.Customer)
.HasForeignKey(m => m.CustomerId)
.OnDelete(DeleteBehavior.Restrict);
// Executor
modelBuilder.Entity<Executor>()
.HasMany(e => e.Repairs)
.WithOne(r => r.Worker)
.HasForeignKey(r => r.WorkerId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Executor>()
.HasMany(e => e.Works)
.WithOne(w => w.Executor)
.HasForeignKey(w => w.ExecutorId)
.OnDelete(DeleteBehavior.Restrict);
// Maintenance
modelBuilder.Entity<Maintenance>()
.HasOne(m => m.Machine)
.WithMany()
.HasForeignKey(m => m.MachineId)
.OnDelete(DeleteBehavior.Restrict);
// Настройка связей "многие-ко-многим" через связующие таблицы
// MaintenanceWork
modelBuilder.Entity<MaintenanceWork>()
.HasOne(mw => mw.Maintenance)
.WithMany(m => m.MaintenanceWorks)
.HasForeignKey(mw => mw.MaintenanceId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MaintenanceWork>()
.HasOne(mw => mw.Work)
.WithMany()
.HasForeignKey(mw => mw.WorkId)
.OnDelete(DeleteBehavior.Restrict);
// RepairSparePart
modelBuilder.Entity<RepairSparePart>()
.HasOne(rsp => rsp.Repair)
.WithMany(r => r.RepairSpareParts)
.HasForeignKey(rsp => rsp.RepairId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<RepairSparePart>()
.HasOne(rsp => rsp.SparePart)
.WithMany()
.HasForeignKey(rsp => rsp.SparePartId)
.OnDelete(DeleteBehavior.Restrict);
// MalfunctionRepair
modelBuilder.Entity<MalfunctionRepair>()
.HasOne(mr => mr.Malfunction)
.WithMany(m => m.MalfunctionRepairs)
.HasForeignKey(mr => mr.MalfunctionId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MalfunctionRepair>()
.HasOne(mr => mr.Repair)
.WithMany()
.HasForeignKey(mr => mr.RepairId)
.OnDelete(DeleteBehavior.Restrict);
// MalfunctionCar
modelBuilder.Entity<MalfunctionCar>()
.HasOne(mc => mc.Malfunction)
.WithMany(m => m.MalfunctionCars)
.HasForeignKey(mc => mc.MalfunctionId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MalfunctionCar>()
.HasOne(mc => mc.Car)
.WithMany()
.HasForeignKey(mc => mc.CarId)
.OnDelete(DeleteBehavior.Restrict);
// Настройка уникальности
modelBuilder.Entity<Customer>()
.HasIndex(c => c.Login)
.IsUnique();
modelBuilder.Entity<Customer>()
.HasIndex(c => c.Phone)
.IsUnique();
modelBuilder.Entity<Executor>()
.HasIndex(e => e.Login)
.IsUnique();
modelBuilder.Entity<Executor>()
.HasIndex(e => e.Phone)
.IsUnique();
modelBuilder.Entity<Car>()
.HasIndex(c => c.LicensePlate)
.IsUnique();
modelBuilder.Entity<SparePart>()
.HasIndex(sp => sp.Article)
.IsUnique();
// Настройка свойств сущностей
modelBuilder.Entity<Car>(entity =>
{
entity.ToTable("cars");
entity.Property(e => e.Id).HasColumnType("uuid");
entity.Property(e => e.LicensePlate).IsRequired().HasMaxLength(20);
entity.Property(e => e.Model).IsRequired().HasMaxLength(100);
entity.Property(e => e.CustomerId).HasColumnType("uuid");
entity.Property(e => e.CreatedAt).HasColumnType("timestamp with time zone").HasDefaultValueSql("CURRENT_TIMESTAMP");
});
// Настройка связующих таблиц
modelBuilder.Entity<MaintenanceWork>(entity =>
{
entity.ToTable("maintenance_works");
entity.Property(e => e.MaintenanceId).HasColumnType("uuid");
entity.Property(e => e.WorkId).HasColumnType("uuid");
});
modelBuilder.Entity<MalfunctionRepair>(entity =>
{
entity.ToTable("malfunction_repairs");
entity.Property(e => e.MalfunctionId).HasColumnType("uuid");
entity.Property(e => e.RepairId).HasColumnType("uuid");
});
modelBuilder.Entity<MalfunctionCar>(entity =>
{
entity.ToTable("malfunction_cars");
entity.Property(e => e.MalfunctionId).HasColumnType("uuid");
entity.Property(e => e.CarId).HasColumnType("uuid");
});
}
// DbSet для всех сущностей
public DbSet<Car> Cars { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Executor> Executors { get; set; }
public DbSet<Work> Works { get; set; }
public DbSet<Maintenance> Maintenances { get; set; }
public DbSet<SparePart> SpareParts { get; set; }
public DbSet<Repair> Repairs { get; set; }
public DbSet<Malfunction> Malfunctions { get; set; }
public DbSet<MaintenanceWork> MaintenanceWorks { get; set; }
public DbSet<RepairSparePart> RepairSpareParts { get; set; }
public DbSet<MalfunctionRepair> MalfunctionRepairs { get; set; }
public DbSet<MalfunctionCar> MalfunctionCars { get; set; }
}

View File

@@ -0,0 +1,13 @@
using HookArmsContract.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase;
public class DefaultConfigurationDatabase : IConfigurationDatabase
{
public string ConnectionString => "Host=127.0.0.1;Port=5432;Database=auto_repair_shop;Username=postgres;Password=postgres;";
}

View File

@@ -0,0 +1,228 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.EntityFrameworkCore.Design;
namespace HookArmsDataBase.Implementations;
public class CarStorage : ICarStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public CarStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
// Маппинг для Car <-> CarDataModel
cfg.CreateMap<Car, CarDataModel>()
.ConstructUsing((src, ctx) => new CarDataModel
{
Id = src.Id,
LicensePlate = src.LicensePlate,
Model = src.Model,
CustomerId = src.CustomerId
});
cfg.CreateMap<CarDataModel, Car>()
.ForMember(dest => dest.Customer, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<CarDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех автомобилей");
var cars = _context.Cars
.Include(c => c.Customer)
.AsNoTracking()
.ToList();
return _mapper.Map<List<CarDataModel>>(cars);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка автомобилей: {ex.Message}");
throw new StorageException(ex);
}
}
public CarDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска автомобиля по ID {id}");
if (string.IsNullOrEmpty(id))
{
Console.WriteLine("GetById: ID автомобиля пустой");
throw new ArgumentNullException(nameof(id), "ID не может быть пустым");
}
if (!id.IsGuid())
{
Console.WriteLine($"GetById: ID {id} не является GUID");
throw new ValidationException("ID должен быть в формате GUID");
}
var car = _context.Cars
.Include(c => c.Customer)
.AsNoTracking()
.FirstOrDefault(c => c.Id == id);
if (car == null)
{
Console.WriteLine($"GetById: Автомобиль с ID {id} не найден");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Автомобиль найден, номерной знак: {car.LicensePlate}");
return _mapper.Map<CarDataModel>(car);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении автомобиля по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(CarDataModel machine)
{
try
{
Console.WriteLine($"Add: Добавление автомобиля с номером {machine.LicensePlate}");
if (machine.Id.IsEmpty() || !machine.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID автомобиля {machine.Id}");
throw new ValidationException("Некорректный ID автомобиля");
}
if (_context.Cars.Any(c => c.LicensePlate == machine.LicensePlate))
{
Console.WriteLine($"Add: Автомобиль с номером {machine.LicensePlate} уже существует");
throw new ElementExistsException("LicensePlate", machine.LicensePlate);
}
if (machine.CustomerId.IsEmpty() || !machine.CustomerId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID заказчика {machine.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == machine.CustomerId))
{
Console.WriteLine($"Add: Заказчик с ID {machine.CustomerId} не найден");
throw new ElementNotFoundException(machine.CustomerId);
}
var car = _mapper.Map<Car>(machine);
_context.Cars.Add(car);
_context.SaveChanges();
Console.WriteLine($"Add: Автомобиль с ID {car.Id} успешно добавлен");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении автомобиля: {ex.Message}");
throw ex is ElementExistsException or ValidationException or ElementNotFoundException ? ex : new StorageException(ex);
}
}
public void Update(CarDataModel machine)
{
try
{
Console.WriteLine($"Update: Обновление автомобиля с ID {machine.Id}");
if (machine.Id.IsEmpty() || !machine.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID автомобиля {machine.Id}");
throw new ValidationException("Некорректный ID автомобиля");
}
var existingCar = _context.Cars.Find(machine.Id);
if (existingCar == null)
{
Console.WriteLine($"Update: Автомобиль с ID {machine.Id} не найден");
throw new ElementNotFoundException(machine.Id);
}
if (existingCar.LicensePlate != machine.LicensePlate &&
_context.Cars.Any(c => c.LicensePlate == machine.LicensePlate))
{
Console.WriteLine($"Update: Автомобиль с номером {machine.LicensePlate} уже существует");
throw new ElementExistsException("LicensePlate", machine.LicensePlate);
}
if (machine.CustomerId.IsEmpty() || !machine.CustomerId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID заказчика {machine.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == machine.CustomerId))
{
Console.WriteLine($"Update: Заказчик с ID {machine.CustomerId} не найден");
throw new ElementNotFoundException(machine.CustomerId);
}
_context.Entry(existingCar).State = EntityState.Detached;
var updatedCar = _mapper.Map<Car>(machine);
_context.Cars.Update(updatedCar);
_context.SaveChanges();
Console.WriteLine($"Update: Автомобиль с ID {machine.Id} успешно обновлён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении автомобиля с ID {machine.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления автомобиля с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID автомобиля {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var car = _context.Cars.Find(id);
if (car == null)
{
Console.WriteLine($"Delete: Автомобиль с ID {id} не найден");
throw new ElementNotFoundException(id);
}
_context.Cars.Remove(car);
_context.SaveChanges();
Console.WriteLine($"Delete: Автомобиль с ID {id} успешно удалён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении автомобиля с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,218 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class CustomerStorage : ICustomerStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public CustomerStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Customer, CustomerDataModel>()
.ConstructUsing((src, ctx) => new CustomerDataModel
{
Id = src.Id,
FullName = src.FullName,
Login = src.Login,
Password = src.Password,
Email = src.Email,
Phone = src.Phone
});
cfg.CreateMap<CustomerDataModel, Customer>()
.ForMember(dest => dest.Cars, opt => opt.Ignore())
.ForMember(dest => dest.Maintenances, opt => opt.Ignore())
.ForMember(dest => dest.Malfunctions, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<CustomerDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех заказчиков");
var customers = _context.Customers
.Include(c => c.Cars)
.Include(c => c.Maintenances)
.Include(c => c.Malfunctions)
.AsNoTracking()
.ToList();
return _mapper.Map<List<CustomerDataModel>>(customers);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка заказчиков: {ex.Message}");
throw new StorageException(ex);
}
}
public CustomerDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска заказчика по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID заказчика {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var customer = _context.Customers
.Include(c => c.Cars)
.Include(c => c.Maintenances)
.Include(c => c.Malfunctions)
.AsNoTracking()
.FirstOrDefault(c => c.Id == id);
if (customer == null)
{
Console.WriteLine($"GetById: Заказчик с ID {id} не найден");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Заказчик найден, ФИО: {customer.FullName}");
return _mapper.Map<CustomerDataModel>(customer);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении заказчика по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(CustomerDataModel customer)
{
try
{
Console.WriteLine($"Add: Добавление заказчика с ФИО {customer.FullName}");
if (customer.Id.IsEmpty() || !customer.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID заказчика {customer.Id}");
throw new ValidationException("Некорректный ID заказчика");
}
if (_context.Customers.Any(c => c.Login == customer.Login))
{
Console.WriteLine($"Add: Заказчик с логином {customer.Login} уже существует");
throw new ElementExistsException("Login", customer.Login);
}
if (_context.Customers.Any(c => c.Phone == customer.Phone))
{
Console.WriteLine($"Add: Заказчик с телефоном {customer.Phone} уже существует");
throw new ElementExistsException("Phone", customer.Phone);
}
var entity = _mapper.Map<Customer>(customer);
_context.Customers.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Заказчик с ID {entity.Id} успешно добавлен");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении заказчика: {ex.Message}");
throw ex is ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(CustomerDataModel customer)
{
try
{
Console.WriteLine($"Update: Обновление заказчика с ID {customer.Id}");
if (customer.Id.IsEmpty() || !customer.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID заказчика {customer.Id}");
throw new ValidationException("Некорректный ID заказчика");
}
var existingCustomer = _context.Customers.Find(customer.Id);
if (existingCustomer == null)
{
Console.WriteLine($"Update: Заказчик с ID {customer.Id} не найден");
throw new ElementNotFoundException(customer.Id);
}
if (existingCustomer.Login != customer.Login &&
_context.Customers.Any(c => c.Login == customer.Login))
{
Console.WriteLine($"Update: Заказчик с логином {customer.Login} уже существует");
throw new ElementExistsException("Login", customer.Login);
}
if (existingCustomer.Phone != customer.Phone &&
_context.Customers.Any(c => c.Phone == customer.Phone))
{
Console.WriteLine($"Update: Заказчик с телефоном {customer.Phone} уже существует");
throw new ElementExistsException("Phone", customer.Phone);
}
_context.Entry(existingCustomer).State = EntityState.Detached;
var updatedCustomer = _mapper.Map<Customer>(customer);
_context.Customers.Update(updatedCustomer);
_context.SaveChanges();
Console.WriteLine($"Update: Заказчик с ID {customer.Id} успешно обновлён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении заказчика с ID {customer.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления заказчика с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID заказчика {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var customer = _context.Customers.Find(id);
if (customer == null)
{
Console.WriteLine($"Delete: Заказчик с ID {id} не найден");
throw new ElementNotFoundException(id);
}
_context.Customers.Remove(customer);
_context.SaveChanges();
Console.WriteLine($"Delete: Заказчик с ID {id} успешно удалён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении заказчика с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,215 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class ExecutorStorage : IExecutorStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public ExecutorStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Executor, ExecutorDataModel>()
.ConstructUsing((src, ctx) => new ExecutorDataModel
{
Id = src.Id,
FullName = src.FullName,
Login = src.Login,
Password = src.Password,
Email = src.Email,
Phone = src.Phone
});
cfg.CreateMap<ExecutorDataModel, Executor>()
.ForMember(dest => dest.Works, opt => opt.Ignore())
.ForMember(dest => dest.Repairs, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<ExecutorDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех исполнителей");
var executors = _context.Executors
.Include(e => e.Works)
.Include(e => e.Repairs)
.AsNoTracking()
.ToList();
return _mapper.Map<List<ExecutorDataModel>>(executors);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка исполнителей: {ex.Message}");
throw new StorageException(ex);
}
}
public ExecutorDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска исполнителя по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID исполнителя {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var executor = _context.Executors
.Include(e => e.Works)
.Include(e => e.Repairs)
.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
if (executor == null)
{
Console.WriteLine($"GetById: Исполнитель с ID {id} не найден");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Исполнитель найден, ФИО: {executor.FullName}");
return _mapper.Map<ExecutorDataModel>(executor);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении исполнителя по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(ExecutorDataModel executor)
{
try
{
Console.WriteLine($"Add: Добавление исполнителя с ФИО {executor.FullName}");
if (executor.Id.IsEmpty() || !executor.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID исполнителя {executor.Id}");
throw new ValidationException("Некорректный ID исполнителя");
}
if (_context.Executors.Any(e => e.Login == executor.Login))
{
Console.WriteLine($"Add: Исполнитель с логином {executor.Login} уже существует");
throw new ElementExistsException("Login", executor.Login);
}
if (_context.Executors.Any(e => e.Phone == executor.Phone))
{
Console.WriteLine($"Add: Исполнитель с телефоном {executor.Phone} уже существует");
throw new ElementExistsException("Phone", executor.Phone);
}
var entity = _mapper.Map<Executor>(executor);
_context.Executors.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Исполнитель с ID {entity.Id} успешно добавлен");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении исполнителя: {ex.Message}");
throw ex is ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(ExecutorDataModel executor)
{
try
{
Console.WriteLine($"Update: Обновление исполнителя с ID {executor.Id}");
if (executor.Id.IsEmpty() || !executor.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID исполнителя {executor.Id}");
throw new ValidationException("Некорректный ID исполнителя");
}
var existingExecutor = _context.Executors.Find(executor.Id);
if (existingExecutor == null)
{
Console.WriteLine($"Update: Исполнитель с ID {executor.Id} не найден");
throw new ElementNotFoundException(executor.Id);
}
if (existingExecutor.Login != executor.Login &&
_context.Executors.Any(e => e.Login == executor.Login))
{
Console.WriteLine($"Update: Исполнитель с логином {executor.Login} уже существует");
throw new ElementExistsException("Login", executor.Login);
}
if (existingExecutor.Phone != executor.Phone &&
_context.Executors.Any(e => e.Phone == executor.Phone))
{
Console.WriteLine($"Update: Исполнитель с телефоном {executor.Phone} уже существует");
throw new ElementExistsException("Phone", executor.Phone);
}
_context.Entry(existingExecutor).State = EntityState.Detached;
var updatedExecutor = _mapper.Map<Executor>(executor);
_context.Executors.Update(updatedExecutor);
_context.SaveChanges();
Console.WriteLine($"Update: Исполнитель с ID {executor.Id} успешно обновлён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении исполнителя с ID {executor.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления исполнителя с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID исполнителя {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var executor = _context.Executors.Find(id);
if (executor == null)
{
Console.WriteLine($"Delete: Исполнитель с ID {id} не найден");
throw new ElementNotFoundException(id);
}
_context.Executors.Remove(executor);
_context.SaveChanges();
Console.WriteLine($"Delete: Исполнитель с ID {id} успешно удалён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении исполнителя с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,250 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class MaintenanceStorage : IMaintenanceStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public MaintenanceStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Maintenance, MaintenanceDataModel>()
.ConstructUsing((src, ctx) => new MaintenanceDataModel
{
Id = src.Id,
Date = src.Date,
Description = src.Description,
MachineId = src.MachineId,
CustomerId = src.CustomerId
});
cfg.CreateMap<MaintenanceDataModel, Maintenance>()
.ForMember(dest => dest.Machine, opt => opt.Ignore())
.ForMember(dest => dest.Customer, opt => opt.Ignore())
.ForMember(dest => dest.MaintenanceWorks, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<MaintenanceDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех обслуживаний");
var maintenances = _context.Maintenances
.Include(m => m.Machine)
.Include(m => m.Customer)
.Include(m => m.MaintenanceWorks).ThenInclude(mw => mw.Work)
.AsNoTracking()
.ToList();
return _mapper.Map<List<MaintenanceDataModel>>(maintenances);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка обслуживаний: {ex.Message}");
throw new StorageException(ex);
}
}
public MaintenanceDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска обслуживания по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID обслуживания {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var maintenance = _context.Maintenances
.Include(m => m.Machine)
.Include(m => m.Customer)
.Include(m => m.MaintenanceWorks).ThenInclude(mw => mw.Work)
.AsNoTracking()
.FirstOrDefault(m => m.Id == id);
if (maintenance == null)
{
Console.WriteLine($"GetById: Обслуживание с ID {id} не найдено");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Обслуживание найдено, описание: {maintenance.Description}");
return _mapper.Map<MaintenanceDataModel>(maintenance);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении обслуживания по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(MaintenanceDataModel maintenance)
{
try
{
Console.WriteLine($"Add: Добавление обслуживания с описанием {maintenance.Description}");
if (maintenance.Id.IsEmpty() || !maintenance.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID обслуживания {maintenance.Id}");
throw new ValidationException("Некорректный ID обслуживания");
}
if (maintenance.Date > DateTime.UtcNow)
{
Console.WriteLine($"Add: Дата обслуживания {maintenance.Date} не может быть в будущем");
throw new ValidationException("Дата обслуживания не может быть в будущем");
}
if (maintenance.MachineId.IsEmpty() || !maintenance.MachineId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID автомобиля {maintenance.MachineId}");
throw new ValidationException("Некорректный ID автомобиля");
}
if (!_context.Cars.Any(c => c.Id == maintenance.MachineId))
{
Console.WriteLine($"Add: Автомобиль с ID {maintenance.MachineId} не найден");
throw new ElementNotFoundException(maintenance.MachineId);
}
if (maintenance.CustomerId.IsEmpty() || !maintenance.CustomerId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID заказчика {maintenance.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == maintenance.CustomerId))
{
Console.WriteLine($"Add: Заказчик с ID {maintenance.CustomerId} не найден");
throw new ElementNotFoundException(maintenance.CustomerId);
}
var entity = _mapper.Map<Maintenance>(maintenance);
_context.Maintenances.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Обслуживание с ID {entity.Id} успешно добавлено");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении обслуживания: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(MaintenanceDataModel maintenance)
{
try
{
Console.WriteLine($"Update: Обновление обслуживания с ID {maintenance.Id}");
if (maintenance.Id.IsEmpty() || !maintenance.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID обслуживания {maintenance.Id}");
throw new ValidationException("Некорректный ID обслуживания");
}
var existingMaintenance = _context.Maintenances.Find(maintenance.Id);
if (existingMaintenance == null)
{
Console.WriteLine($"Update: Обслуживание с ID {maintenance.Id} не найдено");
throw new ElementNotFoundException(maintenance.Id);
}
if (maintenance.Date > DateTime.UtcNow)
{
Console.WriteLine($"Update: Дата обслуживания {maintenance.Date} не может быть в будущем");
throw new ValidationException("Дата обслуживания не может быть в будущем");
}
if (maintenance.MachineId.IsEmpty() || !maintenance.MachineId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID автомобиля {maintenance.MachineId}");
throw new ValidationException("Некорректный ID автомобиля");
}
if (!_context.Cars.Any(c => c.Id == maintenance.MachineId))
{
Console.WriteLine($"Update: Автомобиль с ID {maintenance.MachineId} не найден");
throw new ElementNotFoundException(maintenance.MachineId);
}
if (maintenance.CustomerId.IsEmpty() || !maintenance.CustomerId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID заказчика {maintenance.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == maintenance.CustomerId))
{
Console.WriteLine($"Update: Заказчик с ID {maintenance.CustomerId} не найден");
throw new ElementNotFoundException(maintenance.CustomerId);
}
_context.Entry(existingMaintenance).State = EntityState.Detached;
var updatedMaintenance = _mapper.Map<Maintenance>(maintenance);
_context.Maintenances.Update(updatedMaintenance);
_context.SaveChanges();
Console.WriteLine($"Update: Обслуживание с ID {maintenance.Id} успешно обновлено");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении обслуживания с ID {maintenance.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления обслуживания с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID обслуживания {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var maintenance = _context.Maintenances.Find(id);
if (maintenance == null)
{
Console.WriteLine($"Delete: Обслуживание с ID {id} не найдено");
throw new ElementNotFoundException(id);
}
_context.Maintenances.Remove(maintenance);
_context.SaveChanges();
Console.WriteLine($"Delete: Maintenance with ID {id} successfully deleted");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Error deleting maintenance with ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,214 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class MalfunctionStorage : IMalfunctionStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public MalfunctionStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Malfunction, MalfunctionDataModel>()
.ConstructUsing((src, ctx) => new MalfunctionDataModel
{
Id = src.Id,
Description = src.Description,
Type = src.Type,
CustomerId = src.CustomerId
});
cfg.CreateMap<MalfunctionDataModel, Malfunction>()
.ForMember(dest => dest.Customer, opt => opt.Ignore())
.ForMember(dest => dest.MalfunctionRepairs, opt => opt.Ignore())
.ForMember(dest => dest.MalfunctionCars, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<MalfunctionDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех неисправностей");
var malfunctions = _context.Malfunctions
.Include(m => m.Customer)
.Include(m => m.MalfunctionRepairs).ThenInclude(mr => mr.Repair)
.Include(m => m.MalfunctionCars).ThenInclude(mc => mc.Car)
.AsNoTracking()
.ToList();
return _mapper.Map<List<MalfunctionDataModel>>(malfunctions);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка неисправностей: {ex.Message}");
throw new StorageException(ex);
}
}
public MalfunctionDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска неисправности по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID неисправности {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var malfunction = _context.Malfunctions
.Include(m => m.Customer)
.Include(m => m.MalfunctionRepairs).ThenInclude(mr => mr.Repair)
.Include(m => m.MalfunctionCars).ThenInclude(mc => mc.Car)
.AsNoTracking()
.FirstOrDefault(m => m.Id == id);
if (malfunction == null)
{
Console.WriteLine($"GetById: Неисправность с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Неисправность найдена, описание: {malfunction.Description}");
return _mapper.Map<MalfunctionDataModel>(malfunction);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении неисправности по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(MalfunctionDataModel malfunction)
{
try
{
Console.WriteLine($"Add: Добавление неисправности с описанием {malfunction.Description}");
if (malfunction.Id.IsEmpty() || !malfunction.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID неисправности {malfunction.Id}");
throw new ValidationException("Некорректный ID неисправности");
}
if (malfunction.CustomerId.IsEmpty() || !malfunction.CustomerId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID заказчика {malfunction.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == malfunction.CustomerId))
{
Console.WriteLine($"Add: Заказчик с ID {malfunction.CustomerId} не найден");
throw new ElementNotFoundException(malfunction.CustomerId);
}
var entity = _mapper.Map<Malfunction>(malfunction);
_context.Malfunctions.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Неисправность с ID {entity.Id} успешно добавлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении неисправности: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(MalfunctionDataModel malfunction)
{
try
{
Console.WriteLine($"Update: Обновление неисправности с ID {malfunction.Id}");
if (malfunction.Id.IsEmpty() || !malfunction.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID неисправности {malfunction.Id}");
throw new ValidationException("Некорректный ID неисправности");
}
var existingMalfunction = _context.Malfunctions.Find(malfunction.Id);
if (existingMalfunction == null)
{
Console.WriteLine($"Update: Неисправность с ID {malfunction.Id} не найдена");
throw new ElementNotFoundException(malfunction.Id);
}
if (malfunction.CustomerId.IsEmpty() || !malfunction.CustomerId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID заказчика {malfunction.CustomerId}");
throw new ValidationException("Некорректный ID заказчика");
}
if (!_context.Customers.Any(c => c.Id == malfunction.CustomerId))
{
Console.WriteLine($"Update: Заказчик с ID {malfunction.CustomerId} не найден");
throw new ElementNotFoundException(malfunction.CustomerId);
}
_context.Entry(existingMalfunction).State = EntityState.Detached;
var updatedMalfunction = _mapper.Map<Malfunction>(malfunction);
_context.Malfunctions.Update(updatedMalfunction);
_context.SaveChanges();
Console.WriteLine($"Update: Неисправность с ID {malfunction.Id} успешно обновлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении неисправности с ID {malfunction.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления неисправности с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID неисправности {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var malfunction = _context.Malfunctions.Find(id);
if (malfunction == null)
{
Console.WriteLine($"Delete: Неисправность с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
_context.Malfunctions.Remove(malfunction);
_context.SaveChanges();
Console.WriteLine($"Delete: Неисправность с ID {id} успешно удалена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении неисправности с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,227 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class RepairStorage : IRepairStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public RepairStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Repair, RepairDataModel>()
.ConstructUsing((src, ctx) => new RepairDataModel
{
Id = src.Id,
Description = src.Description,
Type = src.Type,
RepairDate = src.RepairDate,
WorkerId = src.WorkerId
});
cfg.CreateMap<RepairDataModel, Repair>()
.ForMember(dest => dest.Worker, opt => opt.Ignore())
.ForMember(dest => dest.RepairSpareParts, opt => opt.Ignore())
.ForMember(dest => dest.MalfunctionRepairs, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<RepairDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех ремонтов");
var repairs = _context.Repairs
.Include(r => r.Worker)
.Include(r => r.RepairSpareParts).ThenInclude(rsp => rsp.SparePart)
.Include(r => r.MalfunctionRepairs)
.AsNoTracking()
.ToList();
return _mapper.Map<List<RepairDataModel>>(repairs);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка ремонтов: {ex.Message}");
throw ex is StorageException ? ex : new StorageException(ex);
}
}
public RepairDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска ремонта по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID ремонта {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var repair = _context.Repairs
.Include(r => r.Worker)
.Include(r => r.RepairSpareParts).ThenInclude(rsp => rsp.SparePart)
.Include(r => r.MalfunctionRepairs)
.AsNoTracking()
.FirstOrDefault(r => r.Id == id);
if (repair == null)
{
Console.WriteLine($"GetById: Ремонт с ID {id} не найден");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Ремонт найден, описание: {repair.Description}");
return _mapper.Map<RepairDataModel>(repair);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении ремонта по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(RepairDataModel repair)
{
try
{
Console.WriteLine($"Add: Добавление ремонта с описанием {repair.Description}");
if (repair.Id.IsEmpty() || !repair.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID ремонта {repair.Id}");
throw new ValidationException("Некорректный ID ремонта");
}
if (repair.RepairDate > DateTime.UtcNow)
{
Console.WriteLine($"Add: Дата ремонта {repair.RepairDate} не может быть в будущем");
throw new ValidationException("Дата ремонта не может быть в будущем");
}
if (repair.WorkerId.IsEmpty() || !repair.WorkerId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID исполнителя {repair.WorkerId}");
throw new ValidationException("Некорректный ID исполнителя");
}
if (!_context.Executors.Any(e => e.Id == repair.WorkerId))
{
Console.WriteLine($"Add: Исполнитель с ID {repair.WorkerId} не найден");
throw new ElementNotFoundException(repair.WorkerId);
}
var entity = _mapper.Map<Repair>(repair);
_context.Repairs.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Ремонт с ID {entity.Id} успешно добавлен");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении ремонта: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(RepairDataModel repair)
{
try
{
Console.WriteLine($"Update: Обновление ремонта с ID {repair.Id}");
if (repair.Id.IsEmpty() || !repair.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID ремонта {repair.Id}");
throw new ValidationException("Некорректный ID ремонта");
}
var existingRepair = _context.Repairs.Find(repair.Id);
if (existingRepair == null)
{
Console.WriteLine($"Update: Ремонт с ID {repair.Id} не найден");
throw new ElementNotFoundException(repair.Id);
}
if (repair.RepairDate > DateTime.UtcNow)
{
Console.WriteLine($"Update: Дата ремонта {repair.RepairDate} не может быть в будущем");
throw new ValidationException("Дата ремонта не может быть в будущем");
}
if (repair.WorkerId.IsEmpty() || !repair.WorkerId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID исполнителя {repair.WorkerId}");
throw new ValidationException("Некорректный ID исполнителя");
}
if (!_context.Executors.Any(e => e.Id == repair.WorkerId))
{
Console.WriteLine($"Update: Исполнитель с ID {repair.WorkerId} не найден");
throw new ElementNotFoundException(repair.WorkerId);
}
_context.Entry(existingRepair).State = EntityState.Detached;
var updatedRepair = _mapper.Map<Repair>(repair);
_context.Repairs.Update(updatedRepair);
_context.SaveChanges();
Console.WriteLine($"Update: Ремонт с ID {repair.Id} успешно обновлён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении ремонта с ID {repair.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления ремонта с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID ремонта {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var repair = _context.Repairs.Find(id);
if (repair == null)
{
Console.WriteLine($"Delete: Ремонт с ID {id} не найден");
throw new ElementNotFoundException(id);
}
_context.Repairs.Remove(repair);
_context.SaveChanges();
Console.WriteLine($"Delete: Ремонт с ID {id} успешно удалён");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении ремонта с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,224 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class SparePartStorage : ISparePartStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public SparePartStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<SparePart, SparePartDataModel>()
.ConstructUsing((src, ctx) => new SparePartDataModel
{
Id = src.Id,
Name = src.Name,
Type = src.Type,
Price = src.Price,
Manufacturer = src.Manufacturer,
Article = src.Article,
Stock = src.Stock
});
cfg.CreateMap<SparePartDataModel, SparePart>()
.ForMember(dest => dest.RepairSpareParts, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<SparePartDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех запасных частей");
var spareParts = _context.SpareParts
.Include(sp => sp.RepairSpareParts)
.AsNoTracking()
.ToList();
return _mapper.Map<List<SparePartDataModel>>(spareParts);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка запасных частей: {ex.Message}");
throw new StorageException(ex);
}
}
public SparePartDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска запасной части по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID запасной части {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var sparePart = _context.SpareParts
.Include(sp => sp.RepairSpareParts)
.AsNoTracking()
.FirstOrDefault(sp => sp.Id == id);
if (sparePart == null)
{
Console.WriteLine($"GetById: Запасная часть с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Запасная часть найдена, артикул: {sparePart.Article}");
return _mapper.Map<SparePartDataModel>(sparePart);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении запасной части по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(SparePartDataModel sparePart)
{
try
{
Console.WriteLine($"Add: Добавление запасной части с артикулом {sparePart.Article}");
if (sparePart.Id.IsEmpty() || !sparePart.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID запасной части {sparePart.Id}");
throw new ValidationException("Некорректный ID запасной части");
}
if (_context.SpareParts.Any(sp => sp.Article == sparePart.Article))
{
Console.WriteLine($"Add: Запасная часть с артикулом {sparePart.Article} уже существует");
throw new ElementExistsException("Article", sparePart.Article);
}
if (sparePart.Price <= 0)
{
Console.WriteLine($"Add: Цена запасной части {sparePart.Price} должна быть больше 0");
throw new ValidationException("Цена должна быть больше 0");
}
if (sparePart.Stock < 0)
{
Console.WriteLine($"Add: Количество на складе {sparePart.Stock} не может быть отрицательным");
throw new ValidationException("Количество на складе не может быть отрицательным");
}
var entity = _mapper.Map<SparePart>(sparePart);
_context.SpareParts.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Запасная часть с ID {entity.Id} успешно добавлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении запасной части: {ex.Message}");
throw ex is ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(SparePartDataModel sparePart)
{
try
{
Console.WriteLine($"Update: Обновление запасной части с ID {sparePart.Id}");
if (sparePart.Id.IsEmpty() || !sparePart.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID запасной части {sparePart.Id}");
throw new ValidationException("Некорректный ID запасной части");
}
var existingSparePart = _context.SpareParts.Find(sparePart.Id);
if (existingSparePart == null)
{
Console.WriteLine($"Update: Запасная часть с ID {sparePart.Id} не найдена");
throw new ElementNotFoundException(sparePart.Id);
}
if (existingSparePart.Article != sparePart.Article &&
_context.SpareParts.Any(sp => sp.Article == sparePart.Article))
{
Console.WriteLine($"Update: Запасная часть с артикулом {sparePart.Article} уже существует");
throw new ElementExistsException("Article", sparePart.Article);
}
if (sparePart.Price <= 0)
{
Console.WriteLine($"Update: Цена запасной части {sparePart.Price} должна быть больше 0");
throw new ValidationException("Цена должна быть больше 0");
}
if (sparePart.Stock < 0)
{
Console.WriteLine($"Update: Количество на складе {sparePart.Stock} не может быть отрицательным");
throw new ValidationException("Количество на складе не может быть отрицательным");
}
_context.Entry(existingSparePart).State = EntityState.Detached;
var updatedSparePart = _mapper.Map<SparePart>(sparePart);
_context.SpareParts.Update(updatedSparePart);
_context.SaveChanges();
Console.WriteLine($"Update: Запасная часть с ID {sparePart.Id} успешно обновлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении запасной части с ID {sparePart.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ElementExistsException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления запасной части с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID запасной части {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var sparePart = _context.SpareParts.Find(id);
if (sparePart == null)
{
Console.WriteLine($"Delete: Запасная часть с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
_context.SpareParts.Remove(sparePart);
_context.SaveChanges();
Console.WriteLine($"Delete: Запасная часть с ID {id} успешно удалена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении запасной части с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,224 @@
using AutoMapper;
using HookArmsContract.DataModels;
using HookArmsContract.Exceptions;
using HookArmsContract.Extensions;
using HookArmsContract.StorageContracts;
using HookArmsDataBase.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Implementations;
public class WorkStorage : IWorkStorageContract
{
private readonly AutoRepairShopDbContext _context;
private readonly IMapper _mapper;
public WorkStorage(AutoRepairShopDbContext context)
{
_context = context;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Work, WorkDataModel>()
.ConstructUsing((src, ctx) => new WorkDataModel
{
Id = src.Id,
Type = src.Type,
Description = src.Description,
WorkDate = src.WorkDate,
ExecutorId = src.ExecutorId
});
cfg.CreateMap<WorkDataModel, Work>()
.ForMember(dest => dest.Executor, opt => opt.Ignore())
.ForMember(dest => dest.MaintenanceWorks, opt => opt.Ignore())
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore());
});
_mapper = new Mapper(config);
}
public List<WorkDataModel> GetList()
{
try
{
Console.WriteLine("GetList: Запрос списка всех работ");
var works = _context.Works
.Include(w => w.Executor)
.Include(w => w.MaintenanceWorks)
.AsNoTracking()
.ToList();
return _mapper.Map<List<WorkDataModel>>(works);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetList: Ошибка при получении списка работ: {ex.Message}");
throw new StorageException(ex);
}
}
public WorkDataModel GetById(string id)
{
try
{
Console.WriteLine($"GetById: Начало поиска работы по ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"GetById: Некорректный ID работы {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var work = _context.Works
.Include(w => w.Executor)
.Include(w => w.MaintenanceWorks)
.AsNoTracking()
.FirstOrDefault(w => w.Id == id);
if (work == null)
{
Console.WriteLine($"GetById: Работа с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
Console.WriteLine($"GetById: Работа найдена, описание: {work.Description}");
return _mapper.Map<WorkDataModel>(work);
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"GetById: Ошибка при получении работы по ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Add(WorkDataModel work)
{
try
{
Console.WriteLine($"Add: Добавление работы с описанием {work.Description}");
if (work.Id.IsEmpty() || !work.Id.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID работы {work.Id}");
throw new ValidationException("Некорректный ID работы");
}
if (work.WorkDate > DateTime.UtcNow)
{
Console.WriteLine($"Add: Дата работы {work.WorkDate} не может быть в будущем");
throw new ValidationException("Дата работы не может быть в будущем");
}
if (work.ExecutorId.IsEmpty() || !work.ExecutorId.IsGuid())
{
Console.WriteLine($"Add: Некорректный ID исполнителя {work.ExecutorId}");
throw new ValidationException("Некорректный ID исполнителя");
}
if (!_context.Executors.Any(e => e.Id == work.ExecutorId))
{
Console.WriteLine($"Add: Исполнитель с ID {work.ExecutorId} не найден");
throw new ElementNotFoundException(work.ExecutorId);
}
var entity = _mapper.Map<Work>(work);
_context.Works.Add(entity);
_context.SaveChanges();
Console.WriteLine($"Add: Работа с ID {entity.Id} успешно добавлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Add: Ошибка при добавлении работы: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Update(WorkDataModel work)
{
try
{
Console.WriteLine($"Update: Обновление работы с ID {work.Id}");
if (work.Id.IsEmpty() || !work.Id.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID работы {work.Id}");
throw new ValidationException("Некорректный ID работы");
}
var existingWork = _context.Works.Find(work.Id);
if (existingWork == null)
{
Console.WriteLine($"Update: Работа с ID {work.Id} не найдена");
throw new ElementNotFoundException(work.Id);
}
if (work.WorkDate > DateTime.UtcNow)
{
Console.WriteLine($"Update: Дата работы {work.WorkDate} не может быть в будущем");
throw new ValidationException("Дата работы не может быть в будущем");
}
if (work.ExecutorId.IsEmpty() || !work.ExecutorId.IsGuid())
{
Console.WriteLine($"Update: Некорректный ID исполнителя {work.ExecutorId}");
throw new ValidationException("Некорректный ID исполнителя");
}
if (!_context.Executors.Any(e => e.Id == work.ExecutorId))
{
Console.WriteLine($"Update: Исполнитель с ID {work.ExecutorId} не найден");
throw new ElementNotFoundException(work.ExecutorId);
}
_context.Entry(existingWork).State = EntityState.Detached;
var updatedWork = _mapper.Map<Work>(work);
_context.Works.Update(updatedWork);
_context.SaveChanges();
Console.WriteLine($"Update: Работа с ID {work.Id} успешно обновлена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Update: Ошибка при обновлении работы с ID {work.Id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
public void Delete(string id)
{
try
{
Console.WriteLine($"Delete: Начало удаления работы с ID {id}");
if (string.IsNullOrEmpty(id) || !id.IsGuid())
{
Console.WriteLine($"Delete: Некорректный ID работы {id}");
throw new ValidationException("ID должен быть в формате GUID");
}
var work = _context.Works.Find(id);
if (work == null)
{
Console.WriteLine($"Delete: Работа с ID {id} не найдена");
throw new ElementNotFoundException(id);
}
_context.Works.Remove(work);
_context.SaveChanges();
Console.WriteLine($"Delete: Работа с ID {id} успешно удалена");
}
catch (Exception ex)
{
_context.ChangeTracker.Clear();
Console.WriteLine($"Delete: Ошибка при удалении работы с ID {id}: {ex.Message}");
throw ex is ElementNotFoundException or ValidationException ? ex : new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Migrations;
internal class DesignTimeDbContextFactory
{
public AutoRepairShopDbContext CreateDbContext(string[] args)
{
return new AutoRepairShopDbContext(new DefaultConfigurationDatabase());
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Car
{
public string Id { get; set; }
public string LicensePlate { get; set; }
public string Model { get; set; }
public string CustomerId { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационное свойство
public Customer Customer { get; set; }
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Customer
{
public string Id { get; set; }
public string FullName { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационные свойства
public List<Car> Cars { get; set; }
public List<Maintenance> Maintenances { get; set; }
public List<Malfunction> Malfunctions { get; set; }
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Executor
{
public string Id { get; set; }
public string FullName { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационные свойства
public List<Work> Works { get; set; }
public List<Repair> Repairs { get; set; }
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Maintenance
{
public string Id { get; set; }
public DateTime Date { get; set; }
public string Description { get; set; }
public string MachineId { get; set; }
public string CustomerId { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационные свойства
public Car Machine { get; set; }
public Customer Customer { get; set; }
public List<MaintenanceWork> MaintenanceWorks { get; set; }
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class MaintenanceWork
{
public string MaintenanceId { get; set; }
public string WorkId { get; set; }
// Навигационные свойства
public Maintenance Maintenance { get; set; }
public Work Work { get; set; }
}

View File

@@ -0,0 +1,23 @@
using HookArmsContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Malfunction
{
public string Id { get; set; }
public string Description { get; set; }
public MalfunctionType Type { get; set; }
public string CustomerId { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационные свойства
public Customer Customer { get; set; }
public List<MalfunctionRepair> MalfunctionRepairs { get; set; }
public List<MalfunctionCar> MalfunctionCars { get; set; }
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class MalfunctionCar
{
public string MalfunctionId { get; set; }
public string CarId { get; set; }
// Навигационные свойства
public Malfunction Malfunction { get; set; }
public Car Car { get; set; }
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class MalfunctionRepair
{
public string MalfunctionId { get; set; }
public string RepairId { get; set; }
// Навигационные свойства
public Malfunction Malfunction { get; set; }
public Repair Repair { get; set; }
}

View File

@@ -0,0 +1,23 @@
using HookArmsContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Repair
{
public string Id { get; set; }
public string Description { get; set; }
public RepairType Type { get; set; }
public DateTime RepairDate { get; set; }
public string WorkerId { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационные свойства
public Executor Worker { get; set; }
public List<RepairSparePart> RepairSpareParts { get; set; }
public List<MalfunctionRepair> MalfunctionRepairs { get; set; }
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class RepairSparePart
{
public string RepairId { get; set; }
public string SparePartId { get; set; }
public int Quantity { get; set; }
// Навигационные свойства
public Repair Repair { get; set; }
public SparePart SparePart { get; set; }
}

View File

@@ -0,0 +1,24 @@
using HookArmsContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class SparePart
{
public string Id { get; set; }
public string Name { get; set; }
public SparePartType Type { get; set; }
public decimal Price { get; set; }
public string Manufacturer { get; set; }
public string Article { get; set; }
public int Stock { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационное свойство
public List<RepairSparePart> RepairSpareParts { get; set; }
}

View File

@@ -0,0 +1,23 @@
using HookArmsContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HookArmsDataBase.Models;
public class Work
{
public string Id { get; set; }
public WorkType Type { get; set; }
public string Description { get; set; }
public DateTime WorkDate { get; set; }
public string ExecutorId { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационное свойство
public Executor Executor { get; set; }
public List<MaintenanceWork> MaintenanceWorks { get; set; }
}

View File

@@ -7,8 +7,17 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Implementations\" /> <ProjectReference Include="..\HookArmsContract\HookArmsContract.csproj" />
<Folder Include="Models\" /> </ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace HookArmsWebApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.5" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
@HookArmsWebApi_HostAddress = http://localhost:5173
GET {{HookArmsWebApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@@ -0,0 +1,23 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5173",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7193;http://localhost:5173",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,13 @@
namespace HookArmsWebApi
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}