| 
					
				 | 
			
			
				@@ -11,18 +11,89 @@ internal class Update_7_56 : DatabaseUpdateScript 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public override bool Update() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        var ids = DbFactory.Provider.Query<StockMovement>().Rows 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .Select(r => r.Get<StockMovement, Guid>(x => x.ID)).ToArray(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<StockHolding> allholdings = new List<StockHolding>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Logger.Send(LogType.Information, "", $"- Loading Stock Movements"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var movements = DbFactory.Provider.Query( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            new Columns<StockMovement>(x => x.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Location.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Product.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Style.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Job.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Unit.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Quantity) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Width) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Length) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Weight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.UnitSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Dimensions.Value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.JobRequisitionItem.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Units) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .Add(x => x.Cost) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Logger.Send(LogType.Information, "", $"Processing {movements.Rows.Count} Stock Movements"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach (var row in movements.Rows) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var movement = row.ToObject<StockMovement>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var holding = allholdings.FirstOrDefault(x => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (x.Product.ID == movement.Product.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                && (x.Location.ID == movement.Location.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                && (x.Style.ID == movement.Style.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                && (x.Job.ID == movement.Job.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                && (x.Dimensions.Unit.ID == movement.Dimensions.Unit.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                && (x.Dimensions.UnitSize == movement.Dimensions.UnitSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (holding == null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding = new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding.Location.ID = movement.Location.ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding.Product.ID = movement.Product.ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding.Style.ID = movement.Style.ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding.Job.ID = movement.Job.ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                holding.Dimensions.CopyFrom(movement.Dimensions); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                allholdings.Add(holding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.Units += movement.Units; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.Qty += movement.Units * movement.Dimensions.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.Value += movement.Units * movement.Cost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.Available += (movement.JobRequisitionItem.ID == Guid.Empty ? movement.Units : 0.0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.Weight = holding.Qty * holding.Dimensions.Weight; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            holding.AverageValue = holding.Units != 0 ? holding.Value / holding.Units : 0.0F; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((row.Index > 0) && (row.Index % 1000 == 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Logger.Send(LogType.Information, "", $"Processed {row.Index} movements / {allholdings.Count} holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (movements.Rows.Count % 1000 != 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Logger.Send(LogType.Information, "", $"Processed {movements.Rows.Count} movements / {allholdings.Count} holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var nonempty = allholdings.Where(x => Math.Abs(x.Units) >= 0.000001F).ToList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Logger.Send(LogType.Information, "", $"Saving {nonempty.Count} non-empty Stock Holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var updates = new List<StockHolding>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int i = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        foreach (var id in ids) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while (i < nonempty.Count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            StockHoldingStore.UpdateStockHolding(id, StockHoldingStore.Action.Increase); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            updates.Add(nonempty[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (updates.Count == 1000) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                DbFactory.Provider.Save(updates); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Logger.Send(LogType.Information, "", $"Saved {i+1}/{nonempty.Count} Stock Holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                updates.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             i++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (i % 100 == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                Logger.Send(LogType.Information, "", $"Converted {i}/{ids.Length} Stock Holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (i % 100 != 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            Logger.Send(LogType.Information, "", $"Converted {ids.Length}/{ids.Length} Stock Holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (updates.Any()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            DbFactory.Provider.Save(updates); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Logger.Send(LogType.Information, "", $"Saved {nonempty.Count}/{nonempty.Count} Stock Holdings"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |