diff --git a/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/ImplementerLogic.cs b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/ImplementerLogic.cs new file mode 100644 index 0000000..7d8423a --- /dev/null +++ b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/ImplementerLogic.cs @@ -0,0 +1,35 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.BusinessLogicsContracts; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopBusinessLogic.BusinessLogics +{ + public class ImplementerLogic : IImplementerLogic + { + public bool Create(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public bool Delete(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? ReadElement(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List? ReadList(ImplementerSearchModel? model) + { + throw new NotImplementedException(); + } + + public bool Update(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/OrderLogic.cs b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/OrderLogic.cs index 50ee1b9..f0acecb 100644 --- a/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/OrderLogic.cs @@ -22,6 +22,11 @@ namespace AbstractShopBusinessLogic.BusinessLogics throw new NotImplementedException(); } + public OrderViewModel? ReadElement(OrderSearchModel model) + { + throw new NotImplementedException(); + } + public List? ReadList(OrderSearchModel? model) { throw new NotImplementedException(); diff --git a/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/WorkModeling.cs b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/WorkModeling.cs new file mode 100644 index 0000000..c49a26e --- /dev/null +++ b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/WorkModeling.cs @@ -0,0 +1,143 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.BusinessLogicsContracts; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.ViewModels; +using Microsoft.Extensions.Logging; + +namespace AbstractShopBusinessLogic.BusinessLogics +{ + public class WorkModeling : IWorkProcess + { + private readonly ILogger _logger; + + private readonly Random _rnd; + + 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.Принят*/ }); + if (orders == null || orders.Count == 0) + { + _logger.LogWarning("DoWork. Orders is null or empty"); + return; + } + _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 RunOrderInWork(implementer); + + await Task.Run(() => + { + foreach (var order in orders) + { + try + { + _logger.LogDebug("DoWork. Worker {Id} try get order {Order}", implementer.Id, order.Id); + // пытаемся назначить заказ на исполнителя + _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.FinishOrder(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.FinishOrder(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; + } + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BindingModels/ImplementerBindingModel.cs b/AbstractShop/AbstractShopContracts/BindingModels/ImplementerBindingModel.cs new file mode 100644 index 0000000..814d69c --- /dev/null +++ b/AbstractShop/AbstractShopContracts/BindingModels/ImplementerBindingModel.cs @@ -0,0 +1,20 @@ +using AbstractShopDataModels.Models; + +namespace AbstractShopContracts.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; } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IImplementerLogic.cs b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IImplementerLogic.cs new file mode 100644 index 0000000..b6f1c38 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IImplementerLogic.cs @@ -0,0 +1,19 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopContracts.BusinessLogicsContracts +{ + public interface IImplementerLogic + { + List? ReadList(ImplementerSearchModel? model); + + ImplementerViewModel? ReadElement(ImplementerSearchModel model); + + bool Create(ImplementerBindingModel model); + + bool Update(ImplementerBindingModel model); + + bool Delete(ImplementerBindingModel model); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IOrderLogic.cs b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IOrderLogic.cs index e3e706a..6710a9d 100644 --- a/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IOrderLogic.cs +++ b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IOrderLogic.cs @@ -8,6 +8,8 @@ namespace AbstractShopContracts.BusinessLogicsContracts { List? ReadList(OrderSearchModel? model); + OrderViewModel? ReadElement(OrderSearchModel model); + bool CreateOrder(OrderBindingModel model); bool TakeOrderInWork(OrderBindingModel model); diff --git a/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IWorkProcess.cs b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IWorkProcess.cs new file mode 100644 index 0000000..0d51127 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IWorkProcess.cs @@ -0,0 +1,10 @@ +namespace AbstractShopContracts.BusinessLogicsContracts +{ + public interface IWorkProcess + { + /// + /// Запуск работ + /// + void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/SearchModels/ImplementerSearchModel.cs b/AbstractShop/AbstractShopContracts/SearchModels/ImplementerSearchModel.cs new file mode 100644 index 0000000..791be4a --- /dev/null +++ b/AbstractShop/AbstractShopContracts/SearchModels/ImplementerSearchModel.cs @@ -0,0 +1,11 @@ +namespace AbstractShopContracts.SearchModels +{ + public class ImplementerSearchModel + { + public int? Id { get; set; } + + public string? ImplementerFIO { get; set; } + + public string? Password { get; set; } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/StoragesContracts/IImplementerStorage.cs b/AbstractShop/AbstractShopContracts/StoragesContracts/IImplementerStorage.cs new file mode 100644 index 0000000..6479050 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/StoragesContracts/IImplementerStorage.cs @@ -0,0 +1,21 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopContracts.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); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/ViewModels/ImplementerViewModel.cs b/AbstractShop/AbstractShopContracts/ViewModels/ImplementerViewModel.cs new file mode 100644 index 0000000..7268537 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/ViewModels/ImplementerViewModel.cs @@ -0,0 +1,25 @@ +using AbstractShopDataModels.Models; +using System.ComponentModel; + +namespace AbstractShopContracts.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; } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopDataModels/Models/IImplementerModel.cs b/AbstractShop/AbstractShopDataModels/Models/IImplementerModel.cs new file mode 100644 index 0000000..262ec6c --- /dev/null +++ b/AbstractShop/AbstractShopDataModels/Models/IImplementerModel.cs @@ -0,0 +1,13 @@ +namespace AbstractShopDataModels.Models +{ + public interface IImplementerModel : IId + { + string ImplementerFIO { get; } + + string Password { get; } + + int WorkExperience { get; } + + int Qualification { get; } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopDatabaseImplement/Implements/ImplementerStorage.cs b/AbstractShop/AbstractShopDatabaseImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..b69440e --- /dev/null +++ b/AbstractShop/AbstractShopDatabaseImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,40 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.StoragesContracts; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopDatabaseImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFilteredList(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFullList() + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopFileImplement/Implements/ImplementerStorage.cs b/AbstractShop/AbstractShopFileImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..85b430d --- /dev/null +++ b/AbstractShop/AbstractShopFileImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,40 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.StoragesContracts; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopFileImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFilteredList(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFullList() + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopListImplement/Implements/ImplementerStorage.cs b/AbstractShop/AbstractShopListImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..3f99bce --- /dev/null +++ b/AbstractShop/AbstractShopListImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,40 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.StoragesContracts; +using AbstractShopContracts.ViewModels; + +namespace AbstractShopListImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFilteredList(ImplementerSearchModel model) + { + throw new NotImplementedException(); + } + + public List GetFullList() + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopRestApi/Controllers/ImplementerController.cs b/AbstractShop/AbstractShopRestApi/Controllers/ImplementerController.cs new file mode 100644 index 0000000..8f873c9 --- /dev/null +++ b/AbstractShop/AbstractShopRestApi/Controllers/ImplementerController.cs @@ -0,0 +1,106 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.BusinessLogicsContracts; +using AbstractShopContracts.SearchModels; +using AbstractShopContracts.ViewModels; +using Microsoft.AspNetCore.Mvc; + +namespace AbstractShopRestApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class ImplementerController : Controller + { + private readonly ILogger _logger; + + private readonly IOrderLogic _order; + + private readonly IImplementerLogic _logic; + + public ImplementerController(IOrderLogic order, IImplementerLogic logic, ILogger logger) + { + _logger = logger; + _order = order; + _logic = logic; + } + + [HttpGet] + public ImplementerViewModel? Login(string login, string password) + { + try + { + return _logic.ReadElement(new ImplementerSearchModel + { + ImplementerFIO = login, + Password = password + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка авторизации сотрудника"); + throw; + } + } + + [HttpGet] + public List? GetNewOrders() + { + try + { + return _order.ReadList(new OrderSearchModel + { + //Status = OrderStatus.Принят + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения новых заказов"); + throw; + } + } + + [HttpGet] + public OrderViewModel? GetImplementerOrder(int implementerId) + { + try + { + return _order.ReadElement(new OrderSearchModel + { + //ImplementerId = implementerId + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения текущего заказа исполнителя"); + throw; + } + } + + [HttpPost] + public void TakeOrderInWork(OrderBindingModel model) + { + try + { + _order.TakeOrderInWork(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка перевода заказа с №{Id} в работу", model.Id); + throw; + } + } + + [HttpPost] + public void FinishOrder(OrderBindingModel model) + { + try + { + _order.FinishOrder(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отметки о готовности заказа с №{Id}", model.Id); + throw; + } + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopRestApi/Program.cs b/AbstractShop/AbstractShopRestApi/Program.cs index 7677c1f..ab43f08 100644 --- a/AbstractShop/AbstractShopRestApi/Program.cs +++ b/AbstractShop/AbstractShopRestApi/Program.cs @@ -11,10 +11,12 @@ 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(); diff --git a/AbstractShop/AbstractShopView/Program.cs b/AbstractShop/AbstractShopView/Program.cs index eab72e2..8c28ab0 100644 --- a/AbstractShop/AbstractShopView/Program.cs +++ b/AbstractShop/AbstractShopView/Program.cs @@ -36,14 +36,17 @@ namespace AbstractShopView }); 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();