فهرست منبع

Merge remote-tracking branch 'origin/kenric' into frank

frankvandenbos 10 ماه پیش
والد
کامیت
5d3b45e870

+ 1 - 1
prs.classes/EnclosedEntities/Dimensions/DimensionUnit.cs

@@ -76,7 +76,7 @@ namespace Comal.Classes
                 "        // \n"+
                 "        // var qty = Dimensions.Quantity;\n"+
                 "        // Dimensions.Quantity = 1;\n"+
-                "        // Quantity = qty;\n"+
+                "        // Quantity *= qty;\n"+
                 "    }\n"+
                 "}\n";
         }

+ 105 - 49
prs.classes/Entities/Job/Requisitions/JobRequisitionItem.cs

@@ -397,9 +397,21 @@ namespace Comal.Classes
             }
             base.DoPropertyChanged(name, before, after);
         }
+
+        public class JRICostData
+        {
+            public Guid[] ProductIDs { get; set; } = Array.Empty<Guid>();
+
+            public Guid[] SupplierIDs { get; set; } = Array.Empty<Guid>();
+
+            public ProductInstance[] Instances { get; set; } = Array.Empty<ProductInstance>();
+
+            public SupplierProduct[] SupplierProducts { get; set; } = Array.Empty<SupplierProduct>();
+        }
         
-        public static void UpdateCosts(IEnumerable<JobRequisitionItem> items, Dictionary<String,object?> changes)
+        public static void UpdateCosts(IEnumerable<JobRequisitionItem> items, Dictionary<String,object?> changes, JRICostData? data = null)
         {
+            var itemList = items.AsIList();
 
             void UpdateValue<TType>(JobRequisitionItem item,Expression<Func<JobRequisitionItem, TType>> property, TType value)
             {
@@ -410,61 +422,105 @@ namespace Comal.Classes
                 );
             }
             
-            var productids = items.Where(x => x.Product.ID != Guid.Empty).Select(x => x.Product.ID).ToArray();
-            MultiQuery query = new MultiQuery();
-            query.Add(
-                new Filter<SupplierProduct>(x=>x.Product.ID).InList(productids),
-                Columns.None<SupplierProduct>().Add(x=>x.Product.ID)
-                    .Add(x=>x.SupplierLink.ID)
-                    .Add(x=>x.Style.ID)
-                    .AddDimensionsColumns(x => x.Dimensions, Classes.Dimensions.ColumnsType.Local)
-                    .Add(x=>x.Job.ID)
-                    .Add(x=>x.SupplierCode)
-                    .Add(x=>x.SupplierDescription)
-                    .Add(x=>x.CostPrice)
-            );
-            query.Add(
-                new Filter<ProductInstance>(x=>x.Product.ID).InList(productids),
-                Columns.None<ProductInstance>().Add(x=>x.Product.ID)
-                    .Add(x => x.Style.ID)
-                    .AddDimensionsColumns(x => x.Dimensions, Classes.Dimensions.ColumnsType.Local)
-                    .Add(x => x.NettCost)
-            );
-            query.Query();
-
-            var supplierProducts = query.Get<SupplierProduct>().ToArray<SupplierProduct>();
-            var productInstances = query.Get<ProductInstance>().ToArray<ProductInstance>();
-                
-            foreach (var item in items)
+            var productIDs = items.Where(x => x.Product.ID != Guid.Empty).Select(x => x.Product.ID).ToArray();
+            if(productIDs.Length == 0)
             {
-                //Check Supplier / Job Specific Pricing
-                var supplierProduct = supplierProducts.FirstOrDefault(x =>
-                    x.Product.ID == item.Product.ID
-                    && x.SupplierLink.ID == item.Supplier.ID
-                    && x.Style.ID == item.Style.ID
-                    && x.Dimensions.Equals(item.Dimensions)
-                    && x.Job.ID == item.Job.ID);
-                if (supplierProduct != null)
+                return;
+            }
+            var supplierIDs = items.Where(x => x.Supplier.ID != Guid.Empty).Select(x => x.Supplier.ID).ToArray();
+
+            ProductInstance[] instances;
+            SupplierProduct[] supplierProducts;
+
+            var needProducts = data is null || productIDs.Any(x => !data.ProductIDs.Contains(x));
+            var needSuppliers = data is null || supplierIDs.Any(x => !data!.SupplierIDs.Contains(x));
+
+            if(needProducts || needSuppliers)
+            {
+                MultiQuery query = new MultiQuery();
+                query.Add(
+                    new Filter<SupplierProduct>(x=>x.Product.ID).InList(productIDs).And(x => x.SupplierLink.ID).InList(supplierIDs),
+                    Columns.None<SupplierProduct>().Add(x=>x.Product.ID)
+                        .Add(x=>x.SupplierLink.ID)
+                        .Add(x=>x.Style.ID)
+                        .AddDimensionsColumns(x => x.Dimensions, Classes.Dimensions.ColumnsType.Local)
+                        .Add(x=>x.Job.ID)
+                        .Add(x=>x.SupplierCode)
+                        .Add(x=>x.SupplierDescription)
+                        .Add(x=>x.CostPrice)
+                );
+                if(needProducts)
                 {
-                    UpdateValue<double>(item, x => x.UnitCost, supplierProduct.CostPrice);
-                    continue;
+                    query.Add(
+                        new Filter<ProductInstance>(x=>x.Product.ID).InList(productIDs),
+                        Columns.None<ProductInstance>().Add(x=>x.Product.ID)
+                            .Add(x => x.Style.ID)
+                            .AddDimensionsColumns(x => x.Dimensions, Classes.Dimensions.ColumnsType.Local)
+                            .Add(x => x.NettCost)
+                    );
                 }
-                
-                // Check Supplier Pricing
-                supplierProduct = supplierProducts.FirstOrDefault(x =>
-                    x.Product.ID == item.Product.ID
-                    && x.SupplierLink.ID == item.Supplier.ID
-                    && x.Style.ID == item.Style.ID
-                    && x.Dimensions.Equals(item.Dimensions)
-                    && x.Job.ID == Guid.Empty);
-                if (supplierProduct != null)
+                query.Query();
+
+                supplierProducts = query.Get<SupplierProduct>().ToArray<SupplierProduct>();
+                if (needProducts)
+                {
+                    instances = query.Get<ProductInstance>().ToArray<ProductInstance>();
+                }
+                else
+                {
+                    instances = data!.Instances;
+                }
+
+                if(data != null)
+                {
+                    data.SupplierIDs = supplierIDs;
+                    data.SupplierProducts = supplierProducts;
+                    if (needProducts)
+                    {
+                        data.ProductIDs = productIDs;
+                        data.Instances = instances;
+                    }
+                }
+            }
+            else
+            {
+                supplierProducts = data!.SupplierProducts;
+                instances = data!.Instances;
+            }
+
+            foreach (var item in items)
+            {
+                if(supplierProducts != null)
                 {
-                    UpdateValue<double>(item, x => x.UnitCost, supplierProduct.CostPrice);
-                    continue;
+                    //Check Supplier / Job Specific Pricing
+                    var supplierProduct = supplierProducts.FirstOrDefault(x =>
+                        x.Product.ID == item.Product.ID
+                        && x.SupplierLink.ID == item.Supplier.ID
+                        && x.Style.ID == item.Style.ID
+                        && x.Dimensions.Equals(item.Dimensions)
+                        && x.Job.ID == item.Job.ID);
+                    if (supplierProduct != null)
+                    {
+                        UpdateValue<double>(item, x => x.UnitCost, supplierProduct.CostPrice);
+                        continue;
+                    }
+                    
+                    // Check Supplier Pricing
+                    supplierProduct = supplierProducts.FirstOrDefault(x =>
+                        x.Product.ID == item.Product.ID
+                        && x.SupplierLink.ID == item.Supplier.ID
+                        && x.Style.ID == item.Style.ID
+                        && x.Dimensions.Equals(item.Dimensions)
+                        && x.Job.ID == Guid.Empty);
+                    if (supplierProduct != null)
+                    {
+                        UpdateValue<double>(item, x => x.UnitCost, supplierProduct.CostPrice);
+                        continue;
+                    }
                 }
                 
                 // Check Specific Product Instance
-                var productInstance = productInstances.FirstOrDefault(x =>
+                var productInstance = instances.FirstOrDefault(x =>
                     x.Product.ID == item.Product.ID
                     && x.Style.ID == item.Style.ID
                     && x.Dimensions.Equals(item.Dimensions));

+ 7 - 16
prs.classes/Entities/Notification/Notification.cs

@@ -5,20 +5,6 @@ using InABox.Core;
 
 namespace Comal.Classes
 {
-
-    public class NotificationDocumentCount : CoreAggregate<Notification, NotificationDocument, Guid>
-    {
-        public override Expression<Func<NotificationDocument, Guid>> Aggregate => x => x.ID;
-
-        public override AggregateCalculation Calculation => AggregateCalculation.Count;
-
-        public override Dictionary<Expression<Func<NotificationDocument, object>>, Expression<Func<Notification, object>>> Links =>
-            new Dictionary<Expression<Func<NotificationDocument, object>>, Expression<Func<Notification, object>>>()
-            {
-                { NotificationDocument => NotificationDocument.EntityLink.ID, Notification => Notification.ID }
-            };
-    }
-    
     [UserTracking("Notifications")]
     public class Notification : Entity, IRemotable, IPersistent, IOneToMany<Job>, ILicense<CoreLicense>
     {
@@ -76,9 +62,14 @@ namespace Comal.Classes
 
         [NullEditor]
         public Guid EntityID { get; set; }
-        
+
+        private class DocumentCountFormula : ComplexFormulaGenerator<Notification, int>
+        {
+            public override IComplexFormulaNode<Notification, int> GetFormula() =>
+                Count<NotificationDocument, Guid>(x => x.Property(x => x.ID)).WithLink(x => x.EntityLink.ID, x => x.ID);
+        }
         [NullEditor]
-        [Aggregate(typeof(NotificationDocumentCount))]
+        [ComplexFormula(typeof(DocumentCountFormula))]
         public int DocumentCount { get; set; }
     }
 }

+ 2 - 0
prs.classes/Entities/Product/ProductLink.cs

@@ -35,6 +35,8 @@ namespace Comal.Classes
         [NullEditor]
         [RequiredColumn]
         public ProductInstanceLink DefaultInstance { get; set; }
+        
+        public ProductDimensionUnitLink UnitOfMeasure { get; set; }
 
         [NullEditor]
         [RequiredColumn]

+ 10 - 21
prs.classes/Entities/Stock/StockEntity.cs

@@ -10,27 +10,16 @@ namespace Comal.Classes
 
         public static void LinkStockDimensions<TStock>() where TStock : StockEntity
         {
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, Guid>(x => x.Product.Dimensions.Unit, x => x.ID, x => x.Dimensions.Unit.ID);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.Dimensions.Unit, x => x.Code, x => x.Dimensions.Unit.Code);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.Dimensions.Unit, x => x.Description, x => x.Dimensions.Unit.Description);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.Dimensions.Unit, x => x.HasLength, x => x.Dimensions.Unit.HasLength);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.Dimensions.Unit, x => x.HasHeight, x => x.Dimensions.Unit.HasHeight);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.Dimensions.Unit, x => x.HasQuantity, x => x.Dimensions.Unit.HasQuantity);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.Dimensions.Unit, x => x.HasWeight, x => x.Dimensions.Unit.HasWeight);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.Dimensions.Unit, x => x.HasWidth, x => x.Dimensions.Unit.HasWidth);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.Dimensions.Unit, x => x.Formula, x => x.Dimensions.Unit.Formula);
-            // LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.Dimensions.Unit, x => x.Format, x => x.Dimensions.Unit.Format);
-            
-            LinkedProperties.Register<TStock, StockDimensions, Guid>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.ID, x => x.Dimensions.Unit.ID);
-            LinkedProperties.Register<TStock, StockDimensions, String>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.Code, x => x.Dimensions.Unit.Code);
-            LinkedProperties.Register<TStock, StockDimensions, String>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.Description, x => x.Dimensions.Unit.Description);
-            LinkedProperties.Register<TStock, StockDimensions, bool>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.HasLength, x => x.Dimensions.Unit.HasLength);
-            LinkedProperties.Register<TStock, StockDimensions, bool>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.HasHeight, x => x.Dimensions.Unit.HasHeight);
-            LinkedProperties.Register<TStock, StockDimensions, bool>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.HasQuantity, x => x.Dimensions.Unit.HasQuantity);
-            LinkedProperties.Register<TStock, StockDimensions, bool>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.HasWeight, x => x.Dimensions.Unit.HasWeight);
-            LinkedProperties.Register<TStock, StockDimensions, bool>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.HasWidth, x => x.Dimensions.Unit.HasWidth);
-            LinkedProperties.Register<TStock, StockDimensions, String>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.Formula, x => x.Dimensions.Unit.Formula);
-            LinkedProperties.Register<TStock, StockDimensions, String>(x => x.Product.DefaultInstance.Dimensions, x => x.Unit.Format, x => x.Dimensions.Unit.Format);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, Guid>(x => x.Product.UnitOfMeasure, x => x.ID, x => x.Dimensions.Unit.ID);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.UnitOfMeasure, x => x.Code, x => x.Dimensions.Unit.Code);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.UnitOfMeasure, x => x.Description, x => x.Dimensions.Unit.Description);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.UnitOfMeasure, x => x.HasLength, x => x.Dimensions.Unit.HasLength);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.UnitOfMeasure, x => x.HasHeight, x => x.Dimensions.Unit.HasHeight);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.UnitOfMeasure, x => x.HasQuantity, x => x.Dimensions.Unit.HasQuantity);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.UnitOfMeasure, x => x.HasWeight, x => x.Dimensions.Unit.HasWeight);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, bool>(x => x.Product.UnitOfMeasure, x => x.HasWidth, x => x.Dimensions.Unit.HasWidth);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.UnitOfMeasure, x => x.Formula, x => x.Dimensions.Unit.Formula);
+            LinkedProperties.Register<TStock, ProductDimensionUnitLink, String>(x => x.Product.UnitOfMeasure, x => x.Format, x => x.Dimensions.Unit.Format);
             
             LinkedProperties.Register<TStock, StockDimensions, double>(x => x.Product.DefaultInstance.Dimensions, x => x.Height, x => x.Dimensions.Height);
             LinkedProperties.Register<TStock, StockDimensions, double>(x => x.Product.DefaultInstance.Dimensions, x => x.Length, x => x.Dimensions.Length);

