From a85fa1714f4252f8db4b4d7b4733be516aac649b Mon Sep 17 00:00:00 2001
From: Oleg Shabunov <olshab190404@gmail.com>
Date: Fri, 21 Jun 2024 18:36:11 +0400
Subject: [PATCH] change WorkModeling and OrderLogic

---
 .../BusinessLogics/OrderLogic.cs              | 109 +++++++++++-------
 .../BusinessLogics/WorkModeling.cs            |  68 ++++++++---
 AutoWorkshopDataModels/Enums/OrderStatus.cs   |   1 +
 ...s => 20240621132359_Lab6_Hard.Designer.cs} |   9 +-
 ...menters.cs => 20240621132359_Lab6_Hard.cs} |   6 +-
 AutoWorkshopView/MainForm.Designer.cs         |   6 +-
 AutoWorkshopView/Program.cs                   |   4 -
 7 files changed, 128 insertions(+), 75 deletions(-)
 rename AutoWorkshopDatabaseImplement/Migrations/{20240416160914_Implementers.Designer.cs => 20240621132359_Lab6_Hard.Designer.cs} (97%)
 rename AutoWorkshopDatabaseImplement/Migrations/{20240416160914_Implementers.cs => 20240621132359_Lab6_Hard.cs} (97%)

diff --git a/AutoWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs b/AutoWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs
index f83bc75..c969685 100644
--- a/AutoWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs
+++ b/AutoWorkshopBusinessLogic/BusinessLogics/OrderLogic.cs
@@ -4,6 +4,7 @@ using AutoWorkshopContracts.SearchModels;
 using AutoWorkshopContracts.StoragesContracts;
 using AutoWorkshopContracts.ViewModels;
 using AutoWorkshopDataModels.Enums;
+using DocumentFormat.OpenXml.EMMA;
 using Microsoft.Extensions.Logging;
 
 namespace AutoWorkshopBusinessLogic.BusinessLogics
@@ -15,6 +16,8 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
         private readonly IOrderStorage _orderStorage;
         private readonly IShopStorage _shopStorage;
 
+        private static readonly object _locker = new object();
+
         public OrderLogic(ILogger<RepairLogic> Logger, IOrderStorage OrderStorage, IShopStorage ShopStorage)
         {
             _logger = Logger;
@@ -60,43 +63,21 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
 
         private bool ChangeOrderStatus(OrderBindingModel Model, OrderStatus NewStatus)
         {
-            CheckModel(Model, false);
-
-            var Order = _orderStorage.GetElement(new OrderSearchModel { Id = Model.Id });
+            Model = FillOrderBindingModel(Model);
             
-            if (Order == null)
-            {
-                _logger.LogWarning("Change status operation failed. Order not found");
-                return false;
-            }
-            
-            if (Order.Status + 1 != NewStatus)
+            if (Model.Status + 1 != NewStatus)
             {
                 _logger.LogWarning("Change status operation failed. Incorrect new status: {NewStatus}. Current status: {currStatus}",
-                    NewStatus, Order.Status);
+                    NewStatus, Model.Status);
                 return false;
             }
-            
-            Model.RepairId = Order.RepairId;
-            Model.ClientId = Order.ClientId;
-            if (!Model.ImplementerId.HasValue) Model.ImplementerId = Order.ImplementerId;
-            Model.Count = Order.Count;
-            Model.Sum = Order.Sum;
-            Model.DateCreate = Order.DateCreate;
+
             Model.Status = NewStatus;
             
             if (Model.Status == OrderStatus.Ready)
                 Model.DateImplement = DateTime.Now;
-            else
-                Model.DateImplement = Order.DateImplement;
-            
-            if (_orderStorage.Update(Model) == null)
-            {
-                _logger.LogWarning("Change status operation failed");
-                return false;
-            }
 
-            return true;
+            return UpdateOrder(Model);
         }
 
         public bool TakeOrderInWork(OrderBindingModel Model)
