diff --git a/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/OrderLogic.cs b/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/OrderLogic.cs index b64e40f..67940e7 100644 --- a/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/OrderLogic.cs +++ b/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/OrderLogic.cs @@ -85,12 +85,18 @@ namespace AbstractLawFirmBusinessLogic.BusinessLogic _logger.LogWarning("Read operation failed"); return false; } - if (element.Status != status - 1) + if (element.Status != status - 1 && element.Status != OrderStatus.Ожидание) { _logger.LogWarning("Status change operation failed"); throw new InvalidOperationException("Текущий статус заказа не может быть переведен в выбранный"); } - if (status == OrderStatus.Готов) + if (element.ImplementerId.HasValue) + model.ImplementerId = element.ImplementerId; + if (model.DocumentId == 0) + model.DocumentId = element.DocumentId; + if (model.Count == 0) + model.Count = element.Count; + if (status == OrderStatus.Выдан) { var document = _documentStorage.GetElement(new DocumentSearchModel() { Id = model.DocumentId }); if (document == null) @@ -102,7 +108,10 @@ namespace AbstractLawFirmBusinessLogic.BusinessLogic if (!CheckThenSupplyMany(document, model.Count)) { _logger.LogWarning("Status change operation failed. Shop supply error."); - return false; + model.Status = OrderStatus.Ожидание; + if (_orderStorage.Update(model) == null) + _logger.LogWarning("Update operation failed"); + return false; } } diff --git a/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/WorkModeling.cs b/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/WorkModeling.cs index 5fe6bf5..7176202 100644 --- a/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/WorkModeling.cs +++ b/LawFirm/AbstractLawFirmBusinessLogic/BusinessLogic/WorkModeling.cs @@ -14,128 +14,206 @@ namespace AbstractLawFirmBusinessLogic.BusinessLogic { 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); + private readonly ILogger _logger; + private readonly Random _rnd; + private IOrderLogic? _orderLogic; - _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; - } - } - } + 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) + { + _logger.LogWarning("DoWork. Orders is null"); + return; + } + orders.AddRange(_orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Выполняется }) ?? new()); + orders.AddRange(_orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Ожидание }) ?? new()); + if (orders.Count == 0) + { + _logger.LogWarning("DoWork. Orders is 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 RunWaitingOrder(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); + // пытаемся назначить заказ на исполнителя + _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 + }); + // доставляем + _logger.LogDebug("DoWork. Worker {Id} delivery 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.FinishOrder(new OrderBindingModel + { + Id = runOrder.Id + }); + + // доставляем + _logger.LogDebug("DoWork. Worker {Id} delivery 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 RunWaitingOrder(ImplementerViewModel implementer) + { + if (_orderLogic == null || implementer == null) + { + return; + } + try + { + var order = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel + { + ImplementerId = implementer.Id, + Status = OrderStatus.Ожидание + })); + if (order == null) + { + return; + } + + // доставляем + _logger.LogDebug("DoWork. Worker {Id} delivery order {Order}", implementer.Id, order.Id); + _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/LawFirm/AbstractLawFirmDataModels/AbstractLawFirmDataModels/Enums/OrderStatus.cs b/LawFirm/AbstractLawFirmDataModels/AbstractLawFirmDataModels/Enums/OrderStatus.cs index 6837f42..35d8c5a 100644 --- a/LawFirm/AbstractLawFirmDataModels/AbstractLawFirmDataModels/Enums/OrderStatus.cs +++ b/LawFirm/AbstractLawFirmDataModels/AbstractLawFirmDataModels/Enums/OrderStatus.cs @@ -12,6 +12,7 @@ namespace AbstractLawFirmDataModels.Enums Принят = 0, Выполняется = 1, Готов = 2, - Выдан = 3 + Выдан = 3, + Ожидание = 4 } }