+ 18 - 4
prs.desktop/Dashboards/Manufacturing/FactoryProductivity.xaml.cs

@@ -432,7 +432,20 @@ namespace PRSDesktop
                 var criteria = GetFilter();
                 var data = new Client<ManufacturingHistory>().Query(
                     criteria,
-                    null,
+                    Columns.None<ManufacturingHistory>()
+                        .Add(x => x.ID)
+                        .Add(x => x.Employee.Name)
+                        .Add(x => x.Section.Name)
+                        .Add(x => x.QADuration)
+                        .Add(x => x.WorkDuration)
+                        .Add(x => x.Packet.ID)
+                        .Add(x => x.Packet.SetoutLink.JobLink.Color)
+                        .Add(x => x.Packet.SetoutLink.JobLink.JobNumber)
+                        .Add(x => x.Packet.Serial)
+                        .Add(x => x.Packet.SetoutLink.Number)
+                        .Add(x => x.LostTime.ID)
+                        .Add(x => x.LostTime.Description)
+                        .Add(x => x.WorkCompleted),
                     new SortOrder<ManufacturingHistory>(x => x.Employee.Name)
                 );
 
@@ -477,15 +490,16 @@ namespace PRSDesktop
                     else
                         packet = "#FFFF0000|Lost Time";
 
