From ed627b9c737f3f8aecc90d60853baaada68ed4bc Mon Sep 17 00:00:00 2001 From: malimova Date: Mon, 3 Jun 2024 21:54:03 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BA=D1=80=D0=BE=D0=BC=D0=B5=20=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkModeling.cs | 139 ++++++++++++++++++ .../BusinessLogicsContracts/IOrderLogic.cs | 19 +-- .../BusinessLogicsContracts/IWorkProcess.cs | 16 ++ .../SearchModels/OrderSearchModel.cs | 19 ++- .../Controllers/ImplementerController.cs | 103 +++++++++++++ .../ConfectioneryView/FormMain.Designer.cs | 23 ++- Confectionery/ConfectioneryView/FormMain.cs | 10 +- 7 files changed, 304 insertions(+), 25 deletions(-) create mode 100644 Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs create mode 100644 Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IWorkProcess.cs create mode 100644 Confectionery/ConfectioneryRestApi/Controllers/ImplementerController.cs diff --git a/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs b/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs new file mode 100644 index 0000000..d7e8035 --- /dev/null +++ b/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs @@ -0,0 +1,139 @@ +using ConfectioneryContracts.BindingModels; +using ConfectioneryContracts.BusinessLogicsContracts; +using ConfectioneryContracts.SearchModels; +using ConfectioneryContracts.ViewModels; +using ConfectioneryDataModels.Enums; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConfectioneryBusinessLogic.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/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IOrderLogic.cs b/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IOrderLogic.cs index fc1f506..6382443 100644 --- a/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IOrderLogic.cs +++ b/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IOrderLogic.cs @@ -9,12 +9,13 @@ using System.Threading.Tasks; namespace ConfectioneryContracts.BusinessLogicsContracts { - public interface IOrderLogic - { - List? ReadList(OrderSearchModel? model); - bool CreateOrder(OrderBindingModel model); - bool TakeOrderInWork(OrderBindingModel model); - bool FinishOrder(OrderBindingModel model); - bool DeliveryOrder(OrderBindingModel model); - } -} + public interface IOrderLogic + { + List? ReadList(OrderSearchModel? model); + bool CreateOrder(OrderBindingModel model); + bool TakeOrderInWork(OrderBindingModel model); + bool FinishOrder(OrderBindingModel model); + bool DeliveryOrder(OrderBindingModel model); + OrderViewModel? ReadElement(OrderSearchModel model); + } +} \ No newline at end of file diff --git a/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IWorkProcess.cs b/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IWorkProcess.cs new file mode 100644 index 0000000..416c12f --- /dev/null +++ b/Confectionery/ConfectioneryContracts/BusinessLogicsContracts/IWorkProcess.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConfectioneryContracts.BusinessLogicsContracts +{ + public interface IWorkProcess + { + /// + /// Запуск работ + /// + void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic); + } +} \ No newline at end of file diff --git a/Confectionery/ConfectioneryContracts/SearchModels/OrderSearchModel.cs b/Confectionery/ConfectioneryContracts/SearchModels/OrderSearchModel.cs index d636d99..47c840b 100644 --- a/Confectionery/ConfectioneryContracts/SearchModels/OrderSearchModel.cs +++ b/Confectionery/ConfectioneryContracts/SearchModels/OrderSearchModel.cs @@ -1,4 +1,5 @@ -using System; +using ConfectioneryDataModels.Enums; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +7,13 @@ using System.Threading.Tasks; namespace ConfectioneryContracts.SearchModels { - public class OrderSearchModel - { - public int? Id { get; set; } - public int? ClientId { get; set; } - public DateTime? DateFrom { get; set; } - public DateTime? DateTo { get; set; } - } + public class OrderSearchModel + { + public int? Id { get; set; } + public int? ClientId { get; set; } + public OrderStatus? Status { get; set; } + public int? ImplementerId { get; set; } + public DateTime? DateFrom { get; set; } + public DateTime? DateTo { get; set; } + } } diff --git a/Confectionery/ConfectioneryRestApi/Controllers/ImplementerController.cs b/Confectionery/ConfectioneryRestApi/Controllers/ImplementerController.cs new file mode 100644 index 0000000..665543e --- /dev/null +++ b/Confectionery/ConfectioneryRestApi/Controllers/ImplementerController.cs @@ -0,0 +1,103 @@ +using ConfectioneryContracts.BindingModels; +using ConfectioneryContracts.BusinessLogicsContracts; +using ConfectioneryContracts.SearchModels; +using ConfectioneryContracts.ViewModels; +using ConfectioneryDataModels.Enums; +using DocumentFormat.OpenXml.Office2010.Excel; +using Microsoft.AspNetCore.Mvc; + +namespace ConfectioneryRestApi.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; + } + } + } +} diff --git a/Confectionery/ConfectioneryView/FormMain.Designer.cs b/Confectionery/ConfectioneryView/FormMain.Designer.cs index 744a776..b781ed0 100644 --- a/Confectionery/ConfectioneryView/FormMain.Designer.cs +++ b/Confectionery/ConfectioneryView/FormMain.Designer.cs @@ -33,6 +33,7 @@ toolStripMenuItem = new ToolStripMenuItem(); componentsToolStripMenuItem = new ToolStripMenuItem(); pastryToolStripMenuItem = new ToolStripMenuItem(); + clientsToolStripMenuItem = new ToolStripMenuItem(); отчетыToolStripMenuItem = new ToolStripMenuItem(); pastrysListToolStripMenuItem = new ToolStripMenuItem(); componentPastryToolStripMenuItem = new ToolStripMenuItem(); @@ -42,7 +43,7 @@ buttonOrderReady = new Button(); buttonIssuedOrder = new Button(); buttonRef = new Button(); - clientsToolStripMenuItem = new ToolStripMenuItem(); + startWorkToolStripMenuItem = new ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); menuStrip.SuspendLayout(); SuspendLayout(); @@ -60,7 +61,7 @@ // menuStrip // menuStrip.ImageScalingSize = new Size(24, 24); - menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem, отчетыToolStripMenuItem }); + menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem, отчетыToolStripMenuItem, startWorkToolStripMenuItem }); menuStrip.Location = new Point(0, 0); menuStrip.Name = "menuStrip"; menuStrip.Size = new Size(1666, 33); @@ -88,6 +89,13 @@ pastryToolStripMenuItem.Text = "Кондитерские изделия"; pastryToolStripMenuItem.Click += pastryToolStripMenuItem_Click; // + // clientsToolStripMenuItem + // + clientsToolStripMenuItem.Name = "clientsToolStripMenuItem"; + clientsToolStripMenuItem.Size = new Size(298, 34); + clientsToolStripMenuItem.Text = "Клиенты"; + clientsToolStripMenuItem.Click += clientsToolStripMenuItem_Click; + // // отчетыToolStripMenuItem // отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { pastrysListToolStripMenuItem, componentPastryToolStripMenuItem, ordersListToolStripMenuItem }); @@ -171,12 +179,12 @@ buttonRef.UseVisualStyleBackColor = true; buttonRef.Click += buttonRef_Click; // - // clientsToolStripMenuItem + // startWorkToolStripMenuItem // - clientsToolStripMenuItem.Name = "clientsToolStripMenuItem"; - clientsToolStripMenuItem.Size = new Size(298, 34); - clientsToolStripMenuItem.Text = "Клиенты"; - clientsToolStripMenuItem.Click += clientsToolStripMenuItem_Click; + startWorkToolStripMenuItem.Name = "startWorkToolStripMenuItem"; + startWorkToolStripMenuItem.Size = new Size(136, 29); + startWorkToolStripMenuItem.Text = "Запуск работ"; + startWorkToolStripMenuItem.Click += startWorkToolStripMenuItem_Click; // // FormMain // @@ -218,5 +226,6 @@ private ToolStripMenuItem componentPastryToolStripMenuItem; private ToolStripMenuItem ordersListToolStripMenuItem; private ToolStripMenuItem clientsToolStripMenuItem; + private ToolStripMenuItem startWorkToolStripMenuItem; } } \ No newline at end of file diff --git a/Confectionery/ConfectioneryView/FormMain.cs b/Confectionery/ConfectioneryView/FormMain.cs index fc573b3..f1b3cc3 100644 --- a/Confectionery/ConfectioneryView/FormMain.cs +++ b/Confectionery/ConfectioneryView/FormMain.cs @@ -18,13 +18,15 @@ namespace ConfectioneryView private readonly ILogger _logger; private readonly IOrderLogic _orderLogic; 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; } private void FormMain_Load(object sender, EventArgs e) { @@ -203,5 +205,11 @@ namespace ConfectioneryView form.ShowDialog(); } } + + private void startWorkToolStripMenuItem_Click(object sender, EventArgs e) + { + _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + } } }