Browse Source

Improvement to stock ordering screen

Kenric Nugteren 10 months ago
parent
commit
2f3767026c

+ 10 - 3
prs.desktop/Panels/Stock Forecast/OrderScreen/StockForecastOrderScreen.xaml

@@ -15,7 +15,8 @@
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
         <local:StockForecastOrderingGrid x:Name="Grid" Margin="5,5,5,0"
-                                         OnChanged="Grid_OnChanged"/>
+                                         OnChanged="Grid_OnChanged"
+                                         OnSelectItem="Grid_OnSelectItem"/>
         <DockPanel Grid.Row="1" LastChildFill="False" x:Name="Buttons">
             <Label DockPanel.Dock="Left" Margin="5"
                    x:Name="OrderTypeLabel"
@@ -35,14 +36,20 @@
                 Content="Order Strategy: "
                 VerticalAlignment="Stretch" 
                 VerticalContentAlignment="Center"/>
-
             <ComboBox 
                 x:Name="OrderStrategyBox" 
                 DockPanel.Dock="Left" 
                 Margin="0,5,5,5"
                 MinWidth="140"
                 SelectionChanged="OrderStrategyBox_OnSelectionChanged"/>
-            
+
+            <Button x:Name="StyleSelectButton"
+                    DockPanel.Dock="Left"
+                    IsEnabled="False"
+                    Margin="5" Padding="5"
+                    Content="Select Style"
+                    Click="StyleSelectButton_Click"/>
+
             <Button x:Name="CancelButton" Click="CancelButton_Click"
                     Content="Cancel"
                     Margin="5" Padding="5" MinWidth="60"

+ 23 - 0
prs.desktop/Panels/Stock Forecast/OrderScreen/StockForecastOrderScreen.xaml.cs

@@ -19,6 +19,7 @@ using System.Windows.Media.Imaging;
 using System.Windows.Shapes;
 using InABox.Configuration;
 using InABox.Clients;
+using InABox.DynamicGrid;
 
 namespace PRSDesktop;
 
@@ -226,4 +227,26 @@ public partial class StockForecastOrderScreen : Window, INotifyPropertyChanged
 
         MessageWindow.ShowMessage($"The following orders were created:\n- {string.Join("\n- ",orders.Select(x=>x.Item1.PONumber))}", $"Created {orders.Count} orders");
     }
+
+    private void StyleSelectButton_Click(object sender, RoutedEventArgs e)
+    {
+        var dlg = new MultiSelectDialog<ProductStyle>(
+            null,
+            Columns.None<ProductStyle>().Add(x => x.ID).Add(x => x.Code),
+            multiselect: false);
+        var result = dlg.ShowDialog();
+        if(result == true)
+        {
+            Grid.SetStyle(dlg.Data().ToObjects<ProductStyle>().First());
+        }
+        else if(result == false)
+        {
+            Grid.SetStyle(null);
+        }
+    }
+
+    private void Grid_OnSelectItem(object sender, InABox.DynamicGrid.DynamicGridSelectionEventArgs e)
+    {
+        StyleSelectButton.IsEnabled = e.Rows is not null && e.Rows.Length > 0;
+    }
 }

+ 216 - 182
prs.desktop/Panels/Stock Forecast/OrderScreen/StockForecastOrderingGrid.cs

@@ -211,6 +211,8 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
 {
     #region Internal Data + Caches
 
+    private static BitmapImage _warning = PRSDesktop.Resources.warning.AsBitmapImage();
+
     private List<SupplierProduct> SupplierProducts = [];
     private SupplierLink[] Suppliers = [];
 
@@ -223,8 +225,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
 
     #endregion
 
-    private static BitmapImage _warning = PRSDesktop.Resources.warning.AsBitmapImage();
-
     #region Public Properties
 
     public IList<StockForecastOrderData> OrderData { get; set; }
@@ -316,6 +316,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
     public StockForecastOrderingGrid()
     {
         HiddenColumns.Add(x => x.Product.Image.ID);
+        HiddenColumns.Add(x => x.Style.Code);
     }
 
     private static SupplierProductOrderStrategy CastOrderStrategyToProductOrderStrategy(StockForecastOrderingStrategy strategy, SupplierProductOrderStrategy defaultValue)
@@ -365,11 +366,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
             DataGrid.FrozenColumnCount = 8;
         }
 