@@ -114,24 +95,29 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
 
         public bool DeliveryOrder(OrderBindingModel Model)
         {
-            var Order = _orderStorage.GetElement(new OrderSearchModel
-            {
-                Id = Model.Id
-            });
+			lock ( _locker)
+			{
+				Model = FillOrderBindingModel(Model);
 
-            if (Order is null)
-                throw new ArgumentNullException(nameof(Order));
+				if (Model.Status != OrderStatus.Ready && Model.Status != OrderStatus.Waiting)
+				{
+					_logger.LogWarning("Changing status operation failed");
+					throw new InvalidOperationException($"Невозможно присвоить статус Delivered заказу с текущим статусом {Model.Status}");
+				}
 
-            if (!_shopStorage.RestockingShops(new SupplyBindingModel
-            {
-                RepairId = Order.RepairId,
-                Count = Order.Count
-            }))
-            {
-                throw new ArgumentException("Недостаточно места");
-            }
+				if (!_shopStorage.RestockingShops(new SupplyBindingModel
+				{
+					RepairId = Model.RepairId,
+					Count = Model.Count
+				}))
+				{
+					Model.Status = OrderStatus.Waiting;
+					return UpdateOrder(Model);
+				}
 
-            return ChangeOrderStatus(Model, OrderStatus.Delivered);
+				Model.Status = OrderStatus.Delivered;
+				return UpdateOrder(Model);
+			}
         }
 
         private void CheckModel(OrderBindingModel Model, bool WithParams = true)
@@ -175,5 +161,42 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
             _logger.LogInformation("ReadElement find. Id: {Id}", Order.Id);
             return Order;
         }
-    }
+
+		private OrderBindingModel FillOrderBindingModel(OrderBindingModel Model)
+		{
+			CheckModel(Model, false);
+			var OrderViewModel = _orderStorage.GetElement(new OrderSearchModel()
+			{
+				Id = Model.Id
+			});
+			if (OrderViewModel == null)
+			{
+				throw new InvalidOperationException(nameof(OrderViewModel));
+			}
+			Model.Id = OrderViewModel.Id;
+			Model.DateCreate = OrderViewModel.DateCreate;
+			Model.RepairId = OrderViewModel.RepairId;
+			Model.DateImplement = OrderViewModel.DateImplement;
+			Model.ClientId = OrderViewModel.ClientId;
+			Model.Status = OrderViewModel.Status;
+			Model.Count = OrderViewModel.Count;
+			Model.Sum = OrderViewModel.Sum;
+			if (!Model.ImplementerId.HasValue)
+			{
+				Model.ImplementerId = OrderViewModel.ImplementerId;
+			}
+			return Model;
+		}
+
+		private bool UpdateOrder(OrderBindingModel Model)
+		{
+			if (_orderStorage.Update(Model) == null)
+			{
+				_logger.LogWarning("Update operation failed");
+				return false;
+			}
+			_logger.LogWarning("Update operation sucsess");
+			return true;
+		}
+	}
 }
diff --git a/AutoWorkshopBusinessLogic/BusinessLogics/WorkModeling.cs b/AutoWorkshopBusinessLogic/BusinessLogics/WorkModeling.cs
index 3402718..da75dd4 100644
--- a/AutoWorkshopBusinessLogic/BusinessLogics/WorkModeling.cs
+++ b/AutoWorkshopBusinessLogic/BusinessLogics/WorkModeling.cs
@@ -36,13 +36,18 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
             
             var Orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Accepted });
             var BeingProcessedOrders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.BeingProcessed });
-                // in case there are BeingProcessed orders but no Accepted orders
+			var WaitingOrders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Waiting });
 
-            if (Orders == null || BeingProcessedOrders == null || (Orders.Count == 0 && BeingProcessedOrders.Count == 0))
+			if (Orders == null || BeingProcessedOrders == null || WaitingOrders == null)
             {
-                _logger.LogWarning("DoWork. Orders is null or empty");
+                _logger.LogWarning("DoWork. Orders are null");
                 return;
             }
+            if (Orders.Count == 0 && BeingProcessedOrders.Count == 0 && WaitingOrders.Count == 0)
+            {
+				_logger.LogWarning("DoWork. No orders to process");
+				return;
+			}
             
             _logger.LogDebug("DoWork for {Count} orders", Orders.Count);
 
@@ -58,8 +63,9 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
             {
                 return;
             }
-            
-            await RunOrderInWork(Implementer);
+
+			await RunWaitingOrders(Implementer);
+			await RunOrderInWork(Implementer);
 
             await Task.Run(() =>
             {
@@ -86,10 +92,8 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
                         Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 1000) * Order.Count);
                         
                         _logger.LogDebug("WorkerWorkAsync. Worker {Id} finish order {Order}", Implementer.Id, Order.Id);
-                        _orderLogic.FinishOrder(new OrderBindingModel
-                        {
-                            Id = Order.Id
-                        });
+                        _orderLogic.FinishOrder(new OrderBindingModel { Id = Order.Id });
+                        _orderLogic.DeliveryOrder(new OrderBindingModel { Id = Order.Id });
                     }
   
                     catch (InvalidOperationException ex)
@@ -130,10 +134,8 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
                 Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 300) * RunOrder.Count);
                 
                 _logger.LogDebug("RunOrderInWork. Worker {Id} finish order {Order}", Implementer.Id, RunOrder.Id);
-                _orderLogic.FinishOrder(new OrderBindingModel
-                {
-                    Id = RunOrder.Id
-                });
+                _orderLogic.FinishOrder(new OrderBindingModel { Id = RunOrder.Id });
+                _orderLogic.DeliveryOrder(new OrderBindingModel { Id = RunOrder.Id });
 
                 Thread.Sleep(Implementer.Qualification * _rnd.Next(10, 100));
             }
@@ -149,5 +151,43 @@ namespace AutoWorkshopBusinessLogic.BusinessLogics
                 throw;
             }
         }
-    }
+
+		private async Task RunWaitingOrders(ImplementerViewModel Implementer)
+		{
+			if (_orderLogic == null || Implementer == null)
+				return;
+
+			var WaitingOrders = await Task.Run(() => _orderLogic.ReadList(new OrderSearchModel
+			{
+				ImplementerId = Implementer.Id,
+				Status = OrderStatus.Waiting
+			}));
+			if (WaitingOrders == null || WaitingOrders.Count == 0)
+			{
+				return;
+			}
+			
+            _logger.LogDebug("RunWaitingOrders for {Count} orders. Implementer: {id}.", WaitingOrders.Count, Implementer.Id);
+			foreach (var WaitingOrder in WaitingOrders)
+			{
+				try
+				{
+					_logger.LogInformation("RunWaitingOrders. Order {Order} delivery", WaitingOrder.Id);
+					_orderLogic.DeliveryOrder(new OrderBindingModel
+					{
+						Id = WaitingOrder.Id
+					});
+				}
+				catch (InvalidOperationException ex)
+				{
+					_logger.LogWarning(ex, $"Error try deliver waiting order {WaitingOrder.Id}");
+				}
+				catch (Exception ex)
+				{
+					_logger.LogError(ex, $"Error while delivering waiting order {WaitingOrder.Id}");
+					throw;
+				}
+			}
+		}
+	}
 }
diff --git a/AutoWorkshopDataModels/Enums/OrderStatus.cs b/AutoWorkshopDataModels/Enums/OrderStatus.cs
index 6cddbbe..6b8f418 100644
--- a/AutoWorkshopDataModels/Enums/OrderStatus.cs
+++ b/AutoWorkshopDataModels/Enums/OrderStatus.cs
@@ -7,5 +7,6 @@
         BeingProcessed,
         Ready,
         Delivered,
+        Waiting,
     }
 }
