From 5d938d2832beb82b6e93e54f2807da937edcd4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=91=D0=B0=D0=BA=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D1=81=D0=BA=D0=B0=D1=8F?= Date: Sun, 21 Apr 2024 00:48:13 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D1=87=D1=82=D0=B8=20=D0=B3=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=D0=BE,=20=D0=BE=D1=81=D1=82=D0=B0=D0=BB?= =?UTF-8?q?=D0=BE=D1=81=D1=8C=20=D0=BF=D0=BE=D0=BD=D1=8F=D1=82=D1=8C,=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=87=D0=B5=D0=BC=D1=83=20=D0=BD=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=83=D1=87=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D1=82=D1=8C=20=D0=B7=D0=B0=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=20=D0=B1=D0=B5=D0=B7=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SushiBar/FormMain.Designer.cs | 1 + SushiBar/FormMain.cs | 12 +- SushiBar/Program.cs | 1 + SushiBarBusinessLogic/WorkModeling.cs | 147 ++++++++++++++++++ .../BindingModel/OrderBindingModel.cs | 2 +- .../BusinessLogicsContracts/IWorkProcess.cs | 16 ++ .../ViewModels/OrderViewModel.cs | 2 +- SushiBarDatabaseImplement/Models/Order.cs | 1 - .../Controllers/ImplementerController.cs | 105 +++++++++++++ 9 files changed, 283 insertions(+), 4 deletions(-) create mode 100644 SushiBarBusinessLogic/WorkModeling.cs create mode 100644 SushiBarContracts/BusinessLogicsContracts/IWorkProcess.cs create mode 100644 SushiBarRestApi/Controllers/ImplementerController.cs diff --git a/SushiBar/FormMain.Designer.cs b/SushiBar/FormMain.Designer.cs index 1281eb5..dbe41de 100644 --- a/SushiBar/FormMain.Designer.cs +++ b/SushiBar/FormMain.Designer.cs @@ -125,6 +125,7 @@ запускРаботToolStripMenuItem.Name = "запускРаботToolStripMenuItem"; запускРаботToolStripMenuItem.Size = new Size(114, 24); запускРаботToolStripMenuItem.Text = "Запуск работ"; + запускРаботToolStripMenuItem.Click += запускРаботToolStripMenuItem_Click; // // dataGridView // diff --git a/SushiBar/FormMain.cs b/SushiBar/FormMain.cs index e60a512..a6d4fcb 100644 --- a/SushiBar/FormMain.cs +++ b/SushiBar/FormMain.cs @@ -11,12 +11,14 @@ namespace SushiBarView private readonly ILogger _logger; private readonly IOrderLogic _orderLogic; private readonly IReportLogic _reportLogic; - public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic) + private readonly IWorkProcess _workProcess; + public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess) { InitializeComponent(); _logger = logger; _orderLogic = orderLogic; _reportLogic = reportLogic; + _workProcess = workProcess; } private void FormMain_Load(object sender, EventArgs e) { @@ -195,5 +197,13 @@ namespace SushiBarView form.ShowDialog(); } } + + private void запускРаботToolStripMenuItem_Click(object sender, EventArgs e) + { + _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, + _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } } } diff --git a/SushiBar/Program.cs b/SushiBar/Program.cs index a759ab1..f5e29b8 100644 --- a/SushiBar/Program.cs +++ b/SushiBar/Program.cs @@ -56,6 +56,7 @@ namespace SushiBar services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/SushiBarBusinessLogic/WorkModeling.cs b/SushiBarBusinessLogic/WorkModeling.cs new file mode 100644 index 0000000..0d85644 --- /dev/null +++ b/SushiBarBusinessLogic/WorkModeling.cs @@ -0,0 +1,147 @@ +using Microsoft.Extensions.Logging; +using SushiBarContracts.BindingModel; +using SushiBarContracts.BusinessLogicsContracts; +using SushiBarContracts.SearchModel; +using SushiBarContracts.ViewModels; +using SushiBarDataModels.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarBusinessLogic +{ + 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; + } + } + } +} diff --git a/SushiBarContracts/BindingModel/OrderBindingModel.cs b/SushiBarContracts/BindingModel/OrderBindingModel.cs index d2cfe56..1e01064 100644 --- a/SushiBarContracts/BindingModel/OrderBindingModel.cs +++ b/SushiBarContracts/BindingModel/OrderBindingModel.cs @@ -15,7 +15,7 @@ namespace SushiBarContracts.BindingModel public int ClientId { get; set; } public int? ImplementerId { get; set; } public string ClientFIO { get; set; } = string.Empty; - public string ImplementerFIO { get; set; } = string.Empty; + public string? ImplementerFIO { get; set; } = string.Empty; public int Count { get; set; } public double Sum { get; set; } public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; diff --git a/SushiBarContracts/BusinessLogicsContracts/IWorkProcess.cs b/SushiBarContracts/BusinessLogicsContracts/IWorkProcess.cs new file mode 100644 index 0000000..59a6a8c --- /dev/null +++ b/SushiBarContracts/BusinessLogicsContracts/IWorkProcess.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SushiBarContracts.BusinessLogicsContracts +{ + public interface IWorkProcess + { + /// + /// Запуск работ + /// + void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic); + } +} diff --git a/SushiBarContracts/ViewModels/OrderViewModel.cs b/SushiBarContracts/ViewModels/OrderViewModel.cs index c0b5b51..d23efb2 100644 --- a/SushiBarContracts/ViewModels/OrderViewModel.cs +++ b/SushiBarContracts/ViewModels/OrderViewModel.cs @@ -18,7 +18,7 @@ namespace SushiBarContracts.ViewModels public string ClientFIO { get; set; } = string.Empty; [DisplayName("Имя исполнителя")] - public string ImplementerFIO { get; set; } = string.Empty; + public string? ImplementerFIO { get; set; } = string.Empty; [DisplayName("Суши")] public string SushiName { get; set; } = string.Empty; diff --git a/SushiBarDatabaseImplement/Models/Order.cs b/SushiBarDatabaseImplement/Models/Order.cs index e43d13c..b5cc7ba 100644 --- a/SushiBarDatabaseImplement/Models/Order.cs +++ b/SushiBarDatabaseImplement/Models/Order.cs @@ -16,7 +16,6 @@ namespace SushiBarDatabaseImplement.Models [Required] public int ClientId { get; set; } - [Required] public int? ImplementerId { get; set; } [Required] diff --git a/SushiBarRestApi/Controllers/ImplementerController.cs b/SushiBarRestApi/Controllers/ImplementerController.cs new file mode 100644 index 0000000..6ff09c4 --- /dev/null +++ b/SushiBarRestApi/Controllers/ImplementerController.cs @@ -0,0 +1,105 @@ +using DocumentFormat.OpenXml.Office2010.Excel; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using SushiBarContracts.BindingModel; +using SushiBarContracts.BusinessLogicsContracts; +using SushiBarContracts.SearchModel; +using SushiBarContracts.ViewModels; +using SushiBarDataModels.Enums; + +namespace SushiBarRestApi.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; + } + } + } +}