-                    if (!Items.ContainsKey(packet))
+                    if (!Items.TryGetValue(packet, out List<History>? value))
                     {
                         var records = new List<History>();
                         foreach (var _staff in Staff)
                             records.Add(new History { Name = _staff.Name });
-                        Items[packet] = records;
+                        value = records;
+                        Items[packet] = value;
                     }
 
-                    var record = Items[packet].FirstOrDefault(x => string.Equals(x.Name, staff));
+                    var record = value.FirstOrDefault(x => string.Equals(x.Name, staff));
                     record.Packets = record.Packets + row.Get<ManufacturingHistory, int>(x => x.WorkCompleted);
                     record.Hours = record.Hours + row.Get<ManufacturingHistory, TimeSpan>(x => x.QADuration).TotalHours +
                                    row.Get<ManufacturingHistory, TimeSpan>(x => x.WorkDuration).TotalHours;

+ 5 - 1
prs.desktop/Panels/Jobs/Requisitions/JobRequisitionItemGrid.cs

@@ -339,15 +339,19 @@ internal class JobRequisitionItemGrid : DynamicDataGrid<JobRequisitionItem>, IMa
         result.Qty = 1;
         return result;
     }
+
+    private JobRequisitionItem.JRICostData? _jriCostData;
     
     protected override void OnAfterEditorValueChanged(DynamicEditorGrid? grid, JobRequisitionItem[] items, AfterEditorValueChangedArgs args, Dictionary<string, object?> changes)
     {
         base.OnAfterEditorValueChanged(grid, items, args, changes);
         if (args.ColumnName.Equals("Product.ID") || args.ColumnName.Equals("Dimensions") || args.ColumnName.StartsWith("Dimensions.") || args.ColumnName.Equals("Style.ID") || args.ColumnName.Equals("Supplier.ID"))
         {
+            _jriCostData ??= new();
             JobRequisitionItem.UpdateCosts(
                 items, 
-                changes
+                changes,
+                data: _jriCostData
             );
         }
     }

