Browse Source

Fix to some POIAs with empty Jobs. Extracted Ordering functionality to avoid duplicate code.

Kenric Nugteren 9 months ago
parent
commit
68a9ad492e

+ 10 - 6
prs.desktop/Panels/Jobs/Summary/JobSummaryGrid.cs

@@ -953,13 +953,17 @@ internal class JobSummaryGrid : DynamicDataGrid<JobMaterial>, IMasterDetailContr
             if (poItems.Any())
             if (poItems.Any())
             {
             {
                 List<PurchaseOrderItemAllocation> poias = new();
                 List<PurchaseOrderItemAllocation> poias = new();
-                foreach (var poItem in poItems)
+                var jobID = Master?.ID ?? Guid.Empty;
+                if(jobID != Guid.Empty)
                 {
                 {
-                    var poia = new PurchaseOrderItemAllocation();
-                    poia.Item.ID = poItem.ID;
-                    poia.Job.ID = Master?.ID ?? Guid.Empty;
-                    poia.Quantity = poItem.Qty;
-                    poias.Add(poia);
+                    foreach (var poItem in poItems)
+                    {
+                        var poia = new PurchaseOrderItemAllocation();
+                        poia.Item.ID = poItem.ID;
+                        poia.Job.ID = jobID;
+                        poia.Quantity = poItem.Qty;
+                        poias.Add(poia);
+                    }
                 }
                 }
 
 
                 if (poias.Any())
                 if (poias.Any())

+ 6 - 15
prs.desktop/Panels/PurchaseOrders/SupplierPurchaseOrderItemOneToMany.cs

@@ -20,13 +20,10 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
     private Button receive;
     private Button receive;
     private Button assignLocation;
     private Button assignLocation;
 
 
-    private List<Tuple<PurchaseOrderItem, PurchaseOrderItemAllocation>> Allocations = new();
+    private readonly List<Tuple<PurchaseOrderItem, PurchaseOrderItemAllocation>> Allocations = new();
 
 
     public SupplierPurchaseOrderItemOneToMany() : base()
     public SupplierPurchaseOrderItemOneToMany() : base()
     {
     {
-        
-        
-        
         HiddenColumns.Add(x => x.ID);
         HiddenColumns.Add(x => x.ID);
 
 
         HiddenColumns.Add(x => x.Description);
         HiddenColumns.Add(x => x.Description);
@@ -44,7 +41,6 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
         HiddenColumns.Add(x => x.BillLine.ID);
         HiddenColumns.Add(x => x.BillLine.ID);
         HiddenColumns.Add(x => x.Consignment.ID);
         HiddenColumns.Add(x => x.Consignment.ID);
 
 
-        HiddenColumns.Add(x => x.Job.ID);
         HiddenColumns.Add(x => x.StockLocation.ID);
         HiddenColumns.Add(x => x.StockLocation.ID);
         HiddenColumns.Add(x => x.PurchaseGL.ID);
         HiddenColumns.Add(x => x.PurchaseGL.ID);
         HiddenColumns.Add(x => x.CostCentre.ID);
         HiddenColumns.Add(x => x.CostCentre.ID);
@@ -81,11 +77,8 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
         HiddenColumns.Add(x => x.OpenForms);
         HiddenColumns.Add(x => x.OpenForms);
         ActionColumns.Add(new DynamicMenuColumn(BuildFormsMenu) { Position = DynamicActionColumnPosition.End });
         ActionColumns.Add(new DynamicMenuColumn(BuildFormsMenu) { Position = DynamicActionColumnPosition.End });
         ActionColumns.Add(new DynamicImageColumn(FormsImage) { Position = DynamicActionColumnPosition.Start, ToolTip = FormsToolTip });
         ActionColumns.Add(new DynamicImageColumn(FormsImage) { Position = DynamicActionColumnPosition.Start, ToolTip = FormsToolTip });
-        
     }
     }
 
 
-
-
     protected override void Init()
     protected override void Init()
     {
     {
         base.Init();
         base.Init();
@@ -177,16 +170,16 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
         {
         {
             var poi = LoadItem(row);
             var poi = LoadItem(row);
 
 
-            IEnumerable<Guid> _allocationIDs;
+            IList<Guid> _jriIDs;
             if(poi.ID == Guid.Empty)
             if(poi.ID == Guid.Empty)
             {
             {
-                // If not saved yet, we will have any jriPOIs in the transient list.
-                _allocationIDs = Allocations.Where(x => x.Item1 == poi).Select(x => x.Item2.JobRequisitionItem.ID).ToList();
+                // If not saved yet, any allocations will be in the transient list.
+                _jriIDs = Allocations.Where(x => x.Item1 == poi).Select(x => x.Item2.JobRequisitionItem.ID).ToList();
             }
             }
             else
             else
             {
             {
                 // Otherwise, they'll all be in the database.
                 // Otherwise, they'll all be in the database.
-                _allocationIDs = Client.Query(
+                _jriIDs = Client.Query(
                     new Filter<PurchaseOrderItemAllocation>(x => x.Item.ID).IsEqualTo(poi.ID),
                     new Filter<PurchaseOrderItemAllocation>(x => x.Item.ID).IsEqualTo(poi.ID),
                     Columns.None<PurchaseOrderItemAllocation>().Add(x => x.JobRequisitionItem.ID))
                     Columns.None<PurchaseOrderItemAllocation>().Add(x => x.JobRequisitionItem.ID))
                     .ExtractValues<PurchaseOrderItemAllocation, Guid>(x => x.JobRequisitionItem.ID);
                     .ExtractValues<PurchaseOrderItemAllocation, Guid>(x => x.JobRequisitionItem.ID);
@@ -211,8 +204,6 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
             newLine.TaxCode.Synchronise(poi.TaxCode);
             newLine.TaxCode.Synchronise(poi.TaxCode);
             newLine.PurchaseOrderLink.ID = poi.PurchaseOrderLink.ID;
             newLine.PurchaseOrderLink.ID = poi.PurchaseOrderLink.ID;
             newLine.PurchaseOrderLink.Synchronise(poi.PurchaseOrderLink);
             newLine.PurchaseOrderLink.Synchronise(poi.PurchaseOrderLink);
-            newLine.Job.ID = poi.Job.ID;
-            newLine.Job.Synchronise(poi.Job);
             newLine.Dimensions.CopyFrom(poi.Dimensions);
             newLine.Dimensions.CopyFrom(poi.Dimensions);
 
 
             // Copying across the posted reference; this would be a problem if we were to try to sync via a Poster two purchase order items with the
             // Copying across the posted reference; this would be a problem if we were to try to sync via a Poster two purchase order items with the
@@ -234,7 +225,7 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
             poi.Qty = value;
             poi.Qty = value;
             newLine.Qty = qty - value;
             newLine.Qty = qty - value;
 
 
-            foreach(var jriID in _allocationIDs)
+            foreach(var jriID in _jriIDs)
             {
             {
                 // Add to a list to be saved later.
                 // Add to a list to be saved later.
                 var jriPoi = new PurchaseOrderItemAllocation();
                 var jriPoi = new PurchaseOrderItemAllocation();

+ 1 - 79
prs.desktop/Panels/Reservation Management/ReservationManagementItemGrid.cs

@@ -396,7 +396,6 @@ public class ReservationManagementItemGrid : DynamicDataGrid<JobRequisitionItem>
 
 
             item.RequiredQuantity += qtyrequired;
             item.RequiredQuantity += qtyrequired;
             item.SetRequiredQuantity(jobid, id, $"{jobnumber}-{requinumber}",qtyrequired);
             item.SetRequiredQuantity(jobid, id, $"{jobnumber}-{requinumber}",qtyrequired);
-            
         }
         }
 
 
         var window = new StockForecastOrderScreen(items, false);
         var window = new StockForecastOrderScreen(items, false);
@@ -404,84 +403,7 @@ public class ReservationManagementItemGrid : DynamicDataGrid<JobRequisitionItem>
         {
         {
             return false;
             return false;
         }
         }
-
-        var results = window.Results;
-        
-         var orders = new List<Tuple<PurchaseOrder, Dictionary<StockForecastOrderingResult,PurchaseOrderItem>>>();
-        Progress.ShowModal("Creating Orders", progress =>
-        {
-            int iOrder = 1;
-            foreach(var perSupplier in window.Results.GroupBy(x => x.Supplier.ID))
-            {
-                progress.Report($"Creating Orders ({iOrder++}/{window.Results.ToArray().Length})");
-                var order = new PurchaseOrder();
-                order.Description = "Purchase Order created from Reservation Management Screen";
-                order.RaisedBy.ID = App.EmployeeID;
-
-                LookupFactory.DoLookup<PurchaseOrder, Supplier, SupplierLink>(order, x => x.SupplierLink, perSupplier.Key);
-
-                var orderItems = new Dictionary<StockForecastOrderingResult,PurchaseOrderItem>();
-                var results = perSupplier.ToArray();
-                foreach(var item in results)
-                {
-                    var orderItem = new PurchaseOrderItem();
-                    orderItem.Product.ID = item.Item.Product.ID;
-                    orderItem.Style.ID = item.Item.Style.ID;
-                    orderItems[item] = orderItem;
-                }
-
-                LookupFactory.DoLookups<PurchaseOrderItem, Product, ProductLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Product.ID)),
-                    x => x.Product);
-                LookupFactory.DoLookups<PurchaseOrderItem, ProductStyle, ProductStyleLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Style.ID)),
-                    x => x.Style);
-                LookupFactory.DoLookups<PurchaseOrderItem, TaxCode, TaxCodeLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.TaxCode.ID)),
-                    x => x.TaxCode);
-
-                foreach(var item in results)
-                {
-                    var orderItem = orderItems[item];
-                    orderItem.Dimensions.CopyFrom(item.Item.Dimensions);
-                    orderItem.Qty = item.Quantity;
-                    orderItem.ForeignCurrencyCost = item.SupplierProduct.ForeignCurrencyPrice;
-                    orderItem.Cost = item.SupplierProduct.CostPrice;
-                }
-
-                orders.Add(new(order, orderItems));
-            }
-            
-            progress.Report($"Saving {orders.Count} Orders");
-            Client.Save(orders.Select(x => x.Item1), "Created from Reservation Management screen");
-            foreach(var (order, orderItems) in orders)
-            {
-                foreach(var pair in orderItems)
-                    pair.Value.PurchaseOrderLink.ID = order.ID;
-            }
-            Client.Save(orders.SelectMany(x => x.Item2.Values), "Created from Reservation Management screen");
-
-            var allocations = new List<PurchaseOrderItemAllocation>();
-            progress.Report($"Processing Breakups");
-            foreach(var (order, orderItems) in orders)
-            {
-                foreach(var (result, poi) in orderItems)
-                {
-                    foreach (var breakup in result.Breakups)
-                    {
-                        var alloc = new PurchaseOrderItemAllocation();
-                        alloc.Item.ID = poi.ID;
-                        alloc.Job.ID = breakup.JobID;
-                        alloc.JobRequisitionItem.ID = breakup.JobRequiItemID;
-                        alloc.Quantity = breakup.Quantity;
-                        allocations.Add(alloc);
-                    }
-                }
-            }
-            if (allocations.Count != 0)
-                Client.Save(allocations, "Created from Reservation Management Screen");
-        });
-        MessageWindow.ShowMessage($"The following orders were created:\n- {string.Join("\n- ",orders.Select(x=>x.Item1.PONumber))}", $"Created {orders.Count} orders");
+        window.CreateOrders("Reservation Management");
         return true;
         return true;
     }
     }
 
 

+ 0 - 1
prs.desktop/Panels/Reservation Management/ReservationManagementPanel.xaml.cs

@@ -555,7 +555,6 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
                 {
                 {
                     var orderItem = new PurchaseOrderItem();
                     var orderItem = new PurchaseOrderItem();
                     orderItem.Product.ID = item.Item.TreatmentProduct.ID;
                     orderItem.Product.ID = item.Item.TreatmentProduct.ID;
-                    orderItem.Job.ID = item.Item.JRI.Job.ID;
                     orderItem.TaxCode.ID = item.SupplierProduct.TaxCode.ID != Guid.Empty
                     orderItem.TaxCode.ID = item.SupplierProduct.TaxCode.ID != Guid.Empty
                         ? item.SupplierProduct.TaxCode.ID
                         ? item.SupplierProduct.TaxCode.ID
                         : item.Item.TreatmentProduct.TaxCode.ID;
                         : item.Item.TreatmentProduct.TaxCode.ID;

+ 3 - 4
prs.desktop/Panels/Reservation Management/ReservationManagementPurchasing.xaml.cs

@@ -62,8 +62,7 @@ public partial class ReservationManagementPurchasing : UserControl
         if(orderID != Guid.Empty)
         if(orderID != Guid.Empty)
         {
         {
             var _allocations = Client.Query(
             var _allocations = Client.Query(
-                new Filter<PurchaseOrderItemAllocation>(x => x.Item.PurchaseOrderLink.ID)
-                    .IsEqualTo(orderID),
+                new Filter<PurchaseOrderItemAllocation>(x => x.Item.PurchaseOrderLink.ID).IsEqualTo(orderID),
                 Columns.None<PurchaseOrderItemAllocation>().Add(x => x.ID).Add(x => x.JobRequisitionItem.ID))
                 Columns.None<PurchaseOrderItemAllocation>().Add(x => x.ID).Add(x => x.JobRequisitionItem.ID))
                 .ToObjects<PurchaseOrderItemAllocation>();
                 .ToObjects<PurchaseOrderItemAllocation>();
             foreach (var _allocation in _allocations)
             foreach (var _allocation in _allocations)
@@ -214,10 +213,12 @@ public partial class ReservationManagementPurchasing : UserControl
             if(item.PurchaseOrderItem is not null)
             if(item.PurchaseOrderItem is not null)
             {
             {
                 var jriPoi = new PurchaseOrderItemAllocation();
                 var jriPoi = new PurchaseOrderItemAllocation();
+                jriPoi.Job.ID = item.JobRequiItem.Job.ID;
                 jriPoi.JobRequisitionItem.ID = item.JobRequiItem.ID;
                 jriPoi.JobRequisitionItem.ID = item.JobRequiItem.ID;
                 jriPoi.Item.ID = item.PurchaseOrderItem.ID;
                 jriPoi.Item.ID = item.PurchaseOrderItem.ID;
                 jriPoi.Quantity = item.PurchaseOrderItem.Qty;
                 jriPoi.Quantity = item.PurchaseOrderItem.Qty;
                 jriPois.Add(jriPoi);
                 jriPois.Add(jriPoi);
+
                 item.POAllocation = jriPoi;
                 item.POAllocation = jriPoi;
                 jris.Add(item.JobRequiItem);
                 jris.Add(item.JobRequiItem);
             }
             }
@@ -275,8 +276,6 @@ public partial class ReservationManagementPurchasing : UserControl
             poItem.Dimensions.CopyFrom(jobRequisitionItem.Dimensions);
             poItem.Dimensions.CopyFrom(jobRequisitionItem.Dimensions);
             poItem.Style.ID = jobRequisitionItem.Style.ID;
             poItem.Style.ID = jobRequisitionItem.Style.ID;
             poItem.Style.Synchronise(jobRequisitionItem.Style);
             poItem.Style.Synchronise(jobRequisitionItem.Style);
-            poItem.Job.ID = jobRequisitionItem.Requisition.Job.ID;
-            poItem.Job.Synchronise(jobRequisitionItem.Requisition.Job);
             items.Add(poItem);
             items.Add(poItem);
 
 
             JobRequiItems.Add(new JobRequiItemLinking(jobRequisitionItem, poItem));
             JobRequiItems.Add(new JobRequiItemLinking(jobRequisitionItem, poItem));

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

@@ -18,6 +18,7 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Media.Imaging;
 using System.Windows.Shapes;
 using System.Windows.Shapes;
 using InABox.Configuration;
 using InABox.Configuration;
+using InABox.Clients;
 
 
 namespace PRSDesktop;
 namespace PRSDesktop;
 
 
@@ -138,4 +139,90 @@ public partial class StockForecastOrderScreen : Window, INotifyPropertyChanged
         settings.OrderingStrategy = (StockForecastOrderingStrategy)OrderStrategyBox.SelectedValue;
         settings.OrderingStrategy = (StockForecastOrderingStrategy)OrderStrategyBox.SelectedValue;
         new GlobalConfiguration<StockForecastOrderScreenSettings>().Save(settings);
         new GlobalConfiguration<StockForecastOrderScreenSettings>().Save(settings);
     }
     }
+
+    public void CreateOrders(string screenName)
+    {
+        var orders = new List<Tuple<PurchaseOrder, Dictionary<StockForecastOrderingResult,PurchaseOrderItem>>>();
+        Progress.ShowModal("Creating Orders", progress =>
+        {
+            int iOrder = 1;
+            foreach(var perSupplier in Results.GroupBy(x => x.Supplier.ID))
+            {
+                progress.Report($"Creating Orders ({iOrder++}/{Results.ToArray().Length})");
+                var order = new PurchaseOrder();
+                order.Description = $"Purchase Order created from {screenName} Screen";
+                order.RaisedBy.ID = App.EmployeeID;
+
+                LookupFactory.DoLookup<PurchaseOrder, Supplier, SupplierLink>(order, x => x.SupplierLink, perSupplier.Key);
+
+                var orderItems = new Dictionary<StockForecastOrderingResult,PurchaseOrderItem>();
+                var results = perSupplier.ToArray();
+                foreach(var item in results)
+                {
+                    var orderItem = new PurchaseOrderItem();
+                    orderItem.Product.ID = item.Item.Product.ID;
+                    orderItem.Style.ID = item.Item.Style.ID;
+                    orderItems[item] = orderItem;
+                }
+
+                LookupFactory.DoLookups<PurchaseOrderItem, Product, ProductLink>(
+                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Product.ID)),
+                    x => x.Product);
+                LookupFactory.DoLookups<PurchaseOrderItem, ProductStyle, ProductStyleLink>(
+                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Style.ID)),
+                    x => x.Style);
+                LookupFactory.DoLookups<PurchaseOrderItem, TaxCode, TaxCodeLink>(
+                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.TaxCode.ID)),
+                    x => x.TaxCode);
+
+                foreach(var item in results)
+                {
+                    var orderItem = orderItems[item];
+                    orderItem.Dimensions.CopyFrom(item.Item.Dimensions);
+                    orderItem.Qty = item.Quantity;
+                    orderItem.ForeignCurrencyCost = item.SupplierProduct.ForeignCurrencyPrice;
+                    orderItem.Cost = item.SupplierProduct.CostPrice;
+                }
+
+                orders.Add(new(order, orderItems));
+            }
+            
+            progress.Report($"Saving {orders.Count} Orders");
+            Client.Save(orders.Select(x => x.Item1), $"Created from {screenName} screen");
+            foreach(var (order, orderItems) in orders)
+            {
+                foreach(var pair in orderItems)
+                    pair.Value.PurchaseOrderLink.ID = order.ID;
+            }
+            Client.Save(orders.SelectMany(x => x.Item2.Values), $"Created from {screenName} screen");
+
+            var allocations = new List<PurchaseOrderItemAllocation>();
+            progress.Report($"Processing Breakups");
+            foreach(var (order, orderItems) in orders)
+            {
+                foreach(var (result, poi) in orderItems)
+                {
+                    foreach (var breakup in result.Breakups)
+                    {
+                        if(breakup.JobID == Guid.Empty)
+                        {
+                            // This is a general stock allocation, which doesn't get an allocation.
+                            continue;
+                        }
+
+                        var alloc = new PurchaseOrderItemAllocation();
+                        alloc.Item.ID = poi.ID;
+                        alloc.Job.ID = breakup.JobID;
+                        alloc.JobRequisitionItem.ID = breakup.JobRequiItemID;
+                        alloc.Quantity = breakup.Quantity;
+                        allocations.Add(alloc);
+                    }
+                }
+            }
+            if (allocations.Count != 0)
+                Client.Save(allocations, $"Created from {screenName} Screen");
+        });
+
+        MessageWindow.ShowMessage($"The following orders were created:\n- {string.Join("\n- ",orders.Select(x=>x.Item1.PONumber))}", $"Created {orders.Count} orders");
+    }
 }
 }