-        protected override Brush? GetCellSelectionBackgroundBrush()
-        {
-            return null;
-        }
-
         protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)
         {
             var item = Grid.LoadItem(row);
@@ -407,9 +403,12 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
     protected override void DoReconfigure(DynamicGridOptions options)
     {
         options.Clear();
-        options.FilterRows = true; 
+        options.FilterRows = true;
+        options.MultiSelect = true;
     }
 
+    #region Data
+
     private bool _loadedData = false;
     private void LoadData()
     {
@@ -439,7 +438,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         _loadedData = true;
     }
 
-    private StockForecastOrderingItemQuantity CreateQuantity(int itemIdx)
+    private StockForecastOrderingItemQuantity CreateQuantity(int itemIdx, int supplierIdx)
     {
         var qty = new StockForecastOrderingItemQuantity();
         qty.Changed += () =>
@@ -447,12 +446,64 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
             if (!_observing) return;
 
             var row = Data.Rows[itemIdx];
-            InvalidateRow(row);
+            foreach(var ac in ActionColumns)
+            {
+                if(ac != QuantityColumns[supplierIdx])
+                {
+                    UpdateCell(row, ac);
+                }
+            }
             DoChanged();
         };
         return qty;
     }
 
+    private void CalculateQuantities(bool recreateItems)
+    {
+        SetObserving(false);
+
+        if (recreateItems)
+        {
+            Items.Clear();
+            foreach(var dataItem in OrderData)
+            {
+                var item = new StockOrderingItem();
+                item.Product.CopyFrom(dataItem.Product);
+                item.Style.CopyFrom(dataItem.Style);
+                item.Dimensions.CopyFrom(dataItem.Dimensions);
+                item.OrderStrategy = CastOrderStrategyToProductOrderStrategy(OrderStrategy, item.Product.OrderStrategy);
+                item.RequiredQuantity = dataItem.RequiredQuantity;
+                foreach(var breakup in dataItem.GetRequiredQuantities())
+                {
+                    item.SetJobRequiredQuantity(breakup.JobID, breakup.JobRequiItemID, breakup.Quantity);
+                }
+                Items.Add(item);
+            }
+        }
+
+        foreach(var (itemIdx, item) in Items.WithIndex())
+        {
+            var quantities = new StockForecastOrderingItemQuantity[Suppliers.Length];
+            for(int i = 0; i < Suppliers.Length; ++i)
+            {
+                quantities[i] = CreateQuantity(itemIdx, i);
+            }
+
+            item.SetQuantities(quantities);
+        }
+
+        foreach(var item in Items)
+        {
+            CalculateSupplierProduct(item);
+        }
+        SetObserving(true);
+        DoChanged();
+    }
+
+    #endregion
+
+    #region Order Strategy
+
     private SupplierProduct? CalculateSupplierProduct(StockOrderingItem item, int supplierIdx)
     {
         var supplierProducts = string.IsNullOrWhiteSpace(item.Dimensions.Unit.Conversion)
@@ -509,50 +560,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         }
     }
 