diff --git a/AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.Designer.cs b/AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.Designer.cs
similarity index 97%
rename from AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.Designer.cs
rename to AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.Designer.cs
index afcaa58..6c409ae 100644
--- a/AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.Designer.cs
+++ b/AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.Designer.cs
@@ -12,13 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 namespace AutoWorkshopDatabaseImplement.Migrations
 {
     [DbContext(typeof(AutoWorkshopDatabase))]
-<<<<<<<< HEAD:AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.Designer.cs
-    [Migration("20240416160914_Implementers")]
-    partial class Implementers
-========
-    [Migration("20240514192226_Lab5_Hard")]
-    partial class Lab5_Hard
->>>>>>>> Lab5_Hard:AutoWorkshopDatabaseImplement/Migrations/20240514192226_Lab5_Hard.Designer.cs
+    [Migration("20240621132359_Lab6_Hard")]
+    partial class Lab6_Hard
     {
         /// <inheritdoc />
         protected override void BuildTargetModel(ModelBuilder modelBuilder)
diff --git a/AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.cs b/AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.cs
similarity index 97%
rename from AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.cs
rename to AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.cs
index b7fb11a..842855d 100644
--- a/AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.cs
+++ b/AutoWorkshopDatabaseImplement/Migrations/20240621132359_Lab6_Hard.cs
@@ -7,11 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 namespace AutoWorkshopDatabaseImplement.Migrations
 {
     /// <inheritdoc />
-<<<<<<<< HEAD:AutoWorkshopDatabaseImplement/Migrations/20240416160914_Implementers.cs
-    public partial class Implementers : Migration
-========
-    public partial class Lab5_Hard : Migration
->>>>>>>> Lab5_Hard:AutoWorkshopDatabaseImplement/Migrations/20240514192226_Lab5_Hard.cs
+    public partial class Lab6_Hard : Migration
     {
         /// <inheritdoc />
         protected override void Up(MigrationBuilder migrationBuilder)
diff --git a/AutoWorkshopView/MainForm.Designer.cs b/AutoWorkshopView/MainForm.Designer.cs
index 0a107e7..9d7d6c5 100644
--- a/AutoWorkshopView/MainForm.Designer.cs
+++ b/AutoWorkshopView/MainForm.Designer.cs
@@ -62,7 +62,7 @@
             // MenuStrip
             // 
             MenuStrip.ImageScalingSize = new Size(20, 20);
-            MenuStrip.Items.AddRange(new ToolStripItem[] { ToolStripMenu, OperationToolStripMenuItem, ReportsToolStripMenuItem });
+            MenuStrip.Items.AddRange(new ToolStripItem[] { ToolStripMenu, OperationToolStripMenuItem, ReportsToolStripMenuItem, WorkStartToolStripMenuItem });
             MenuStrip.Location = new Point(0, 0);
             MenuStrip.Name = "MenuStrip";
             MenuStrip.Padding = new Padding(5, 2, 0, 2);
@@ -293,7 +293,9 @@
         private ToolStripMenuItem TransactionToolStripMenuItem;
         private ToolStripMenuItem SaleToolStripMenuItem;
         private ToolStripMenuItem ReportsToolStripMenuItem;
-        private ToolStripMenuItem ReportRepairsToolStripMenuItem;
+		private ToolStripMenuItem ComponentsToolStripMenuItem1;
+		private ToolStripMenuItem ComponentRepairToolStripMenuItem1;
+		private ToolStripMenuItem ReportRepairsToolStripMenuItem;
         private ToolStripMenuItem ReportRepCompToolStripMenuItem;
         private ToolStripMenuItem OrdersToolStripMenuItem;
         private ToolStripMenuItem ReportShopsToolStripMenuItem;
diff --git a/AutoWorkshopView/Program.cs b/AutoWorkshopView/Program.cs
index 2e7a20b..87ed06d 100644
--- a/AutoWorkshopView/Program.cs
+++ b/AutoWorkshopView/Program.cs
@@ -10,7 +10,6 @@ using AutoWorkshopView.Forms.Shop;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using NLog.Extensions.Logging;
-using AutoWorkshopContracts.BusinessLogicsContracts;
 
 namespace AutoWorkshopView
 {
@@ -43,8 +42,6 @@ namespace AutoWorkshopView
             Services.AddTransient<IOrderStorage, OrderStorage>();
             Services.AddTransient<IRepairStorage, RepairStorage>();
             Services.AddTransient<IShopStorage, ShopStorage>();
-            Services.AddTransient<IClientStorage, ClientStorage>();
-
             Services.AddTransient<IClientStorage, ClientStorage>();
             Services.AddTransient<IImplementerStorage, ImplementerStorage>();
 
@@ -53,7 +50,6 @@ namespace AutoWorkshopView
             Services.AddTransient<IRepairLogic, RepairLogic>();
             Services.AddTransient<IReportLogic, ReportLogic>();
             Services.AddTransient<IShopLogic, ShopLogic>();
-			Services.AddTransient<IClientLogic, ClientLogic>();			
 			Services.AddTransient<IClientLogic, ClientLogic>();
             Services.AddTransient<IImplementerLogic, ImplementerLogic>();
             Services.AddTransient<IWorkProcess, WorkModeling>();