+ 0 - 2
prs.desktop/Panels/Stock Forecast/OrderScreen/StockForecastOrderingGrid.cs

@@ -434,7 +434,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
 
 
     private void CalculateQuantities(bool recreateItems)
     private void CalculateQuantities(bool recreateItems)
     {
     {
-        
         SetObserving(false);
         SetObserving(false);
 
 
         if (recreateItems)
         if (recreateItems)
@@ -461,7 +460,6 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
                     }
                     }
                 }
                 }
                 Items.Add(item);
                 Items.Add(item);
-
             }
             }
         }
         }
 
 

+ 7 - 81
prs.desktop/Panels/Stock Forecast/StockForecastGrid.cs

@@ -835,8 +835,12 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
                 foreach(var mvt in movements.Rows)
                 foreach(var mvt in movements.Rows)
                 {
                 {
                     var item = GetItem(GetKey(mvt));
                     var item = GetItem(GetKey(mvt));
-                
-                    item.AddJobBOM(mvt.Get<StockMovement, Guid>(x => x.Job.ID), mvt.Get<StockMovement, double>(x => x.Units));
+
+                    var jobID = mvt.Get<StockMovement, Guid>(x => x.Job.ID);
+                    if(jobID != Guid.Empty)
+                    {
+                        item.AddJobBOM(jobID, mvt.Get<StockMovement, double>(x => x.Units));
+                    }
                 }
                 }
 
 
                 _supplierProducts = results.GetArray<SupplierProduct>();
                 _supplierProducts = results.GetArray<SupplierProduct>();