-    private void CalculateQuantities(bool recreateItems)
-    {
-        SetObserving(false);
-
-        if (recreateItems)
-        {
-            Items.Clear();
-            foreach(var dataItem in OrderData)
-            {
-                var item = new StockOrderingItem();
-                item.Product.CopyFrom(dataItem.Product);
-                item.Style.CopyFrom(dataItem.Style);
-                item.Dimensions.CopyFrom(dataItem.Dimensions);
-                item.OrderStrategy = CastOrderStrategyToProductOrderStrategy(OrderStrategy, item.Product.OrderStrategy);
-                item.RequiredQuantity = dataItem.RequiredQuantity;
-                foreach(var breakup in dataItem.GetRequiredQuantities())
-                {
-                    item.SetJobRequiredQuantity(breakup.JobID, breakup.JobRequiItemID, breakup.Quantity);
-                }
-                Items.Add(item);
-            }
-        }
-
-        foreach(var (itemIdx, item) in Items.WithIndex())
-        {
-            var quantities = new StockForecastOrderingItemQuantity[Suppliers.Length];
-            for(int i = 0; i < Suppliers.Length; ++i)
-            {
-                quantities[i] = CreateQuantity(itemIdx);
-            }
-
-            item.SetQuantities(quantities);
-        }
-
-        foreach(var item in Items)
-        {
-            CalculateSupplierProduct(item);
-        }
-        SetObserving(true);
-        DoChanged();
-    }
-
-    #region Order Strategy
-
     private double CalculateSupplierProductRequiredQuantity(StockOrderingItem item, SupplierProduct supplierProduct)
     {
         var supplierIdx = Suppliers.WithIndex().FirstOrDefault(x => x.Value.ID == supplierProduct.SupplierLink.ID).Key;
@@ -623,6 +630,8 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
 
     #endregion
 
+    #region Columns
+
     private bool _loadedColumns = false;
     protected override DynamicGridColumns LoadColumns()
     {
@@ -690,90 +699,12 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         return columns;
     }
 
-    private void EditSupplierProductGrid(DynamicGrid<SupplierProduct> grid)
-    {
-        grid.OnCustomiseEditor += (sender, items, column, editor) =>
-        {
-            if(new Column<SupplierProduct>(x => x.SupplierLink.ID).IsEqualTo(column.ColumnName)
-                || new Column<SupplierProduct>(x => x.Product.ID).IsEqualTo(column.ColumnName)
-                || new Column<SupplierProduct>(x => x.Style.ID).IsEqualTo(column.ColumnName))
-            {
-                editor.Editable = editor.Editable.Combine(Editable.Disabled);
-            }
-        };
-    }
-
-    private void BuildMenu(DynamicMenuColumn column, CoreRow? row)
+    protected override void ConfigureColumnGroups()
     {
-        if (row is null) return;
-
-        column.AddItem("New Supplier", null, row =>
+        for(int idx = 0; idx < Suppliers.Length; ++idx)
         {
-            if (row is null) return;
-
-            var selection = new MultiSelectDialog<Supplier>(
-                new Filter<Supplier>(x => x.ID).NotInList(Suppliers.Select(x => x.ID).ToArray()),
-                Columns.None<Supplier>().Add(x => x.ID).Add(x => x.Code), multiselect: false);
-            if (selection.ShowDialog() != true)
-            {
-                return;
-            }
-
-            var supplier = selection.Data().Rows.First().ToObject<Supplier>();
-            var orderingItem = LoadItem(row);
-
-            var supplierProduct = new SupplierProduct();
-            supplierProduct.Product.CopyFrom(orderingItem.Product);
-            supplierProduct.Style.CopyFrom(orderingItem.Style);
-            supplierProduct.Dimensions.CopyFrom(orderingItem.Dimensions);
-            supplierProduct.SupplierLink.CopyFrom(supplier);
-
-            if (DynamicGridUtils.EditEntity(supplierProduct, customiseGrid: EditSupplierProductGrid))
-            {
-                SupplierProducts.Add(supplierProduct);
-                var newSuppliers = new SupplierLink[Suppliers.Length + 1];
-                var newIdx = Suppliers.Length;
-
-                for (int i = 0; i < Suppliers.Length; i++)
-                {
-                    newSuppliers[i] = Suppliers[i];
-                }
-                newSuppliers[newIdx] = supplierProduct.SupplierLink;
-
-                foreach (var (itemIdx, item) in Items.WithIndex())
-                {
-                    var quantities = new StockForecastOrderingItemQuantity[newSuppliers.Length];
-                    for (int i = 0; i < Suppliers.Length; ++i)
-                    {
-                        quantities[i] = item.GetQuantity(i);
-                    }
-                    var newQty = CreateQuantity(itemIdx);
-
-                    quantities[newIdx] = newQty;
-                    if(OrderType == StockForecastOrderingType.StockOrder)
-                    {
-                        newQty.OrderTotal = 0;
-                    }
-                    else
-                    {
-                        newQty.OrderTotal = 0;
-                        foreach(var id in item.GetJobRequiredQuantities().Keys)
-                        {
-                            newQty.Breakups[id] = 0;
-                        }
-                    }
-                    item.SetQuantities(quantities);
-                }
-                Suppliers = newSuppliers;
-                foreach (var item in Items)
-                {
-                    CalculateSupplierProduct(item, newIdx);
-                }
-
-                _loadedColumns = false;
-                Refresh(true, true);
-            }
-        });
+            GetColumnGrouping().AddGroup(Suppliers[idx].Code, SupplierProductColumns[idx], CostColumns[idx]);
+        }
     }
 
     private BitmapImage? Warning_Image(CoreRow? row)