+ 2 - 0
prs.desktop/Panels/PanelHost.cs

@@ -486,6 +486,8 @@ public class PanelHost : IPanelHost
 
     private void Heartbeat(TimeSpan time, bool closing)
     {
+        if (TrackedTicks == DateTime.MinValue)
+            return;
         if (!closing && time.TotalMinutes < 5)
             return;
 

+ 19 - 17
prs.desktop/Panels/Stock Forecast/OrderScreen/StockForecastOrderingGrid.cs

@@ -688,25 +688,32 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         }
     }
 
-    private double CalculateSupplierProductRequiredQuantity(StockOrderingItem item, SupplierProduct supplierProduct)
+    /// <summary>
+    /// Calculate the number of units of the given <paramref name="supplierProduct"/> are needed to fill the given item.
+    /// </summary>
+    /// <remarks>
+    /// If we are doing breakups, and <paramref name="useRequiredQuantity"/> is <see langword="true"/>, then we use the <see cref="StockOrderingItem.GetJobRequiredQuantities"/>; otherwise, we use <see cref="StockForecastOrderingItemQuantity.Breakups"/>.
+    /// </remarks>
+    /// <param name="item"></param>
+    /// <param name="supplierProduct"></param>
+    /// <returns></returns>
+    private double CalculateSupplierProductRequiredQuantity(StockOrderingItem item, SupplierProduct supplierProduct, bool useRequiredQuantity)
     {
         var supplierIdx = Suppliers.WithIndex().FirstOrDefault(x => x.Value.ID == supplierProduct.SupplierLink.ID).Key;
         var qty = item.GetQuantity(supplierIdx);
-        var req = OrderType == StockForecastOrderingType.StockOrder ? item.RequiredQuantity : qty.Breakups.Sum(x => x.Value);
+        var req = OrderType == StockForecastOrderingType.StockOrder
+            ? item.RequiredQuantity
+            : (useRequiredQuantity ? item.GetJobRequiredQuantities().Sum(x => x.Value) : qty.Breakups.Sum(x => x.Value));
 
         var d = new StockDimensions();
         d.CopyFrom(supplierProduct.Dimensions);
         var result = DimensionUtils.ConvertDimensions(d, 1.0, (f,c) => Client.Query(f,c));
-        req = Math.Ceiling(req / result);
+        req /= result;
         return req;
     }
 
     private SupplierProduct? SelectSupplierProduct(IEnumerable<SupplierProduct> supplierProducts, StockOrderingItem item)
     {
-        double DimensionsRatio(SupplierProduct x)
-        {
-            return item.Dimensions.Value / (x.Dimensions.Value.IsEffectivelyEqual(0.0) ? (item.Dimensions.Value.IsEffectivelyEqual(0.0) ? 1.0 : item.Dimensions.Value) : x.Dimensions.Value);
-        }
         switch (item.OrderStrategy)
         {
             case SupplierProductOrderStrategy.Exact:
@@ -715,13 +722,13 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
                            .MinBy(x => x.CostPrice);
             
             case SupplierProductOrderStrategy.LowestOverallPrice:
-                return supplierProducts.MinBy(x => x.CostPrice * Math.Ceiling(CalculateSupplierProductRequiredQuantity(item, x) * DimensionsRatio(x)));
+                return supplierProducts.MinBy(x => x.CostPrice * Math.Ceiling(CalculateSupplierProductRequiredQuantity(item, x, true)));
 
             case SupplierProductOrderStrategy.LowestUnitPrice:
-                return supplierProducts.MinBy(x => x.CostPrice * DimensionsRatio(x));
+                return supplierProducts.MinBy(x => x.CostPrice / x.Dimensions.Value);
             
             case SupplierProductOrderStrategy.LowestOverstock:
-                return supplierProducts.MinBy(x => x.Dimensions.Value * Math.Ceiling(CalculateSupplierProductRequiredQuantity(item, x) * DimensionsRatio(x)));
+                return supplierProducts.MinBy(x => x.Dimensions.Value * Math.Ceiling(CalculateSupplierProductRequiredQuantity(item, x, true)));
                 
             default:
                 return null;
@@ -730,12 +737,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
 
     private double GetRequiredQuantity(StockOrderingItem item, SupplierProduct supplierProduct)
     {
-        var requiredQuantity = CalculateSupplierProductRequiredQuantity(item, supplierProduct);
-
-        double DimensionsRatio(SupplierProduct x)
-        {
-            return item.Dimensions.Value / (x.Dimensions.Value.IsEffectivelyEqual(0.0) ? (item.Dimensions.Value.IsEffectivelyEqual(0.0) ? 1.0 : item.Dimensions.Value) : x.Dimensions.Value);
-        }
+        var requiredQuantity = CalculateSupplierProductRequiredQuantity(item, supplierProduct, useRequiredQuantity: false);
 
         var _strategy = item.CustomStrategy
             ? SupplierProductOrderStrategy.LowestOverstock
@@ -750,7 +752,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
             case SupplierProductOrderStrategy.LowestOverallPrice:
             case SupplierProductOrderStrategy.LowestUnitPrice:
             case SupplierProductOrderStrategy.LowestOverstock:
-                return Math.Ceiling(requiredQuantity * DimensionsRatio(supplierProduct));
+                return Math.Ceiling(requiredQuantity);
             default:
                 return 0.0;
         }