@@ -980,88 +984,10 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
         {
         {
             return false;
             return false;
         }
         }
-        
-        var orders = new List<Tuple<PurchaseOrder, Dictionary<StockForecastOrderingResult,PurchaseOrderItem>>>();
-        Progress.ShowModal("Creating Orders", progress =>
-        {
-            int iOrder = 1;
-            foreach(var perSupplier in window.Results.GroupBy(x => x.Supplier.ID))
-            {
-                progress.Report($"Creating Orders ({iOrder++}/{window.Results.ToArray().Length})");
-                var order = new PurchaseOrder();
-                order.Description = "Purchase Order created from Stock Forecast Screen";
-                order.RaisedBy.ID = App.EmployeeID;
-
-                LookupFactory.DoLookup<PurchaseOrder, Supplier, SupplierLink>(order, x => x.SupplierLink, perSupplier.Key);
-
-                var orderItems = new Dictionary<StockForecastOrderingResult,PurchaseOrderItem>();
-                var results = perSupplier.ToArray();
-                foreach(var item in results)
-                {
-                    var orderItem = new PurchaseOrderItem();
-                    orderItem.Product.ID = item.Item.Product.ID;
-                    orderItem.Style.ID = item.Item.Style.ID;
-                    orderItems[item] = orderItem;
-                }
-
-                LookupFactory.DoLookups<PurchaseOrderItem, Product, ProductLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Product.ID)),
-                    x => x.Product);
-                LookupFactory.DoLookups<PurchaseOrderItem, ProductStyle, ProductStyleLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Style.ID)),
-                    x => x.Style);
-                LookupFactory.DoLookups<PurchaseOrderItem, Job, JobLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Job.ID)),
-                    x => x.Job);
-                LookupFactory.DoLookups<PurchaseOrderItem, TaxCode, TaxCodeLink>(
-                    orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.TaxCode.ID)),
-                    x => x.TaxCode);
-
-                foreach(var item in results)
-                {
-                    var orderItem = orderItems[item];
-                    orderItem.Dimensions.CopyFrom(item.Item.Dimensions);
-                    orderItem.Qty = item.Quantity;
-                    orderItem.ForeignCurrencyCost = item.SupplierProduct.ForeignCurrencyPrice;
-                    orderItem.Cost = item.SupplierProduct.CostPrice;
-                }
-
-                orders.Add(new(order, orderItems));
-            }
-            
-            progress.Report($"Saving {orders.Count} Orders");
-            Client.Save(orders.Select(x => x.Item1), "Created from Stock Forecast screen");
-            foreach(var (order, orderItems) in orders)
-            {
-                foreach(var pair in orderItems)
-                    pair.Value.PurchaseOrderLink.ID = order.ID;
-            }
-            Client.Save(orders.SelectMany(x => x.Item2.Values), "Created from Stock Forecast screen");
-
-            List<PurchaseOrderItemAllocation> allocations = new();
-            progress.Report($"Processing Breakups");
-            foreach(var (order, orderItems) in orders)
-            {
-                foreach(var pair in orderItems)
-                {
-                    foreach (var breakup in pair.Key.Breakups)
-                    {
-                        var alloc = new PurchaseOrderItemAllocation();
-                        alloc.Item.ID = pair.Value.ID;
-                        alloc.Job.ID = breakup.Item1;
-                        alloc.Quantity = breakup.Item4;
-                        allocations.Add(alloc);
-                    }
-                }
-            }
-            if (allocations.Any())
-                Client.Save(allocations,"Created from Stock Forecast Screen");
-        });
-        
+        window.CreateOrders("Stock Forecast");
         
         
         SelectedForOrder.Clear();
         SelectedForOrder.Clear();
         OrderButton.IsEnabled = false;
         OrderButton.IsEnabled = false;
-        MessageWindow.ShowMessage($"The following orders were created:\n- {string.Join("\n- ",orders.Select(x=>x.Item1.PONumber))}", $"Created {orders.Count} orders");
         return true;
         return true;
     }
     }