@@ -791,51 +722,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         }
     }
 
-    protected override void ConfigureColumnGroups()
-    {
-        for(int idx = 0; idx < Suppliers.Length; ++idx)
-        {
-            GetColumnGrouping().AddGroup(Suppliers[idx].Code, SupplierProductColumns[idx], CostColumns[idx]);
-        }
-    }
-
-    #region Job Data Cache
-
-    private void LoadJobData(IEnumerable<Guid> ids)
-    {
-        var neededIDs = ids.Where(x => x != Guid.Empty && !JobDetails.ContainsKey(x)).ToArray();
-        if(neededIDs.Length > 0)
-        {
-            var details = Client.Query(
-                new Filter<Job>(x => x.ID).InList(neededIDs),
-                Columns.None<Job>().Add(x => x.ID)
-                    .Add(x => x.JobNumber)
-                    .Add(x => x.Name));
-            foreach(var job in details.ToObjects<Job>())
-            {
-                JobDetails[job.ID] = job;
-            }
-        }
-    }
-    private void LoadJobRequiData(IEnumerable<Guid> ids)
-    {
-        var neededIDs = ids.Where(x => x != Guid.Empty && !JobRequiDetails.ContainsKey(x)).ToArray();
-        if(neededIDs.Length > 0)
-        {
-            var details = Client.Query(
-                new Filter<JobRequisitionItem>(x => x.ID).InList(neededIDs),
-                Columns.None<JobRequisitionItem>().Add(x => x.ID)
-                    .Add(x => x.Requisition.Number)
-                    .Add(x => x.Requisition.Description));
-            foreach(var requi in details.ToObjects<JobRequisitionItem>())
-            {
-                JobRequiDetails[requi.ID] = requi;
-            }
-        }
-    }
-
-    #endregion
-
     private class QuantityControl : ContentControl
     {
         private readonly StockOrderingItem Item;
@@ -1015,7 +901,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
                 ? SupplierProducts.Where(x => x.Dimensions.Equals(instance.Dimensions))
                 : SupplierProducts;
 
-            var items = supplierProducts.Where(x => x.SupplierLink.ID == Suppliers[idx].ID && x.Product.ID == instance.Product.ID)
+            var items = supplierProducts.Where(x => x.SupplierLink.ID == Suppliers[idx].ID && x.Product.ID == instance.Product.ID && x.Style.ID == instance.Style.ID)
                 .Select(x => new KeyValuePair<SupplierProduct?, string>(x, x.Job.ID == Guid.Empty ? x.Dimensions.UnitSize : $"Job {x.Job.JobNumber}: {x.Dimensions.UnitSize}"));
             if (items.Any())
                 items = items.Prepend(new KeyValuePair<SupplierProduct?, string>(null, ""));
@@ -1112,6 +998,97 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
         });
     }
 
