diff --git a/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/ImplementerLogic.cs b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/ImplementerLogic.cs new file mode 100644 index 0000000..c82c57d --- /dev/null +++ b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/ImplementerLogic.cs @@ -0,0 +1,177 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.BusinessLogicsContracts; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.StoragesContracts; +using AircraftPlantContracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantBusinessLogic.BusinessLogics +{ + /// + /// Реализация интерфейса бизнес-логики для исполнителей + /// + public class ImplementerLogic : IImplementerLogic + { + /// + /// Логгер + /// + private readonly ILogger _logger; + + /// + /// Взаимодействие с хранилищем исполнителей + /// + private readonly IImplementerStorage _implementerStorage; + + /// + /// Конструктор + /// + /// + /// + public ImplementerLogic(ILogger logger, IImplementerStorage implementerStorage) + { + _logger = logger; + _implementerStorage = implementerStorage; + } + + /// + /// Получение списка + /// + /// + /// + public List? ReadList(ImplementerSearchModel? model) + { + _logger.LogInformation("ReadList. ImplementerFIO:{ImplementerFIO}.Id:{Id}", model?.ImplementerFIO, model?.Id); + var list = model == null ? _implementerStorage.GetFullList() : _implementerStorage.GetFilteredList(model); + + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + + /// + /// Получение отдельной записи + /// + /// + /// + /// + public ImplementerViewModel? ReadElement(ImplementerSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + + _logger.LogInformation("ReadElement. ImplementerFIO:{ImplementerFIO}.Id:{Id}", model.ImplementerFIO, model.Id); + + var element = _implementerStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + + /// + /// Создание записи + /// + /// + /// + public bool Create(ImplementerBindingModel model) + { + CheckModel(model); + + if (_implementerStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + /// + /// Изменение записи + /// + /// + /// + public bool Update(ImplementerBindingModel model) + { + CheckModel(model); + + if (_implementerStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + + /// + /// Удаление записи + /// + /// + /// + public bool Delete(ImplementerBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + + if (_implementerStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + + private void CheckModel(ImplementerBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.ImplementerFIO)) + { + throw new ArgumentNullException("У исполнителя должно быть ФИО", nameof(model.ImplementerFIO)); + } + if (string.IsNullOrEmpty(model.Password)) + { + throw new ArgumentNullException("У исполнителя должен быть пароль", nameof(model.Password)); + } + if (model.WorkExperience <= 0) + { + throw new ArgumentNullException("У исполнителя стаж должен быть больше 0", nameof(model.WorkExperience)); + } + if (model.Qualification <= 0) + { + throw new ArgumentNullException("У исполнителя квалификация должна быть больше 0", nameof(model.Qualification)); + } + + _logger.LogInformation("Implementer. ImplementerFIO:{ImplementerFIO}.Qualification:{Qualification}.WorkExperience:{WorkExperience} Id: {Id}", model.ImplementerFIO, model.Qualification, model.WorkExperience, model.Id); + var element = _implementerStorage.GetElement(new ImplementerSearchModel + { + ImplementerFIO = model.ImplementerFIO + }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Исполнитель с таким ФИО уже есть"); + } + } + } +} diff --git a/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/OrderLogic.cs b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/OrderLogic.cs index 41901c2..88da590 100644 --- a/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/OrderLogic.cs @@ -78,6 +78,31 @@ namespace AircraftPlantBusinessLogic.BusinessLogics return list; } + /// + /// Получение отдельной записи + /// + /// + /// + /// + public OrderViewModel? ReadElement(OrderSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Id:{ Id}", model.Id); + + var element = _orderStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + /// /// Создание заказа /// @@ -178,7 +203,7 @@ namespace AircraftPlantBusinessLogic.BusinessLogics { throw new ArgumentNullException(nameof(model)); } - if (element.Status + 1 != newStatus) + if (element.Status + 1 != newStatus && element.Status != OrderStatus.Ожидание) { _logger.LogWarning("Change status operation failed"); return false; @@ -186,7 +211,7 @@ namespace AircraftPlantBusinessLogic.BusinessLogics model.Status = newStatus; - if (newStatus == OrderStatus.Выдан) + if (model.Status == OrderStatus.Готов || element.Status == OrderStatus.Ожидание) { var plane = _planeStorage.GetElement(new PlaneSearchModel { Id = element.PlaneId }); if (plane == null) @@ -194,21 +219,22 @@ namespace AircraftPlantBusinessLogic.BusinessLogics _logger.LogWarning("Status change error. Plane not found"); return false; } + if (!CheckSupply(plane, element.Count)) { + model.Status = OrderStatus.Ожидание; _logger.LogWarning("Status change error. Shop is overflowed"); - return false; } - } - - if (model.Status == OrderStatus.Выдан) - { - model.DateImplement = DateTime.Now; + else + { + model.DateImplement = DateTime.Now; + } } else { model.DateImplement = element.DateImplement; } + CheckModel(model, false); if (_orderStorage.Update(model) == null) { diff --git a/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/WorkModeling.cs b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/WorkModeling.cs new file mode 100644 index 0000000..7aba89f --- /dev/null +++ b/AircraftPlant/AircraftPlantBusinessLogic/BusinessLogics/WorkModeling.cs @@ -0,0 +1,232 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.BusinessLogicsContracts; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDataModels.Enums; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantBusinessLogic.BusinessLogics +{ + /// + /// Реализация интерфейса бизнес-логики для имитации деятельности исполнителей + /// + public class WorkModeling : IWorkProcess + { + /// + /// Логгер + /// + private readonly ILogger _logger; + + /// + /// Рандом + /// + private readonly Random _rnd; + + private readonly object orderLock = new object(); + private readonly object waitingOrderLock = new object(); + + /// + /// Бизнес-логика для заказов + /// + private IOrderLogic? _orderLogic; + + /// + /// Конструктор + /// + /// + public WorkModeling(ILogger logger) + { + _logger = logger; + _rnd = new Random(1000); + } + + /// + /// Имитация рабочего процесса + /// + /// + /// + public void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic) + { + _orderLogic = orderLogic; + var implementers = implementerLogic.ReadList(null); + if (implementers == null) + { + _logger.LogWarning("DoWork. Implementers is null"); + return; + } + + var orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Принят }); + + _logger.LogDebug("DoWork for {Count} orders", orders?.Count); + foreach (var implementer in implementers) + { + Task.Run(() => WorkerWorkAsync(implementer, orders)); + } + } + + /// + /// Имитация работы исполнителя + /// + /// + /// + private async Task WorkerWorkAsync(ImplementerViewModel implementer, List orders) + { + if (_orderLogic == null || implementer == null) + { + return; + } + + // Выполняем заказы в статусе "Ожидание" + await RunOrderInWaiting(implementer); + // Выполняем заказы в статусе "Выполняется" + await RunOrderInWork(implementer); + + await Task.Run(() => + { + foreach (var order in orders) + { + try + { + _logger.LogDebug("DoWork. Worker {Id} try get order {Order}", implementer.Id, order.Id); + // пытаемся назначить заказ на исполнителя + lock (orderLock) + { + _orderLogic.TakeOrderInWork(new OrderBindingModel + { + Id = order.Id, + ImplementerId = implementer.Id + }); + } + + // делаем работу + Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 1000) * order.Count); + _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, order.Id); + _orderLogic.DeliveryOrder(new OrderBindingModel + { + Id = order.Id + }); + } + // кто-то мог уже перехватить заказ, игнорируем ошибку + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try get work"); + } + // заканчиваем выполнение имитации в случае иной ошибки + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + + // отдыхаем + Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + } + }); + } + + /// + /// Ищем заказ, которые уже в работе (вдруг исполнителя прервали) + /// + /// + /// + private async Task RunOrderInWork(ImplementerViewModel implementer) + { + if (_orderLogic == null || implementer == null) + { + return; + } + try + { + var runOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel + { + ImplementerId = implementer.Id, + Status = OrderStatus.Выполняется + })); + if (runOrder == null) + { + return; + } + + _logger.LogDebug("DoWork. Worker {Id} back to order {Order}", implementer.Id, runOrder.Id); + // доделываем работу + Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 300) * runOrder.Count); + _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id); + _orderLogic.DeliveryOrder(new OrderBindingModel + { + Id = runOrder.Id + }); + + // отдыхаем + Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + } + // заказа может не быть, просто игнорируем ошибку + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try get work"); + } + // а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + } + + /// + /// Ищем заказ, которые в ожидании + /// + /// + /// + private async Task RunOrderInWaiting(ImplementerViewModel implementer) + { + if (_orderLogic == null || implementer == null) + { + return; + } + try + { + var orders = await Task.Run(() => _orderLogic.ReadList(new OrderSearchModel + { + ImplementerId = implementer.Id, + Status = OrderStatus.Ожидание + })); + if (orders == null) + { + return; + } + + // доделываем работу + foreach (var order in orders) + { + _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, order.Id); + lock (waitingOrderLock) + { + _orderLogic.DeliveryOrder(new OrderBindingModel + { + Id = order.Id + }); + } + + // отдыхаем + Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + } + } + // заказа может не быть, просто игнорируем ошибку + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try get work"); + } + // а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + } + } +} diff --git a/AircraftPlant/AircraftPlantContracts/BindingModels/ImplementerBindingModel.cs b/AircraftPlant/AircraftPlantContracts/BindingModels/ImplementerBindingModel.cs new file mode 100644 index 0000000..5a792b2 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/BindingModels/ImplementerBindingModel.cs @@ -0,0 +1,41 @@ +using AircraftPlantDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.BindingModels +{ + /// + /// Модель для передачи данных пользователя + /// в методы для сохранения данных для исполнителей + /// + public class ImplementerBindingModel : IImplementerModel + { + /// + /// Идентификатор + /// + public int Id { get; set; } + + /// + /// ФИО исполнителя + /// + public string ImplementerFIO { get; set; } = string.Empty; + + /// + /// Пароль + /// + public string Password { get; set; } = string.Empty; + + /// + /// Опыт работы + /// + public int WorkExperience { get; set; } + + /// + /// Квалификация + /// + public int Qualification { get; set; } + } +} diff --git a/AircraftPlant/AircraftPlantContracts/BindingModels/OrderBindingModel.cs b/AircraftPlant/AircraftPlantContracts/BindingModels/OrderBindingModel.cs index eefcb5b..c4d124c 100644 --- a/AircraftPlant/AircraftPlantContracts/BindingModels/OrderBindingModel.cs +++ b/AircraftPlant/AircraftPlantContracts/BindingModels/OrderBindingModel.cs @@ -29,6 +29,11 @@ namespace AircraftPlantContracts.BindingModels /// public int ClientId { get; set; } + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; set; } + /// /// Количество изделий /// diff --git a/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IImplementerLogic.cs b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IImplementerLogic.cs new file mode 100644 index 0000000..3e047e1 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IImplementerLogic.cs @@ -0,0 +1,52 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.BusinessLogicsContracts +{ + /// + /// Интерфейс для описания работы бизнес-логики для исполнителей + /// + public interface IImplementerLogic + { + /// + /// Получение списка + /// + /// + /// + List? ReadList(ImplementerSearchModel? model); + + /// + /// Получение отдельной записи + /// + /// + /// + ImplementerViewModel? ReadElement(ImplementerSearchModel? model); + + /// + /// Создание записи + /// + /// + /// + bool Create(ImplementerBindingModel? model); + + /// + /// Изменение записи + /// + /// + /// + bool Update(ImplementerBindingModel? model); + + /// + /// Удаление записи + /// + /// + /// + bool Delete(ImplementerBindingModel? model); + } +} diff --git a/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IOrderLogic.cs b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IOrderLogic.cs index a329126..8bb3f4c 100644 --- a/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IOrderLogic.cs +++ b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IOrderLogic.cs @@ -21,6 +21,13 @@ namespace AircraftPlantContracts.BusinessLogicsContracts /// List? ReadList(OrderSearchModel? model); + /// + /// Получение отдельной записи + /// + /// + /// + OrderViewModel? ReadElement(OrderSearchModel model); + /// /// Создание заказа /// diff --git a/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IWorkProcess.cs b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IWorkProcess.cs new file mode 100644 index 0000000..21d58d9 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/BusinessLogicsContracts/IWorkProcess.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.BusinessLogicsContracts +{ + /// + /// Интерфейс для описания работы бизнес-логики для имитации деятельности исполнителя + /// + public interface IWorkProcess + { + /// + /// Запуск работ + /// + void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic); + } +} diff --git a/AircraftPlant/AircraftPlantContracts/SearchModels/ImplementerSearchModel.cs b/AircraftPlant/AircraftPlantContracts/SearchModels/ImplementerSearchModel.cs new file mode 100644 index 0000000..1974631 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/SearchModels/ImplementerSearchModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.SearchModels +{ + /// + /// Модель для передачи данных пользователя + /// в методы для поиска данных для исполнителей + /// + public class ImplementerSearchModel + { + /// + /// Идентификатор + /// + public int? Id { get; set; } + + /// + /// ФИО исполнителя + /// + public string? ImplementerFIO { get; set; } + + /// + /// Пароль + /// + public string? Password { get; set; } + } +} diff --git a/AircraftPlant/AircraftPlantContracts/SearchModels/OrderSearchModel.cs b/AircraftPlant/AircraftPlantContracts/SearchModels/OrderSearchModel.cs index dc023be..bce1b81 100644 --- a/AircraftPlant/AircraftPlantContracts/SearchModels/OrderSearchModel.cs +++ b/AircraftPlant/AircraftPlantContracts/SearchModels/OrderSearchModel.cs @@ -1,4 +1,5 @@ -using System; +using AircraftPlantDataModels.Enums; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -22,6 +23,16 @@ namespace AircraftPlantContracts.SearchModels /// public int? ClientId { get; set; } + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; set; } + + /// + /// Статус выполнения заказа + /// + public OrderStatus? Status { get; set; } + /// /// Начало периода выборки данных /// diff --git a/AircraftPlant/AircraftPlantContracts/StoragesContracts/IImplementerStorage.cs b/AircraftPlant/AircraftPlantContracts/StoragesContracts/IImplementerStorage.cs new file mode 100644 index 0000000..c8aff41 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/StoragesContracts/IImplementerStorage.cs @@ -0,0 +1,58 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.StoragesContracts +{ + /// + /// Интерфейс для описания работы с хранилищем для исполнителей + /// + public interface IImplementerStorage + { + /// + /// Получение полного списка + /// + /// + List GetFullList(); + + /// + /// Получение фильтрованного списка + /// + /// + /// + List GetFilteredList(ImplementerSearchModel model); + + /// + /// Получение элемента + /// + /// + /// + ImplementerViewModel? GetElement(ImplementerSearchModel model); + + /// + /// Добавление элемента + /// + /// + /// + ImplementerViewModel? Insert(ImplementerBindingModel model); + + /// + /// Редактирование элемента + /// + /// + /// + ImplementerViewModel? Update(ImplementerBindingModel model); + + /// + /// Удаление элемента + /// + /// + /// + ImplementerViewModel? Delete(ImplementerBindingModel model); + } +} diff --git a/AircraftPlant/AircraftPlantContracts/ViewModels/ImplementerViewModel.cs b/AircraftPlant/AircraftPlantContracts/ViewModels/ImplementerViewModel.cs new file mode 100644 index 0000000..b40ec35 --- /dev/null +++ b/AircraftPlant/AircraftPlantContracts/ViewModels/ImplementerViewModel.cs @@ -0,0 +1,46 @@ +using AircraftPlantDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantContracts.ViewModels +{ + /// + /// Модель для передачи данных пользователю + /// для отображения для исполнителей + /// + public class ImplementerViewModel : IImplementerModel + { + /// + /// Идентификатор + /// + public int Id { get; set; } + + /// + /// ФИО исполнителя + /// + [DisplayName("ФИО исполнителя")] + public string ImplementerFIO { get; set; } = string.Empty; + + /// + /// Пароль + /// + [DisplayName("Пароль")] + public string Password { get; set; } = string.Empty; + + /// + /// Опыт работы + /// + [DisplayName("Опыт работы")] + public int WorkExperience { get; set; } + + /// + /// Квалификация + /// + [DisplayName("Квалификация")] + public int Qualification { get; set; } + } +} diff --git a/AircraftPlant/AircraftPlantContracts/ViewModels/OrderViewModel.cs b/AircraftPlant/AircraftPlantContracts/ViewModels/OrderViewModel.cs index 04e7533..e44dc84 100644 --- a/AircraftPlant/AircraftPlantContracts/ViewModels/OrderViewModel.cs +++ b/AircraftPlant/AircraftPlantContracts/ViewModels/OrderViewModel.cs @@ -43,6 +43,17 @@ namespace AircraftPlantContracts.ViewModels [DisplayName("ФИО клиента")] public string ClientFIO { get; set; } = string.Empty; + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; set; } + + /// + /// ФИО клиента + /// + [DisplayName("ФИО исполнителя")] + public string ImplementerFIO { get; set; } = string.Empty; + /// /// Количество изделий /// diff --git a/AircraftPlant/AircraftPlantDataModels/Enums/OrderStatus.cs b/AircraftPlant/AircraftPlantDataModels/Enums/OrderStatus.cs index ac2308f..4fb6ec4 100644 --- a/AircraftPlant/AircraftPlantDataModels/Enums/OrderStatus.cs +++ b/AircraftPlant/AircraftPlantDataModels/Enums/OrderStatus.cs @@ -19,6 +19,8 @@ namespace AircraftPlantDataModels.Enums Готов = 2, - Выдан = 3 + Выдан = 3, + + Ожидание = 4 } } diff --git a/AircraftPlant/AircraftPlantDataModels/Models/IImplementerModel.cs b/AircraftPlant/AircraftPlantDataModels/Models/IImplementerModel.cs new file mode 100644 index 0000000..01cabea --- /dev/null +++ b/AircraftPlant/AircraftPlantDataModels/Models/IImplementerModel.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantDataModels.Models +{ + /// + /// Интерфейс для модели исполнителя + /// + public interface IImplementerModel : IId + { + /// + /// ФИО исполнителя + /// + string ImplementerFIO { get; } + + /// + /// Пароль + /// + string Password { get; } + + /// + /// Опыт работы + /// + int WorkExperience { get; } + + /// + /// Квалификация + /// + int Qualification { get; } + } +} diff --git a/AircraftPlant/AircraftPlantDataModels/Models/IOrderModel.cs b/AircraftPlant/AircraftPlantDataModels/Models/IOrderModel.cs index bef7a0b..e8b7e57 100644 --- a/AircraftPlant/AircraftPlantDataModels/Models/IOrderModel.cs +++ b/AircraftPlant/AircraftPlantDataModels/Models/IOrderModel.cs @@ -22,6 +22,11 @@ namespace AircraftPlantDataModels.Models /// int ClientId { get; } + /// + /// Идентификатор исполнителя + /// + int? ImplementerId { get; } + /// /// Количество изделий /// diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/AircraftPlantDatabase.cs b/AircraftPlant/AircraftPlantDatabaseImplement/AircraftPlantDatabase.cs index 42d8994..86d720f 100644 --- a/AircraftPlant/AircraftPlantDatabaseImplement/AircraftPlantDatabase.cs +++ b/AircraftPlant/AircraftPlantDatabaseImplement/AircraftPlantDatabase.cs @@ -60,5 +60,10 @@ namespace AircraftPlantDatabaseImplement /// Таблица клиентов /// public virtual DbSet Clients { set; get; } + + /// + /// Таблица исполнителей + /// + public virtual DbSet Implementers { set; get; } } } diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Implements/ImplementerStorage.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..41bee77 --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,136 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.StoragesContracts; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantDatabaseImplement.Implements +{ + /// + /// Реализация интерфейса хранилища для исполнителей + /// + public class ImplementerStorage : IImplementerStorage + { + /// + /// Получение полного списка + /// + /// + public List GetFullList() + { + using var context = new AircraftPlantDatabase(); + return context.Implementers + .Include(x => x.Orders) + .Select(x => x.GetViewModel) + .ToList(); + } + + /// + /// Получение фильтрованного списка + /// + /// + /// + public List GetFilteredList(ImplementerSearchModel model) + { + if (string.IsNullOrEmpty(model.ImplementerFIO)) + { + return new(); + } + + using var context = new AircraftPlantDatabase(); + return context.Implementers + .Include(x => x.Orders) + .Where(x => x.ImplementerFIO.Contains(model.ImplementerFIO)) + .Select(x => x.GetViewModel) + .ToList(); + } + + /// + /// Получение элемента + /// + /// + /// + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + using var context = new AircraftPlantDatabase(); + if (model.Id.HasValue) + return context.Implementers + .Include(x => x.Orders) + .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)? + .GetViewModel; + + else if (!string.IsNullOrEmpty(model.ImplementerFIO) && !string.IsNullOrEmpty(model.Password)) + return context.Implementers.Include(x => x.Orders) + .FirstOrDefault(x => x.ImplementerFIO == model.ImplementerFIO && x.Password == model.Password)? + .GetViewModel; + + else if (!string.IsNullOrEmpty(model.ImplementerFIO)) + return context.Implementers.Include(x => x.Orders) + .FirstOrDefault(x => x.ImplementerFIO == model.ImplementerFIO)? + .GetViewModel; + + return null; + } + + /// + /// Добавление элемента + /// + /// + /// + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + var newImplementer = Implementer.Create(model); + if (newImplementer == null) + { + return null; + } + + using var context = new AircraftPlantDatabase(); + context.Implementers.Add(newImplementer); + context.SaveChanges(); + return newImplementer.GetViewModel; + } + + /// + /// Редактирование элемента + /// + /// + /// + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + using var context = new AircraftPlantDatabase(); + var implementer = context.Implementers.Include(x => x.Orders).FirstOrDefault(x => x.Id == model.Id); + if (implementer == null) + { + return null; + } + + implementer.Update(model); + context.SaveChanges(); + return implementer.GetViewModel; + } + + /// + /// Удаление элемента + /// + /// + /// + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + using var context = new AircraftPlantDatabase(); + var element = context.Implementers.Include(x => x.Orders).FirstOrDefault(x => x.Id == model.Id); + if (element != null) + { + context.Implementers.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Implements/OrderStorage.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Implements/OrderStorage.cs index 3b5c0a4..d7ea784 100644 --- a/AircraftPlant/AircraftPlantDatabaseImplement/Implements/OrderStorage.cs +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Implements/OrderStorage.cs @@ -27,6 +27,7 @@ namespace AircraftPlantDatabaseImplement.Implements return context.Orders .Include(x => x.Plane) .Include(x => x.Client) + .Include(x => x.Implementer) .Select(x => x.GetViewModel) .ToList(); } @@ -38,7 +39,7 @@ namespace AircraftPlantDatabaseImplement.Implements /// public List GetFilteredList(OrderSearchModel model) { - if (!model.Id.HasValue && !model.ClientId.HasValue && (!model.DateFrom.HasValue || !model.DateTo.HasValue)) + if (!model.Id.HasValue && !model.ClientId.HasValue && (!model.DateFrom.HasValue || !model.DateTo.HasValue) && model.Status == null) { return new(); } @@ -50,6 +51,7 @@ namespace AircraftPlantDatabaseImplement.Implements return context.Orders .Include(x => x.Plane) .Include(x => x.Client) + .Include(x => x.Implementer) .Where(x => x.DateCreate >= model.DateFrom && x.DateCreate <= model.DateTo) .Select(x => x.GetViewModel) .ToList(); @@ -60,11 +62,23 @@ namespace AircraftPlantDatabaseImplement.Implements return context.Orders .Include(x => x.Plane) .Include(x => x.Client) + .Include(x => x.Implementer) .Where(x => x.ClientId == model.ClientId) .Select(x => x.GetViewModel) .ToList(); } + if (model.Status.HasValue) + { + return context.Orders + .Include(x => x.Plane) + .Include(x => x.Client) + .Include(x => x.Implementer) + .Where(x => x.Status == model.Status) + .Select(x => x.GetViewModel) + .ToList(); + } + return context.Orders .Include(x => x.Plane) .Include(x => x.Client) @@ -86,11 +100,37 @@ namespace AircraftPlantDatabaseImplement.Implements } using var context = new AircraftPlantDatabase(); - return context.Orders - .Include(x => x.Plane) - .Include(x => x.Client) - .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id))? - .GetViewModel; + if (model.Id.HasValue) + { + return context.Orders + .Include(x => x.Plane) + .Include(x => x.Client) + .Include(x => x.Implementer) + .FirstOrDefault(x => x.Id == model.Id) + ?.GetViewModel; + } + + if (model.ImplementerId.HasValue && model.Status.HasValue) + { + return context.Orders + .Include(x => x.Plane) + .Include(x => x.Client) + .Include(x => x.Implementer) + .FirstOrDefault(x => x.ImplementerId == model.ImplementerId && x.Status == model.Status) + ?.GetViewModel; + } + + if (model.ImplementerId.HasValue) + { + return context.Orders + .Include(x => x.Plane) + .Include(x => x.Client) + .Include(x => x.Implementer) + .FirstOrDefault(x => x.ImplementerId == model.ImplementerId) + ?.GetViewModel; + } + + return null; } /// diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.Designer.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.Designer.cs new file mode 100644 index 0000000..9cbb898 --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.Designer.cs @@ -0,0 +1,260 @@ +// +using System; +using AircraftPlantDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AircraftPlantDatabaseImplement.Migrations +{ + [DbContext(typeof(AircraftPlantDatabase))] + [Migration("20240419180448_AddImplementers")] + partial class AddImplementers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Clients"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ImplementerFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Qualification") + .HasColumnType("int"); + + b.Property("WorkExperience") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Implementers"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("ImplementerId") + .IsRequired() + .HasColumnType("int"); + + b.Property("PlaneId") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("ImplementerId"); + + b.HasIndex("PlaneId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Plane", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("PlaneName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Planes"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.PlaneComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("PlaneId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("PlaneId"); + + b.ToTable("PlaneComponents"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Order", b => + { + b.HasOne("AircraftPlantDatabaseImplement.Models.Client", "Client") + .WithMany("Orders") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Implementer", "Implementer") + .WithMany("Orders") + .HasForeignKey("ImplementerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Plane", "Plane") + .WithMany("Orders") + .HasForeignKey("PlaneId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Implementer"); + + b.Navigation("Plane"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.PlaneComponent", b => + { + b.HasOne("AircraftPlantDatabaseImplement.Models.Component", "Component") + .WithMany("PlaneComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Plane", "Plane") + .WithMany("Components") + .HasForeignKey("PlaneId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Plane"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Client", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Component", b => + { + b.Navigation("PlaneComponents"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Plane", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.cs new file mode 100644 index 0000000..fcb244a --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240419180448_AddImplementers.cs @@ -0,0 +1,69 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AircraftPlantDatabaseImplement.Migrations +{ + /// + public partial class AddImplementers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImplementerId", + table: "Orders", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "Implementers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ImplementerFIO = table.Column(type: "nvarchar(max)", nullable: false), + Password = table.Column(type: "nvarchar(max)", nullable: false), + WorkExperience = table.Column(type: "int", nullable: false), + Qualification = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Implementers", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Orders_ImplementerId", + table: "Orders", + column: "ImplementerId"); + + migrationBuilder.AddForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders", + column: "ImplementerId", + principalTable: "Implementers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders"); + + migrationBuilder.DropTable( + name: "Implementers"); + + migrationBuilder.DropIndex( + name: "IX_Orders_ImplementerId", + table: "Orders"); + + migrationBuilder.DropColumn( + name: "ImplementerId", + table: "Orders"); + } + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.Designer.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.Designer.cs new file mode 100644 index 0000000..72443d8 --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.Designer.cs @@ -0,0 +1,257 @@ +// +using System; +using AircraftPlantDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AircraftPlantDatabaseImplement.Migrations +{ + [DbContext(typeof(AircraftPlantDatabase))] + [Migration("20240420181402_FixImplementers")] + partial class FixImplementers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Clients"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ImplementerFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Qualification") + .HasColumnType("int"); + + b.Property("WorkExperience") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Implementers"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("ImplementerId") + .HasColumnType("int"); + + b.Property("PlaneId") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("ImplementerId"); + + b.HasIndex("PlaneId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Plane", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("PlaneName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Planes"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.PlaneComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("PlaneId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("PlaneId"); + + b.ToTable("PlaneComponents"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Order", b => + { + b.HasOne("AircraftPlantDatabaseImplement.Models.Client", "Client") + .WithMany("Orders") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Implementer", "Implementer") + .WithMany("Orders") + .HasForeignKey("ImplementerId"); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Plane", "Plane") + .WithMany("Orders") + .HasForeignKey("PlaneId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Implementer"); + + b.Navigation("Plane"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.PlaneComponent", b => + { + b.HasOne("AircraftPlantDatabaseImplement.Models.Component", "Component") + .WithMany("PlaneComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AircraftPlantDatabaseImplement.Models.Plane", "Plane") + .WithMany("Components") + .HasForeignKey("PlaneId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Plane"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Client", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Component", b => + { + b.Navigation("PlaneComponents"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Plane", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.cs new file mode 100644 index 0000000..03aeff3 --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/20240420181402_FixImplementers.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AircraftPlantDatabaseImplement.Migrations +{ + /// + public partial class FixImplementers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders"); + + migrationBuilder.AlterColumn( + name: "ImplementerId", + table: "Orders", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders", + column: "ImplementerId", + principalTable: "Implementers", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders"); + + migrationBuilder.AlterColumn( + name: "ImplementerId", + table: "Orders", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders", + column: "ImplementerId", + principalTable: "Implementers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/AircraftPlantDatabaseModelSnapshot.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/AircraftPlantDatabaseModelSnapshot.cs index 7cd6f28..7bfbe92 100644 --- a/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/AircraftPlantDatabaseModelSnapshot.cs +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Migrations/AircraftPlantDatabaseModelSnapshot.cs @@ -67,6 +67,33 @@ namespace AircraftPlantDatabaseImplement.Migrations b.ToTable("Components"); }); + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ImplementerFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Qualification") + .HasColumnType("int"); + + b.Property("WorkExperience") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Implementers"); + }); + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -87,6 +114,9 @@ namespace AircraftPlantDatabaseImplement.Migrations b.Property("DateImplement") .HasColumnType("datetime2"); + b.Property("ImplementerId") + .HasColumnType("int"); + b.Property("PlaneId") .HasColumnType("int"); @@ -100,6 +130,8 @@ namespace AircraftPlantDatabaseImplement.Migrations b.HasIndex("ClientId"); + b.HasIndex("ImplementerId"); + b.HasIndex("PlaneId"); b.ToTable("Orders"); @@ -212,6 +244,10 @@ namespace AircraftPlantDatabaseImplement.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("AircraftPlantDatabaseImplement.Models.Implementer", "Implementer") + .WithMany("Orders") + .HasForeignKey("ImplementerId"); + b.HasOne("AircraftPlantDatabaseImplement.Models.Plane", "Plane") .WithMany("Orders") .HasForeignKey("PlaneId") @@ -220,6 +256,8 @@ namespace AircraftPlantDatabaseImplement.Migrations b.Navigation("Client"); + b.Navigation("Implementer"); + b.Navigation("Plane"); }); @@ -271,6 +309,11 @@ namespace AircraftPlantDatabaseImplement.Migrations b.Navigation("PlaneComponents"); }); + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Implementer", b => + { + b.Navigation("Orders"); + }); + modelBuilder.Entity("AircraftPlantDatabaseImplement.Models.Plane", b => { b.Navigation("Components"); diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Models/Implementer.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Models/Implementer.cs new file mode 100644 index 0000000..dc5855f --- /dev/null +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Models/Implementer.cs @@ -0,0 +1,105 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantDatabaseImplement.Models +{ + /// + /// Сущность "Исполнитель" + /// + public class Implementer : IImplementerModel + { + /// + /// Идентификатор + /// + public int Id { get; private set; } + + /// + /// ФИО исполнителя + /// + [Required] + public string ImplementerFIO { get; private set; } = string.Empty; + + /// + /// Пароль + /// + [Required] + public string Password { get; private set; } = string.Empty; + + /// + /// Опыт работы + /// + [Required] + public int WorkExperience { get; private set; } + + /// + /// Квалификация + /// + [Required] + public int Qualification { get; private set; } + + /// + /// Связь с заказами + /// + [ForeignKey("ImplementerId")] + public virtual List Orders { get; set; } = new(); + + /// + /// Создание модели исполнителя + /// + /// + /// + public static Implementer? Create(ImplementerBindingModel model) + { + if (model == null) + { + return null; + } + + return new Implementer() + { + Id = model.Id, + ImplementerFIO = model.ImplementerFIO, + Password = model.Password, + WorkExperience = model.WorkExperience, + Qualification = model.Qualification + }; + } + + /// + /// Изменение модели исполнителя + /// + /// + public void Update(ImplementerBindingModel model) + { + if (model == null) + { + return; + } + + ImplementerFIO = model.ImplementerFIO; + Password = model.Password; + WorkExperience = model.WorkExperience; + Qualification = model.Qualification; + } + + /// + /// Получение модели исполнителя + /// + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + ImplementerFIO = ImplementerFIO, + Password = Password, + WorkExperience = WorkExperience, + Qualification = Qualification, + }; + } +} diff --git a/AircraftPlant/AircraftPlantDatabaseImplement/Models/Order.cs b/AircraftPlant/AircraftPlantDatabaseImplement/Models/Order.cs index 1e6f314..7fad501 100644 --- a/AircraftPlant/AircraftPlantDatabaseImplement/Models/Order.cs +++ b/AircraftPlant/AircraftPlantDatabaseImplement/Models/Order.cs @@ -43,6 +43,16 @@ namespace AircraftPlantDatabaseImplement.Models /// public Client Client { get; set; } = new(); + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; set; } + + /// + /// Сущность "Исполнитель" + /// + public virtual Implementer? Implementer { get; set; } = new(); + /// /// Количество изделий /// @@ -91,6 +101,8 @@ namespace AircraftPlantDatabaseImplement.Models Plane = context.Planes.First(x => x.Id == model.PlaneId), ClientId = model.ClientId, Client = context.Clients.First(x => x.Id == model.ClientId), + ImplementerId = model.ImplementerId, + Implementer = model.ImplementerId.HasValue ? context.Implementers.First(x => x.Id == model.ImplementerId) : null, Count = model.Count, Sum = model.Sum, Status = model.Status, @@ -112,6 +124,8 @@ namespace AircraftPlantDatabaseImplement.Models Status = model.Status; DateImplement = model.DateImplement; + if (model.ImplementerId.HasValue) + ImplementerId = model.ImplementerId; } /// @@ -124,6 +138,8 @@ namespace AircraftPlantDatabaseImplement.Models PlaneName = Plane.PlaneName, ClientId = ClientId, ClientFIO = Client.ClientFIO, + ImplementerId = ImplementerId, + ImplementerFIO = Implementer?.ImplementerFIO ?? string.Empty, Count = Count, Sum = Sum, Status = Status, diff --git a/AircraftPlant/AircraftPlantFileImplement/DataFileSingleton.cs b/AircraftPlant/AircraftPlantFileImplement/DataFileSingleton.cs index fc4e143..f9920ec 100644 --- a/AircraftPlant/AircraftPlantFileImplement/DataFileSingleton.cs +++ b/AircraftPlant/AircraftPlantFileImplement/DataFileSingleton.cs @@ -43,6 +43,11 @@ namespace AircraftPlantFileImplement /// private readonly string ShopFileName = "Shop.xml"; + /// + /// Название файла для хранения информации о исполнителях + /// + private readonly string ImplementerFileName = "Implementer.xml"; + /// /// Список классов-моделей компонентов /// @@ -68,6 +73,11 @@ namespace AircraftPlantFileImplement /// public List Clients { get; set; } + /// + /// Список классов-моделей исполнителей + /// + public List Implementers { get; set; } + /// /// Конструктор /// @@ -78,6 +88,7 @@ namespace AircraftPlantFileImplement Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; Shops = LoadData(ShopFileName, "Shop", x => Shop.Create(x)!)!; Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; + Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!; } /// @@ -118,6 +129,11 @@ namespace AircraftPlantFileImplement /// public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); + /// + /// Сохранение исполнителей + /// + public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement); + /// /// Метод для загрузки данных из xml-файла /// diff --git a/AircraftPlant/AircraftPlantFileImplement/Implements/ImplementerStorage.cs b/AircraftPlant/AircraftPlantFileImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..3ae089f --- /dev/null +++ b/AircraftPlant/AircraftPlantFileImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,137 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.StoragesContracts; +using AircraftPlantContracts.ViewModels; +using AircraftPlantFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantFileImplement.Implements +{ + /// + /// Реализация интерфейса хранилища для исполнителей + /// + public class ImplementerStorage : IImplementerStorage + { + /// + /// Хранилище + /// + private readonly DataFileSingleton _source; + + /// + /// Конструктор + /// + public ImplementerStorage() + { + _source = DataFileSingleton.GetInstance(); + } + + /// + /// Получение полного списка + /// + /// + public List GetFullList() + { + return _source.Implementers + .Select(x => x.GetViewModel) + .ToList(); + } + + /// + /// Получение фильтрованного списка + /// + /// + /// + public List GetFilteredList(ImplementerSearchModel model) + { + if (string.IsNullOrEmpty(model.ImplementerFIO)) + { + return new(); + } + + return _source.Implementers + .Where(x => x.ImplementerFIO.Contains(model.ImplementerFIO)) + .Select(x => x.GetViewModel) + .ToList(); + } + + /// + /// Получение элемента + /// + /// + /// + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + if (!string.IsNullOrEmpty(model.ImplementerFIO) || model.Id.HasValue) + { + return _source.Implementers.FirstOrDefault(x => + (!string.IsNullOrEmpty(model.ImplementerFIO) && x.ImplementerFIO == model.ImplementerFIO) || + (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + + else if (!string.IsNullOrEmpty(model.ImplementerFIO) && !string.IsNullOrEmpty(model.Password)) + return _source.Implementers.FirstOrDefault(x => + x.ImplementerFIO == model.ImplementerFIO && x.Password == model.Password)?.GetViewModel; + + return null; + } + + /// + /// Добавление элемента + /// + /// + /// + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + model.Id = _source.Implementers.Count > 0 ? _source.Implementers.Max(x => x.Id) + 1 : 1; + + var newImplementer = Implementer.Create(model); + if (newImplementer == null) + { + return null; + } + + _source.Implementers.Add(newImplementer); + _source.SaveImplementers(); + return newImplementer.GetViewModel; + } + + /// + /// Редактирование элемента + /// + /// + /// + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + var implementer = _source.Implementers.FirstOrDefault(x => x.Id == model.Id); + if (implementer == null) + { + return null; + } + + implementer.Update(model); + _source.SaveImplementers(); + return implementer.GetViewModel; + } + + /// + /// Удаление элемента + /// + /// + /// + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + var element = _source.Implementers.FirstOrDefault(x => x.Id == model.Id); + if (element != null) + { + _source.Implementers.Remove(element); + _source.SaveImplementers(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/AircraftPlant/AircraftPlantFileImplement/Models/Implementer.cs b/AircraftPlant/AircraftPlantFileImplement/Models/Implementer.cs new file mode 100644 index 0000000..d03f21f --- /dev/null +++ b/AircraftPlant/AircraftPlantFileImplement/Models/Implementer.cs @@ -0,0 +1,126 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace AircraftPlantFileImplement.Models +{ + /// + /// Сущность "Исполнитель" + /// + public class Implementer : IImplementerModel + { + /// + /// Идентификатор + /// + public int Id { get; private set; } + + /// + /// ФИО исполнителя + /// + public string ImplementerFIO { get; private set; } = string.Empty; + + /// + /// Пароль + /// + public string Password { get; private set; } = string.Empty; + + /// + /// Опыт работы + /// + public int WorkExperience { get; private set; } + + /// + /// Квалификация + /// + public int Qualification { get; private set; } + + /// + /// Создание модели исполнителя + /// + /// + /// + public static Implementer? Create(ImplementerBindingModel? model) + { + if (model == null) + { + return null; + } + + return new Implementer() + { + Id = model.Id, + ImplementerFIO = model.ImplementerFIO, + Password = model.Password, + WorkExperience = model.WorkExperience, + Qualification = model.Qualification, + }; + } + + /// + /// Создание модели исполнителя из данных файла + /// + /// + /// + public static Implementer? Create(XElement element) + { + if (element == null) + { + return null; + } + + return new Implementer() + { + Id = Convert.ToInt32(element.Attribute("Id")!.Value), + ImplementerFIO = element.Element("ImplementerFIO")!.Value, + Password = element.Element("Password")!.Value, + WorkExperience = Convert.ToInt32(element.Element("WorkExperience")!.Value), + Qualification = Convert.ToInt32(element.Element("Qualification")!.Value) + }; + } + + /// + /// Изменение модели исполнителя + /// + /// + public void Update(ImplementerBindingModel? model) + { + if (model == null) + { + return; + } + + ImplementerFIO = model.ImplementerFIO; + Password = model.Password; + WorkExperience = model.WorkExperience; + Qualification = model.Qualification; + } + + /// + /// Получение модели исполнителя + /// + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + ImplementerFIO = ImplementerFIO, + Password = Password, + WorkExperience = WorkExperience, + Qualification = Qualification + }; + + /// + /// Запись данных о модели исполнителя в файл + /// + public XElement GetXElement => new("Implementer", + new XAttribute("Id", Id), + new XElement("ImplementerFIO", ImplementerFIO), + new XElement("Password", Password), + new XElement("WorkExperience", WorkExperience), + new XElement("Qualification", Qualification)); + } +} diff --git a/AircraftPlant/AircraftPlantFileImplement/Models/Order.cs b/AircraftPlant/AircraftPlantFileImplement/Models/Order.cs index 322b008..6eac33f 100644 --- a/AircraftPlant/AircraftPlantFileImplement/Models/Order.cs +++ b/AircraftPlant/AircraftPlantFileImplement/Models/Order.cs @@ -31,6 +31,11 @@ namespace AircraftPlantFileImplement.Models /// public int ClientId { get; private set; } + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; private set; } + /// /// Количество изделий /// @@ -73,6 +78,7 @@ namespace AircraftPlantFileImplement.Models Id = model.Id, PlaneId = model.PlaneId, ClientId = model.ClientId, + ImplementerId = model.ImplementerId, Count = model.Count, Sum = model.Sum, Status = model.Status, @@ -98,6 +104,7 @@ namespace AircraftPlantFileImplement.Models Id = Convert.ToInt32(element.Attribute("Id")!.Value), PlaneId = Convert.ToInt32(element.Element("PlaneId")!.Value), ClientId = Convert.ToInt32(element.Element("ClientId")!.Value), + ImplementerId = Convert.ToInt32(element.Element("ImplementerId")!.Value), Sum = Convert.ToDouble(element.Element("Sum")!.Value), Count = Convert.ToInt32(element.Element("Count")!.Value), Status = (OrderStatus)Enum.Parse(typeof(OrderStatus), element.Element("Status")!.Value), @@ -119,6 +126,8 @@ namespace AircraftPlantFileImplement.Models Status = model.Status; DateImplement = model.DateImplement; + if (model.ImplementerId.HasValue) + ImplementerId = model.ImplementerId; } /// @@ -129,6 +138,7 @@ namespace AircraftPlantFileImplement.Models Id = Id, PlaneId = PlaneId, ClientId = ClientId, + ImplementerId = ImplementerId, Count = Count, Sum = Sum, Status = Status, @@ -143,6 +153,7 @@ namespace AircraftPlantFileImplement.Models new XAttribute("Id", Id), new XElement("PlaneId", PlaneId), new XElement("ClientId", ClientId), + new XElement("ImplementerId", ImplementerId), new XElement("Count", Count.ToString()), new XElement("Sum", Sum.ToString()), new XElement("Status", Status.ToString()), diff --git a/AircraftPlant/AircraftPlantListImplement/DataListSingleton.cs b/AircraftPlant/AircraftPlantListImplement/DataListSingleton.cs index d19a8f8..9671eca 100644 --- a/AircraftPlant/AircraftPlantListImplement/DataListSingleton.cs +++ b/AircraftPlant/AircraftPlantListImplement/DataListSingleton.cs @@ -42,6 +42,11 @@ namespace AircraftPlantListImplement /// public List Clients { get; set; } + /// + /// Список классов-моделей исполнителей + /// + public List Implementers { get; set; } + /// /// Конструктор /// @@ -52,6 +57,7 @@ namespace AircraftPlantListImplement Planes = new List(); Shops = new List(); Clients = new List(); + Implementers = new List(); } /// diff --git a/AircraftPlant/AircraftPlantListImplement/Implements/ImplementerStorage.cs b/AircraftPlant/AircraftPlantListImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..949354b --- /dev/null +++ b/AircraftPlant/AircraftPlantListImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,157 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.StoragesContracts; +using AircraftPlantContracts.ViewModels; +using AircraftPlantListImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantListImplement.Implements +{ + /// + /// Реализация интерфейса хранилища для исполнителей + /// + public class ImplementerStorage : IImplementerStorage + { + /// + /// Хранилище + /// + private readonly DataListSingleton _source; + + /// + /// Конструктор + /// + public ImplementerStorage() + { + _source = DataListSingleton.GetInstance(); + } + + /// + /// Получение полного списка + /// + /// + public List GetFullList() + { + var result = new List(); + foreach (var implementer in _source.Implementers) + { + result.Add(implementer.GetViewModel); + } + return result; + } + + /// + /// Получение фильтрованного списка + /// + /// + /// + public List GetFilteredList(ImplementerSearchModel model) + { + var result = new List(); + if (string.IsNullOrEmpty(model.ImplementerFIO)) + { + return result; + } + + foreach (var implementer in _source.Implementers) + { + if (implementer.ImplementerFIO.Contains(model.ImplementerFIO)) + { + result.Add(implementer.GetViewModel); + } + } + return result; + } + + /// + /// Получение элемента + /// + /// + /// + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + if (string.IsNullOrEmpty(model.ImplementerFIO) && string.IsNullOrEmpty(model.Password) && !model.Id.HasValue) + { + return null; + } + + foreach (var implementer in _source.Implementers) + { + if (model.Id.HasValue && model.Id == implementer.Id) + return implementer.GetViewModel; + if (!string.IsNullOrEmpty(model.ImplementerFIO) && !string.IsNullOrEmpty(model.Password) && + implementer.ImplementerFIO.Equals(model.ImplementerFIO) && implementer.Password.Equals(model.Password)) + return implementer.GetViewModel; + if (!string.IsNullOrEmpty(model.ImplementerFIO) && implementer.ImplementerFIO.Equals(model.ImplementerFIO)) + return implementer.GetViewModel; + } + return null; + } + + /// + /// Добавление элемента + /// + /// + /// + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + model.Id = 1; + foreach (var implementer in _source.Implementers) + { + if (model.Id <= implementer.Id) + { + model.Id = implementer.Id + 1; + } + } + + var newImplementer = Implementer.Create(model); + if (newImplementer == null) + { + return null; + } + + _source.Implementers.Add(newImplementer); + return newImplementer.GetViewModel; + } + + /// + /// Редактирование элемента + /// + /// + /// + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + foreach (var implementer in _source.Implementers) + { + if (implementer.Id == model.Id) + { + implementer.Update(model); + return implementer.GetViewModel; + } + } + return null; + } + + /// + /// Удаление элемента + /// + /// + /// + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + for (int i = 0; i < _source.Implementers.Count; ++i) + { + if (_source.Implementers[i].Id == model.Id) + { + var element = _source.Implementers[i]; + _source.Implementers.RemoveAt(i); + return element.GetViewModel; + } + } + return null; + } + } +} diff --git a/AircraftPlant/AircraftPlantListImplement/Models/Implementer.cs b/AircraftPlant/AircraftPlantListImplement/Models/Implementer.cs new file mode 100644 index 0000000..9e16280 --- /dev/null +++ b/AircraftPlant/AircraftPlantListImplement/Models/Implementer.cs @@ -0,0 +1,93 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AircraftPlantListImplement.Models +{ + /// + /// Сущность "Исполнитель" + /// + public class Implementer : IImplementerModel + { + /// + /// Идентификатор + /// + public int Id { get; private set; } + + /// + /// ФИО исполнителя + /// + public string ImplementerFIO { get; private set; } = string.Empty; + + /// + /// Пароль + /// + public string Password { get; private set; } = string.Empty; + + /// + /// Опыт работы + /// + public int WorkExperience { get; private set; } + + /// + /// Квалификация + /// + public int Qualification { get; private set; } + + /// + /// Создание модели исполнителя + /// + /// + /// + public static Implementer? Create(ImplementerBindingModel? model) + { + if (model == null) + { + return null; + } + + return new Implementer() + { + Id = model.Id, + ImplementerFIO = model.ImplementerFIO, + Password = model.Password, + WorkExperience = model.WorkExperience, + Qualification = model.Qualification, + }; + } + + /// + /// Изменение модели исполнителя + /// + /// + public void Update(ImplementerBindingModel? model) + { + if (model == null) + { + return; + } + + ImplementerFIO = model.ImplementerFIO; + Password = model.Password; + WorkExperience = model.WorkExperience; + Qualification = model.Qualification; + } + + /// + /// Получение модели исполнителя + /// + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + ImplementerFIO = ImplementerFIO, + Password = Password, + WorkExperience = WorkExperience, + Qualification = Qualification + }; + } +} diff --git a/AircraftPlant/AircraftPlantListImplement/Models/Order.cs b/AircraftPlant/AircraftPlantListImplement/Models/Order.cs index 15edd6b..dd59f97 100644 --- a/AircraftPlant/AircraftPlantListImplement/Models/Order.cs +++ b/AircraftPlant/AircraftPlantListImplement/Models/Order.cs @@ -30,6 +30,11 @@ namespace AircraftPlantListImplement.Models /// public int ClientId { get; private set; } + /// + /// Идентификатор исполнителя + /// + public int? ImplementerId { get; private set; } + /// /// Количество изделий /// @@ -72,6 +77,7 @@ namespace AircraftPlantListImplement.Models Id = model.Id, PlaneId = model.PlaneId, ClientId = model.ClientId, + ImplementerId = model.ImplementerId, Count = model.Count, Sum = model.Sum, Status = model.Status, @@ -93,6 +99,8 @@ namespace AircraftPlantListImplement.Models Status = model.Status; DateImplement = model.DateImplement; + if (model.ImplementerId.HasValue) + ImplementerId = model.ImplementerId; } /// @@ -103,6 +111,7 @@ namespace AircraftPlantListImplement.Models Id = Id, PlaneId = PlaneId, ClientId = ClientId, + ImplementerId = ImplementerId, Count = Count, Sum = Sum, Status = Status, diff --git a/AircraftPlant/AircraftPlantRestApi/Controllers/ImplementerController.cs b/AircraftPlant/AircraftPlantRestApi/Controllers/ImplementerController.cs new file mode 100644 index 0000000..2b98acf --- /dev/null +++ b/AircraftPlant/AircraftPlantRestApi/Controllers/ImplementerController.cs @@ -0,0 +1,148 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.BusinessLogicsContracts; +using AircraftPlantContracts.SearchModels; +using AircraftPlantContracts.ViewModels; +using AircraftPlantDataModels.Enums; +using Microsoft.AspNetCore.Mvc; + +namespace AircraftPlantRestApi.Controllers +{ + /// + /// Контроллер для работы с исполнителями + /// + [Route("api/[controller]/[action]")] + [ApiController] + public class ImplementerController : Controller + { + /// + /// Логгер + /// + private readonly ILogger _logger; + + /// + /// Бизнес-логика для заказов + /// + private readonly IOrderLogic _orderLogic; + + /// + /// Бизнес-логика для исполнителей + /// + private readonly IImplementerLogic _implementerLogic; + + /// + /// Конструктор + /// + /// + /// + /// + public ImplementerController(IOrderLogic orderLogic, IImplementerLogic implementerLogic, ILogger logger) + { + _logger = logger; + _orderLogic = orderLogic; + _implementerLogic = implementerLogic; + } + + /// + /// Авторизация исполнителя + /// + /// + /// + /// + [HttpGet] + public ImplementerViewModel? Login(string login, string password) + { + try + { + return _implementerLogic.ReadElement(new ImplementerSearchModel + { + ImplementerFIO = login, + Password = password + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка входа сотрудника"); + throw; + } + } + + /// + /// Получение новых заказов + /// + /// + [HttpGet] + public List? GetNewOrders() + { + try + { + return _orderLogic.ReadList(new OrderSearchModel + { + Status = OrderStatus.Принят + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения новых заказов"); + throw; + } + } + + /// + /// Получение текущего заказа исполнителя + /// + /// + /// + [HttpGet] + public OrderViewModel? GetImplementerOrder(int implementerId) + { + try + { + return _orderLogic.ReadElement(new OrderSearchModel + { + ImplementerId = implementerId + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения текущего заказа исполнителя"); + throw; + } + } + + /// + /// Смена статуса заказа (Выполняется) + /// + /// + [HttpPost] + public void TakeOrderInWork(OrderBindingModel model) + { + try + { + _orderLogic.TakeOrderInWork(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка перевода заказа с №{Id} в работу", model.Id); + throw; + } + } + + /// + /// Смена статуса заказа (Выдан) + /// + /// + [HttpPost] + public void FinishOrder(OrderBindingModel model) + { + try + { + _orderLogic.FinishOrder(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отметки о готовности заказа с №{Id}", model.Id); + throw; + } + } + } +} diff --git a/AircraftPlant/AircraftPlantRestApi/Program.cs b/AircraftPlant/AircraftPlantRestApi/Program.cs index 6be259b..065db15 100644 --- a/AircraftPlant/AircraftPlantRestApi/Program.cs +++ b/AircraftPlant/AircraftPlantRestApi/Program.cs @@ -11,12 +11,14 @@ builder.Logging.AddLog4Net("log4net.config"); // Add services to the container. builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); -builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/AircraftPlant/AircraftPlantView/FormImplementer.Designer.cs b/AircraftPlant/AircraftPlantView/FormImplementer.Designer.cs new file mode 100644 index 0000000..b2fe207 --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementer.Designer.cs @@ -0,0 +1,166 @@ +namespace AircraftPlantView +{ + partial class FormImplementer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + textBoxImplementerFIO = new TextBox(); + textBoxPassword = new TextBox(); + numericUpDownWorkExperience = new NumericUpDown(); + numericUpDownQualification = new NumericUpDown(); + buttonCancel = new Button(); + labelImplementerFIO = new Label(); + labelPassword = new Label(); + labelWorkExperience = new Label(); + labelQualification = new Label(); + buttonSave = new Button(); + ((System.ComponentModel.ISupportInitialize)numericUpDownWorkExperience).BeginInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownQualification).BeginInit(); + SuspendLayout(); + // + // textBoxImplementerFIO + // + textBoxImplementerFIO.Location = new Point(108, 12); + textBoxImplementerFIO.Name = "textBoxImplementerFIO"; + textBoxImplementerFIO.Size = new Size(264, 23); + textBoxImplementerFIO.TabIndex = 0; + // + // textBoxPassword + // + textBoxPassword.Location = new Point(108, 41); + textBoxPassword.Name = "textBoxPassword"; + textBoxPassword.Size = new Size(264, 23); + textBoxPassword.TabIndex = 1; + // + // numericUpDownWorkExperience + // + numericUpDownWorkExperience.Location = new Point(108, 70); + numericUpDownWorkExperience.Name = "numericUpDownWorkExperience"; + numericUpDownWorkExperience.Size = new Size(264, 23); + numericUpDownWorkExperience.TabIndex = 2; + // + // numericUpDownQualification + // + numericUpDownQualification.Location = new Point(108, 99); + numericUpDownQualification.Name = "numericUpDownQualification"; + numericUpDownQualification.Size = new Size(264, 23); + numericUpDownQualification.TabIndex = 3; + // + // buttonCancel + // + buttonCancel.Location = new Point(297, 134); + buttonCancel.Name = "buttonCancel"; + buttonCancel.Size = new Size(75, 23); + buttonCancel.TabIndex = 4; + buttonCancel.Text = "Отмена"; + buttonCancel.UseVisualStyleBackColor = true; + buttonCancel.Click += buttonCancel_Click; + // + // labelImplementerFIO + // + labelImplementerFIO.AutoSize = true; + labelImplementerFIO.Location = new Point(12, 15); + labelImplementerFIO.Name = "labelImplementerFIO"; + labelImplementerFIO.Size = new Size(37, 15); + labelImplementerFIO.TabIndex = 5; + labelImplementerFIO.Text = "ФИО:"; + // + // labelPassword + // + labelPassword.AutoSize = true; + labelPassword.Location = new Point(11, 44); + labelPassword.Name = "labelPassword"; + labelPassword.Size = new Size(52, 15); + labelPassword.TabIndex = 6; + labelPassword.Text = "Пароль:"; + // + // labelWorkExperience + // + labelWorkExperience.AutoSize = true; + labelWorkExperience.Location = new Point(12, 72); + labelWorkExperience.Name = "labelWorkExperience"; + labelWorkExperience.Size = new Size(38, 15); + labelWorkExperience.TabIndex = 7; + labelWorkExperience.Text = "label1"; + // + // labelQualification + // + labelQualification.AutoSize = true; + labelQualification.Location = new Point(11, 101); + labelQualification.Name = "labelQualification"; + labelQualification.Size = new Size(91, 15); + labelQualification.TabIndex = 8; + labelQualification.Text = "Квалификация:"; + // + // buttonSave + // + buttonSave.Location = new Point(216, 134); + buttonSave.Name = "buttonSave"; + buttonSave.Size = new Size(75, 23); + buttonSave.TabIndex = 9; + buttonSave.Text = "Сохранить"; + buttonSave.UseVisualStyleBackColor = true; + buttonSave.Click += buttonSave_Click; + // + // FormImplementer + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(384, 169); + Controls.Add(buttonSave); + Controls.Add(labelQualification); + Controls.Add(labelWorkExperience); + Controls.Add(labelPassword); + Controls.Add(labelImplementerFIO); + Controls.Add(buttonCancel); + Controls.Add(numericUpDownQualification); + Controls.Add(numericUpDownWorkExperience); + Controls.Add(textBoxPassword); + Controls.Add(textBoxImplementerFIO); + Name = "FormImplementer"; + Text = "Исполнитель"; + Load += FormImplementer_Load; + ((System.ComponentModel.ISupportInitialize)numericUpDownWorkExperience).EndInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownQualification).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private TextBox textBoxImplementerFIO; + private TextBox textBoxPassword; + private NumericUpDown numericUpDownWorkExperience; + private NumericUpDown numericUpDownQualification; + private Button buttonCancel; + private Label labelImplementerFIO; + private Label labelPassword; + private Label labelWorkExperience; + private Label labelQualification; + private Button buttonSave; + } +} \ No newline at end of file diff --git a/AircraftPlant/AircraftPlantView/FormImplementer.cs b/AircraftPlant/AircraftPlantView/FormImplementer.cs new file mode 100644 index 0000000..d2641bd --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementer.cs @@ -0,0 +1,140 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.BusinessLogicsContracts; +using AircraftPlantContracts.SearchModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AircraftPlantView +{ + /// + /// Форма для работы с компонентами + /// + public partial class FormImplementer : Form + { + /// + /// Логгер + /// + private readonly ILogger _logger; + + /// + /// Бизнес-логика для исполнителей + /// + private readonly IImplementerLogic _logic; + + /// + /// Идентификатор + /// + private int? _id; + public int Id { set { _id = value; } } + + /// + /// Конструктор + /// + /// + /// + public FormImplementer(ILogger logger, IImplementerLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + + /// + /// Загрузка информации о исполнителе + /// + /// + /// + private void FormImplementer_Load(object sender, EventArgs e) + { + if (_id.HasValue) + { + try + { + _logger.LogInformation("Получение исполнителя"); + var view = _logic.ReadElement(new ImplementerSearchModel + { + Id = _id.Value + }); + if (view != null) + { + textBoxImplementerFIO.Text = view.ImplementerFIO; + textBoxPassword.Text = view.Password; + numericUpDownQualification.Value = view.Qualification; + numericUpDownWorkExperience.Value = view.WorkExperience; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + /// + /// Кнопка "Сохранить" + /// + /// + /// + private void buttonSave_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(textBoxPassword.Text)) + { + MessageBox.Show("Заполните пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (string.IsNullOrEmpty(textBoxImplementerFIO.Text)) + { + MessageBox.Show("Заполните ФИО", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + _logger.LogInformation("Сохранение исполнителя"); + try + { + var model = new ImplementerBindingModel + { + Id = _id ?? 0, + ImplementerFIO = textBoxImplementerFIO.Text, + Password = textBoxPassword.Text, + Qualification = (int)numericUpDownQualification.Value, + WorkExperience = (int)numericUpDownWorkExperience.Value, + }; + + var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + + MessageBox.Show("Сохранение прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + DialogResult = DialogResult.OK; + Close(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка сохранения исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// Кнопка "Отмена" + /// + /// + /// + private void buttonCancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/AircraftPlant/AircraftPlantView/FormImplementer.resx b/AircraftPlant/AircraftPlantView/FormImplementer.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/AircraftPlant/AircraftPlantView/FormImplementers.Designer.cs b/AircraftPlant/AircraftPlantView/FormImplementers.Designer.cs new file mode 100644 index 0000000..b0292b7 --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementers.Designer.cs @@ -0,0 +1,122 @@ +namespace AircraftPlantView +{ + partial class FormImplementers + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + buttonRefresh = new Button(); + buttonDelete = new Button(); + buttonUpdate = new Button(); + buttonAdd = new Button(); + dataGridView = new DataGridView(); + ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + SuspendLayout(); + // + // buttonRefresh + // + buttonRefresh.Location = new Point(480, 102); + buttonRefresh.Name = "buttonRefresh"; + buttonRefresh.Size = new Size(75, 23); + buttonRefresh.TabIndex = 9; + buttonRefresh.Text = "Обновить"; + buttonRefresh.UseVisualStyleBackColor = true; + buttonRefresh.Click += buttonRefresh_Click; + // + // buttonDelete + // + buttonDelete.Location = new Point(480, 73); + buttonDelete.Name = "buttonDelete"; + buttonDelete.Size = new Size(75, 23); + buttonDelete.TabIndex = 8; + buttonDelete.Text = "Удалить"; + buttonDelete.UseVisualStyleBackColor = true; + buttonDelete.Click += buttonDelete_Click; + // + // buttonUpdate + // + buttonUpdate.Location = new Point(480, 44); + buttonUpdate.Name = "buttonUpdate"; + buttonUpdate.Size = new Size(75, 23); + buttonUpdate.TabIndex = 7; + buttonUpdate.Text = "Изменить"; + buttonUpdate.UseVisualStyleBackColor = true; + buttonUpdate.Click += buttonUpdate_Click; + // + // buttonAdd + // + buttonAdd.Location = new Point(480, 15); + buttonAdd.Name = "buttonAdd"; + buttonAdd.Size = new Size(75, 23); + buttonAdd.TabIndex = 6; + buttonAdd.Text = "Добавить"; + buttonAdd.UseVisualStyleBackColor = true; + buttonAdd.Click += buttonAdd_Click; + // + // dataGridView + // + dataGridView.AllowUserToAddRows = false; + dataGridView.AllowUserToDeleteRows = false; + dataGridView.BackgroundColor = Color.White; + dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView.Dock = DockStyle.Left; + dataGridView.GridColor = Color.White; + dataGridView.Location = new Point(0, 0); + dataGridView.MultiSelect = false; + dataGridView.Name = "dataGridView"; + dataGridView.ReadOnly = true; + dataGridView.RowHeadersVisible = false; + dataGridView.RowTemplate.Height = 25; + dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; + dataGridView.Size = new Size(450, 361); + dataGridView.TabIndex = 5; + // + // FormImplementers + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(584, 361); + Controls.Add(buttonRefresh); + Controls.Add(buttonDelete); + Controls.Add(buttonUpdate); + Controls.Add(buttonAdd); + Controls.Add(dataGridView); + Name = "FormImplementers"; + Text = "Исполнители"; + Load += FormImplementers_Load; + ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + ResumeLayout(false); + } + + #endregion + + private Button buttonRefresh; + private Button buttonDelete; + private Button buttonUpdate; + private Button buttonAdd; + private DataGridView dataGridView; + } +} \ No newline at end of file diff --git a/AircraftPlant/AircraftPlantView/FormImplementers.cs b/AircraftPlant/AircraftPlantView/FormImplementers.cs new file mode 100644 index 0000000..0d725d5 --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementers.cs @@ -0,0 +1,154 @@ +using AircraftPlantContracts.BindingModels; +using AircraftPlantContracts.BusinessLogicsContracts; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AircraftPlantView +{ + /// + /// Форма для вывода всех исполнителей + /// + public partial class FormImplementers : Form + { + /// + /// Логгер + /// + private readonly ILogger _logger; + + /// + /// Бизнес-логика для исполнителей + /// + private readonly IImplementerLogic _logic; + + /// + /// Конструктор + /// + /// + /// + public FormImplementers(ILogger logger, IImplementerLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + + /// + /// Загрузка списка исполнителей + /// + /// + /// + private void FormImplementers_Load(object sender, EventArgs e) + { + LoadData(); + } + + /// + /// Кнопка "Добавить" + /// + /// + /// + private void buttonAdd_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormImplementer)); + if (service is FormImplementer form) + { + if (form.ShowDialog() == DialogResult.OK) + { + LoadData(); + } + } + } + + /// + /// Кнопка "Изменить" + /// + /// + /// + private void buttonUpdate_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + var service = Program.ServiceProvider?.GetService(typeof(FormImplementer)); + if (service is FormImplementer form) + { + form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + if (form.ShowDialog() == DialogResult.OK) + { + LoadData(); + } + } + } + } + + /// + /// Кнопка "Удалить" + /// + /// + /// + private void buttonDelete_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Удаление исполнителя"); + try + { + if (!_logic.Delete(new ImplementerBindingModel { Id = id })) + { + throw new Exception("Ошибка при удалении. Дополнительная информация в логах."); + } + LoadData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка удаления исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } + + /// + /// Кнопка "Обновить" + /// + /// + /// + private void buttonRefresh_Click(object sender, EventArgs e) + { + LoadData(); + } + + /// + /// Метод загрузки списка исполнителей + /// + private void LoadData() + { + try + { + var list = _logic.ReadList(null); + if (list != null) + { + dataGridView.DataSource = list; + dataGridView.Columns["Id"].Visible = false; + dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + _logger.LogInformation("Загрузка списка исполнителей"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки списка исполнителей"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/AircraftPlant/AircraftPlantView/FormImplementers.resx b/AircraftPlant/AircraftPlantView/FormImplementers.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/AircraftPlant/AircraftPlantView/FormImplementers.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/AircraftPlant/AircraftPlantView/FormMain.Designer.cs b/AircraftPlant/AircraftPlantView/FormMain.Designer.cs index 264fa65..b9f2be7 100644 --- a/AircraftPlant/AircraftPlantView/FormMain.Designer.cs +++ b/AircraftPlant/AircraftPlantView/FormMain.Designer.cs @@ -30,8 +30,6 @@ { dataGridView = new DataGridView(); buttonCreateOrder = new Button(); - buttonTakeOrderInWork = new Button(); - buttonOrderReady = new Button(); buttonIssuedOrder = new Button(); buttonRefresh = new Button(); menuStrip = new MenuStrip(); @@ -39,6 +37,7 @@ компонентыToolStripMenuItem = new ToolStripMenuItem(); изделияToolStripMenuItem = new ToolStripMenuItem(); магазиныToolStripMenuItem = new ToolStripMenuItem(); + клиентыToolStripMenuItem = new ToolStripMenuItem(); отчетыToolStripMenuItem = new ToolStripMenuItem(); изделияToolStripMenuItem1 = new ToolStripMenuItem(); изделияСКомпонентамиToolStripMenuItem = new ToolStripMenuItem(); @@ -49,6 +48,8 @@ списокМагазиновToolStripMenuItem = new ToolStripMenuItem(); ассортиментМагазиновToolStripMenuItem = new ToolStripMenuItem(); клиентыToolStripMenuItem = new ToolStripMenuItem(); + запускРаботToolStripMenuItem = new ToolStripMenuItem(); + исполнителиToolStripMenuItem = new ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); menuStrip.SuspendLayout(); SuspendLayout(); @@ -81,29 +82,9 @@ buttonCreateOrder.UseVisualStyleBackColor = true; buttonCreateOrder.Click += buttonCreateOrder_Click; // - // buttonTakeOrderInWork - // - buttonTakeOrderInWork.Location = new Point(822, 76); - buttonTakeOrderInWork.Name = "buttonTakeOrderInWork"; - buttonTakeOrderInWork.Size = new Size(150, 23); - buttonTakeOrderInWork.TabIndex = 2; - buttonTakeOrderInWork.Text = "Отдать на выполнение"; - buttonTakeOrderInWork.UseVisualStyleBackColor = true; - buttonTakeOrderInWork.Click += buttonTakeOrderInWork_Click; - // - // buttonOrderReady - // - buttonOrderReady.Location = new Point(822, 105); - buttonOrderReady.Name = "buttonOrderReady"; - buttonOrderReady.Size = new Size(150, 23); - buttonOrderReady.TabIndex = 3; - buttonOrderReady.Text = "Заказ готов"; - buttonOrderReady.UseVisualStyleBackColor = true; - buttonOrderReady.Click += buttonOrderReady_Click; - // // buttonIssuedOrder // - buttonIssuedOrder.Location = new Point(822, 134); + buttonIssuedOrder.Location = new Point(822, 65); buttonIssuedOrder.Name = "buttonIssuedOrder"; buttonIssuedOrder.Size = new Size(150, 23); buttonIssuedOrder.TabIndex = 4; @@ -113,7 +94,7 @@ // // buttonRefresh // - buttonRefresh.Location = new Point(822, 172); + buttonRefresh.Location = new Point(822, 94); buttonRefresh.Name = "buttonRefresh"; buttonRefresh.Size = new Size(150, 23); buttonRefresh.TabIndex = 5; @@ -123,7 +104,7 @@ // // menuStrip // - menuStrip.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчетыToolStripMenuItem }); + menuStrip.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчетыToolStripMenuItem, запускРаботToolStripMenuItem }); menuStrip.Location = new Point(0, 0); menuStrip.Name = "menuStrip"; menuStrip.Size = new Size(984, 24); @@ -134,6 +115,7 @@ // справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, изделияToolStripMenuItem, магазиныToolStripMenuItem }); справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, изделияToolStripMenuItem, клиентыToolStripMenuItem }); + справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, изделияToolStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem }); справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem"; справочникиToolStripMenuItem.Size = new Size(94, 20); справочникиToolStripMenuItem.Text = "Справочники"; @@ -159,6 +141,13 @@ магазиныToolStripMenuItem.Text = "Магазины"; магазиныToolStripMenuItem.Click += магазиныToolStripMenuItem_Click; // + // клиентыToolStripMenuItem + // + клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem"; + клиентыToolStripMenuItem.Size = new Size(180, 22); + клиентыToolStripMenuItem.Text = "Клиенты"; + клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click; + // // отчетыToolStripMenuItem // отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { изделияToolStripMenuItem1, изделияСКомпонентамиToolStripMenuItem, списокЗаказовToolStripMenuItem, заказыСГруппировкойToolStripMenuItem, списокМагазиновToolStripMenuItem, ассортиментМагазиновToolStripMenuItem }); @@ -229,11 +218,19 @@ ассортиментМагазиновToolStripMenuItem.Click += ассортиментМагазиновToolStripMenuItem_Click; // // клиентыToolStripMenuItem + // запускРаботToolStripMenuItem // - клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem"; - клиентыToolStripMenuItem.Size = new Size(180, 22); - клиентыToolStripMenuItem.Text = "Клиенты"; - клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click; + запускРаботToolStripMenuItem.Name = "запускРаботToolStripMenuItem"; + запускРаботToolStripMenuItem.Size = new Size(92, 20); + запускРаботToolStripMenuItem.Text = "Запуск работ"; + запускРаботToolStripMenuItem.Click += запускРаботToolStripMenuItem_Click; + // + // исполнителиToolStripMenuItem + // + исполнителиToolStripMenuItem.Name = "исполнителиToolStripMenuItem"; + исполнителиToolStripMenuItem.Size = new Size(180, 22); + исполнителиToolStripMenuItem.Text = "Исполнители"; + исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click; // // FormMain // @@ -244,8 +241,6 @@ Controls.Add(buttonAddPlaneInShop); Controls.Add(buttonRefresh); Controls.Add(buttonIssuedOrder); - Controls.Add(buttonOrderReady); - Controls.Add(buttonTakeOrderInWork); Controls.Add(buttonCreateOrder); Controls.Add(dataGridView); Controls.Add(menuStrip); @@ -264,8 +259,6 @@ private DataGridView dataGridView; private Button buttonCreateOrder; - private Button buttonTakeOrderInWork; - private Button buttonOrderReady; private Button buttonIssuedOrder; private Button buttonRefresh; private MenuStrip menuStrip; @@ -283,5 +276,7 @@ private ToolStripMenuItem списокМагазиновToolStripMenuItem; private ToolStripMenuItem ассортиментМагазиновToolStripMenuItem; private ToolStripMenuItem клиентыToolStripMenuItem; + private ToolStripMenuItem запускРаботToolStripMenuItem; + private ToolStripMenuItem исполнителиToolStripMenuItem; } } \ No newline at end of file diff --git a/AircraftPlant/AircraftPlantView/FormMain.cs b/AircraftPlant/AircraftPlantView/FormMain.cs index 06be354..7d074e9 100644 --- a/AircraftPlant/AircraftPlantView/FormMain.cs +++ b/AircraftPlant/AircraftPlantView/FormMain.cs @@ -34,17 +34,23 @@ namespace AircraftPlantView /// private readonly IReportLogic _reportLogic; + /// + /// Имитация деятельности исполнителей + /// + private readonly IWorkProcess _workProcess; + /// /// Конструктор /// /// /// - public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic) + public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess) { InitializeComponent(); _logger = logger; _orderLogic = orderLogic; _reportLogic = reportLogic; + _workProcess = workProcess; } /// @@ -113,6 +119,20 @@ namespace AircraftPlantView } } + /// + /// Вывести список всех исполнителей + /// + /// + /// + private void исполнителиToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormImplementers)); + if (service is FormImplementers form) + { + form.ShowDialog(); + } + } + /// /// Вывести отчет по изделиям /// @@ -199,6 +219,19 @@ namespace AircraftPlantView } } + /// + /// Кнопка "Создать заказ" + /// + /// + /// + private void запускРаботToolStripMenuItem_Click(object sender, EventArgs e) + { + _workProcess.DoWork(( + Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, + _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + /// /// Кнопка "Создать заказ" /// @@ -214,62 +247,6 @@ namespace AircraftPlantView } } - /// - /// Кнопка "Отдать на выполнение" - /// - /// - /// - private void buttonTakeOrderInWork_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Заказ №{id}. Меняется статус на 'В работе'", id); - try - { - var operationResult = _orderLogic.TakeOrderInWork(new OrderBindingModel { Id = id }); - if (!operationResult) - { - throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); - } - LoadData(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка передачи заказа в работу"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } - - /// - /// Кнопка "Заказ готов" - /// - /// - /// - private void buttonOrderReady_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Заказ №{id}. Меняется статус на 'Готов'", id); - try - { - var operationResult = _orderLogic.DeliveryOrder(new OrderBindingModel { Id = id }); - if (!operationResult) - { - throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); - } - LoadData(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка отметки о готовности заказа"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } - /// /// Кнопка "Заказ выдан" /// @@ -349,9 +326,9 @@ namespace AircraftPlantView if (list != null) { dataGridView.DataSource = list; - dataGridView.Columns["PlaneName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dataGridView.Columns["PlaneId"].Visible = false; dataGridView.Columns["ClientId"].Visible = false; + dataGridView.Columns["ImplementerId"].Visible = false; } _logger.LogInformation("Загрузка заказов"); } diff --git a/AircraftPlant/AircraftPlantView/Program.cs b/AircraftPlant/AircraftPlantView/Program.cs index 0588465..24d66fe 100644 --- a/AircraftPlant/AircraftPlantView/Program.cs +++ b/AircraftPlant/AircraftPlantView/Program.cs @@ -49,17 +49,20 @@ namespace AircraftPlantView }); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -67,6 +70,8 @@ namespace AircraftPlantView services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/AircraftPlant/AircraftPlantView/nlog.config b/AircraftPlant/AircraftPlantView/nlog.config index cfe664d..bf280eb 100644 --- a/AircraftPlant/AircraftPlantView/nlog.config +++ b/AircraftPlant/AircraftPlantView/nlog.config @@ -5,7 +5,7 @@ autoReload="true" internalLogLevel="Info"> - +