+
+    #endregion
+
+    #region New Suppliers and Supplier Products
+
+    private void EditSupplierProductGrid(DynamicGrid<SupplierProduct> grid)
+    {
+        grid.OnCustomiseEditor += (sender, items, column, editor) =>
+        {
+            if(new Column<SupplierProduct>(x => x.SupplierLink.ID).IsEqualTo(column.ColumnName)
+                || new Column<SupplierProduct>(x => x.Product.ID).IsEqualTo(column.ColumnName)
+                || new Column<SupplierProduct>(x => x.Style.ID).IsEqualTo(column.ColumnName))
+            {
+                editor.Editable = editor.Editable.Combine(Editable.Disabled);
+            }
+        };
+    }
+
+    private void BuildMenu(DynamicMenuColumn column, CoreRow? row)
+    {
+        if (row is null) return;
+
+        column.AddItem("New Supplier", null, row =>
+        {
+            if (row is null) return;
+
+            var selection = new MultiSelectDialog<Supplier>(
+                new Filter<Supplier>(x => x.ID).NotInList(Suppliers.Select(x => x.ID).ToArray()),
+                Columns.None<Supplier>().Add(x => x.ID).Add(x => x.Code), multiselect: false);
+            if (selection.ShowDialog() != true)
+            {
+                return;
+            }
+
+            var supplier = selection.Data().Rows.First().ToObject<Supplier>();
+            var orderingItem = LoadItem(row);
+
+            var supplierProduct = new SupplierProduct();
+            supplierProduct.Product.CopyFrom(orderingItem.Product);
+            supplierProduct.Style.CopyFrom(orderingItem.Style);
+            supplierProduct.Dimensions.CopyFrom(orderingItem.Dimensions);
+            supplierProduct.SupplierLink.CopyFrom(supplier);
+
+            if (DynamicGridUtils.EditEntity(supplierProduct, customiseGrid: EditSupplierProductGrid))
+            {
+                SupplierProducts.Add(supplierProduct);
+                var newSuppliers = new SupplierLink[Suppliers.Length + 1];
+                var newIdx = Suppliers.Length;
+
+                for (int i = 0; i < Suppliers.Length; i++)
+                {
+                    newSuppliers[i] = Suppliers[i];
+                }
+                newSuppliers[newIdx] = supplierProduct.SupplierLink;
+
+                foreach (var (itemIdx, item) in Items.WithIndex())
+                {
+                    var quantities = new StockForecastOrderingItemQuantity[newSuppliers.Length];
+                    for (int i = 0; i < Suppliers.Length; ++i)
+                    {
+                        quantities[i] = item.GetQuantity(i);
+                    }
+                    var newQty = CreateQuantity(itemIdx, newSuppliers.Length - 1);
+
+                    quantities[newIdx] = newQty;
+                    if(OrderType == StockForecastOrderingType.StockOrder)
+                    {
+                        newQty.OrderTotal = 0;
+                    }
+                    else
+                    {
+                        newQty.OrderTotal = 0;
+                        foreach(var id in item.GetJobRequiredQuantities().Keys)
+                        {
+                            newQty.Breakups[id] = 0;
+                        }
+                    }
+                    item.SetQuantities(quantities);
+                }
+                Suppliers = newSuppliers;
+                foreach (var item in Items)
+                {
+                    CalculateSupplierProduct(item, newIdx);
+                }
+
+                _loadedColumns = false;
+                Refresh(true, true);
+            }
+        });
+    }
+
     private void CreateSupplierProduct_Click(Tuple<StockOrderingItem, int> tuple)
     {
         var (item, supplierIdx) = tuple;
@@ -1138,4 +1115,61 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockOrderingItem>
             InvalidateGrid();
         }
     }
+
+    #endregion
+
+    #region Job Data Cache
+
+    private void LoadJobData(IEnumerable<Guid> ids)
+    {
+        var neededIDs = ids.Where(x => x != Guid.Empty && !JobDetails.ContainsKey(x)).ToArray();
+        if(neededIDs.Length > 0)
+        {
+            var details = Client.Query(
+                new Filter<Job>(x => x.ID).InList(neededIDs),
+                Columns.None<Job>().Add(x => x.ID)
+                    .Add(x => x.JobNumber)
+                    .Add(x => x.Name));
+            foreach(var job in details.ToObjects<Job>())
+            {
+                JobDetails[job.ID] = job;
+            }
+        }
+    }
+    private void LoadJobRequiData(IEnumerable<Guid> ids)
+    {
+        var neededIDs = ids.Where(x => x != Guid.Empty && !JobRequiDetails.ContainsKey(x)).ToArray();
+        if(neededIDs.Length > 0)
+        {
+            var details = Client.Query(
+                new Filter<JobRequisitionItem>(x => x.ID).InList(neededIDs),
+                Columns.None<JobRequisitionItem>().Add(x => x.ID)
+                    .Add(x => x.Requisition.Number)
+                    .Add(x => x.Requisition.Description));
+            foreach(var requi in details.ToObjects<JobRequisitionItem>())
+            {
+                JobRequiDetails[requi.ID] = requi;
+            }
+        }
+    }
+
+    #endregion
+
+    public void SetStyle(ProductStyle? style)
+    {
+        foreach(var row in SelectedRows)
+        {
+            var item = LoadItem(row);
+            if(style is null)
+            {
+                item.Style.CopyFrom(new ProductStyleLink());
+            }
+            else
+            {
+                item.Style.CopyFrom(style);
+            }
+            CalculateSupplierProduct(item);
+            UpdateRow(row, item);
+        }
+    }
 }