|  | @@ -12,6 +12,7 @@ using InABox.Clients;
 | 
	
		
			
				|  |  |  using InABox.Wpf;
 | 
	
		
			
				|  |  |  using Columns = InABox.Core.Columns;
 | 
	
		
			
				|  |  |  using PRSDesktop.Panels.ReservationManagement.TreatmentPO;
 | 
	
		
			
				|  |  | +using Syncfusion.UI.Xaml.Grid;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace PRSDesktop;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -22,11 +23,11 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      private ReservationManagementGlobalSettings _globalSettings = null!; // Initialised in Setup()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //private List<PurchaseOrder> PurchaseOrders = new List<PurchaseOrder>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      public ReservationManagementPanel()
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          InitializeComponent();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        PanelLink = new(this);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private void Reconfigure()
 | 
	
	
		
			
				|  | @@ -35,38 +36,6 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |          OnUpdateDataModel?.Invoke(SectionName, DataModel(Selection.None));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // private void SelectNewPurchaseOrder()
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     SelectDetailButton(AddPOButton);
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     reserveCol.Width = new System.Windows.GridLength(0);
 | 
	
		
			
				|  |  | -    //     purchaseCol.Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     if (Mode != PanelMode.Purchase)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         Mode = PanelMode.Purchase;
 | 
	
		
			
				|  |  | -    //         Reconfigure();
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     purchasing.LoadFromRequiLine(Guid.Empty);
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    // private void SelectPurchaseOrder(Button button, PurchaseOrder order)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     SelectDetailButton(button);
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     reserveCol.Width = new System.Windows.GridLength(0);
 | 
	
		
			
				|  |  | -    //     purchaseCol.Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     if (Mode != PanelMode.Purchase)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         Mode = PanelMode.Purchase;
 | 
	
		
			
				|  |  | -    //         Reconfigure();
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     purchasing.LoadFromRequiLine(order.ID);
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      public bool IsReady { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public string SectionName => "Job Requisitions";
 | 
	
	
		
			
				|  | @@ -80,29 +49,6 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (Security.IsAllowed<CanCreateTreatmentPO>())
 | 
	
		
			
				|  |  |            host.CreatePanelAction(new PanelAction("Treatment PO", PRSDesktop.Resources.purchase, TreatmentPO_Click));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // if(Mode == PanelMode.Purchase && SplitPanel.IsDetailVisible())
 | 
	
		
			
				|  |  | -        // {
 | 
	
		
			
				|  |  | -        //     var sectionName = SupplierPurchaseOrderPanel.SectionName;
 | 
	
		
			
				|  |  | -        //     var dataModel = SupplierPurchaseOrderPanel.DataModel(Array.Empty<Guid>());
 | 
	
		
			
				|  |  | -        //     var reports = ReportUtils.LoadReports(sectionName, dataModel);
 | 
	
		
			
				|  |  | -        //     foreach(var report in reports)
 | 
	
		
			
				|  |  | -        //     {
 | 
	
		
			
				|  |  | -        //         host.CreateReport(PanelHost.CreateReportAction(report, (selection) =>
 | 
	
		
			
				|  |  | -        //         {
 | 
	
		
			
				|  |  | -        //             Guid[] ids;
 | 
	
		
			
				|  |  | -        //             if(selection == Selection.None)
 | 
	
		
			
				|  |  | -        //             {
 | 
	
		
			
				|  |  | -        //                 ids = Array.Empty<Guid>();
 | 
	
		
			
				|  |  | -        //             }
 | 
	
		
			
				|  |  | -        //             else
 | 
	
		
			
				|  |  | -        //             {
 | 
	
		
			
				|  |  | -        //                 ids = PurchaseOrders.Select(x => x.ID).ToArray();
 | 
	
		
			
				|  |  | -        //             }
 | 
	
		
			
				|  |  | -        //             return SupplierPurchaseOrderPanel.DataModel(ids);
 | 
	
		
			
				|  |  | -        //         }));
 | 
	
		
			
				|  |  | -        //     }
 | 
	
		
			
				|  |  | -        // }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private void ConfigSettingsClick(PanelAction obj)
 | 
	
	
		
			
				|  | @@ -143,144 +89,31 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void Setup()
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        //SelectReserved();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          _globalSettings = new GlobalConfiguration<ReservationManagementGlobalSettings>().Load();
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  |          JobRequiItems.DueDateAlert = _globalSettings.DueDateAlert;
 | 
	
		
			
				|  |  |          JobRequiItems.DueDateWarning = _globalSettings.DueDateWarning;
 | 
	
		
			
				|  |  |          JobRequiItems.CompanyDefaultStyle = _globalSettings.ProductStyle;
 | 
	
		
			
				|  |  |          JobRequiItems.Refresh(true, false);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -        //substitutions.FreeStockOnly = JobRequiItems.UserSettings.SubstituteFreeStockOnly;
 | 
	
		
			
				|  |  | -        //substitutions.UpdateStyle = JobRequiItems.UserSettings.SubstituteUpdateStyle;
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        //holdings.OnHoldingsReviewRefresh += Holdings_OnHoldingsReviewRefresh;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        //purchasing.OnPurchaseOrderSaved += Refresh;
 | 
	
		
			
				|  |  | +    // This class is to manage a reference back to this current panel; this link class is referred to by the SubPanels when
 | 
	
		
			
				|  |  | +    // a treatment PO is created; but we don't want the panel to continue to be referenced once it has shutdown, preventing it
 | 
	
		
			
				|  |  | +    // being garbage collected. Hence, when we shutdown, we set the 'Panel' property to 'null', removing the reference to this panel, allowing
 | 
	
		
			
				|  |  | +    // it to be garbage collected.
 | 
	
		
			
				|  |  | +    private class PanelWrapper(ReservationManagementPanel panel)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public ReservationManagementPanel? Panel { get; set; } = panel;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // private void OnJobRequiItemSelected(object sender, DynamicGridSelectionEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     if (SplitPanel.IsDetailVisible())
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         holdings.Item = e.Rows?.FirstOrDefault()?.ToObject<JobRequisitionItem>();
 | 
	
		
			
				|  |  | -    //         RefreshPurchaseOrderButtons();
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private void RefreshPurchaseOrderButtons()
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     var requiIDs = JobRequiItems.SelectedRows
 | 
	
		
			
				|  |  | -    //         .Select(x => x.Get<JobRequisitionItem, Guid>(x => x.ID))
 | 
	
		
			
				|  |  | -    //         .ToArray();
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     var pos = Client.Query(
 | 
	
		
			
				|  |  | -    //         new Filter<PurchaseOrder>(x => x.ID).InQuery(
 | 
	
		
			
				|  |  | -    //             new Filter<PurchaseOrderItemAllocation>(x => x.JobRequisitionItem.ID)
 | 
	
		
			
				|  |  | -    //                 .InList(requiIDs),
 | 
	
		
			
				|  |  | -    //             x => x.Item.PurchaseOrderLink.ID),
 | 
	
		
			
				|  |  | -    //         Columns.None<PurchaseOrder>().Add(x => x.ID)
 | 
	
		
			
				|  |  | -    //             .Add(x => x.PONumber))
 | 
	
		
			
				|  |  | -    //         .ToObjects<PurchaseOrder>().ToList();
 | 
	
		
			
				|  |  | -    //     PurchaseOrders = pos;
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    //     PurchaseOrderButtons.Children.Clear();
 | 
	
		
			
				|  |  | -    //     var buttons = new List<(Button btn, PurchaseOrder po)>();
 | 
	
		
			
				|  |  | -    //     foreach (var po in pos)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         var button = new Button
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             Content = po.PONumber,
 | 
	
		
			
				|  |  | -    //             Height = 30,
 | 
	
		
			
				|  |  | -    //             FontWeight = FontWeights.DemiBold,
 | 
	
		
			
				|  |  | -    //             BorderBrush = new SolidColorBrush(Colors.DarkGray),
 | 
	
		
			
				|  |  | -    //             BorderThickness = new Thickness(1.25),
 | 
	
		
			
				|  |  | -    //             Margin = new Thickness(2, 0, 0, 2),
 | 
	
		
			
				|  |  | -    //             Padding = new Thickness(13, 3, 13, 3)
 | 
	
		
			
				|  |  | -    //         };
 | 
	
		
			
				|  |  | -    //         button.Click += (o, e) =>
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             SelectPurchaseOrder(button, po);
 | 
	
		
			
				|  |  | -    //         };
 | 
	
		
			
				|  |  | -    //         buttons.Add((button, po));
 | 
	
		
			
				|  |  | -    //         PurchaseOrderButtons.Children.Add(button);
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //     if (Mode == PanelMode.Purchase)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         if (buttons.Count == 0)
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             SelectNewPurchaseOrder();
 | 
	
		
			
				|  |  | -    //         }
 | 
	
		
			
				|  |  | -    //         else
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             var btn = buttons[0];
 | 
	
		
			
				|  |  | -    //             SelectPurchaseOrder(btn.btn, btn.po);
 | 
	
		
			
				|  |  | -    //         }
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //     else if (Mode == PanelMode.Reserve)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         SelectReserved();
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // private void Holdings_OnHoldingsReviewRefresh()
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     Refresh();
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private void CheckSaved(CancelEventArgs cancel)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     if (!SplitPanel.IsDetailVisible() || !purchasing.EditorChanged)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         return;
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //     var result = MessageWindow.ShowYesNoCancel("You have changes that have not been saved; do you wish to save these changes?", "Save Changes?");
 | 
	
		
			
				|  |  | -    //     if (result == MessageWindowResult.Yes)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         purchasing.Editor.SaveItem(cancel);
 | 
	
		
			
				|  |  | -    //         if (!cancel.Cancel)
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             MessageWindow.ShowMessage("Purchase Order saved.", "Success");
 | 
	
		
			
				|  |  | -    //         }
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    //     else if (result == MessageWindowResult.Cancel)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         cancel.Cancel = true;
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | +    private PanelWrapper PanelLink;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void Shutdown(CancelEventArgs? cancel)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        // if(cancel is not null && purchasing.EditorChanged)
 | 
	
		
			
				|  |  | -        // {
 | 
	
		
			
				|  |  | -        //     CheckSaved(cancel);
 | 
	
		
			
				|  |  | -        // }
 | 
	
		
			
				|  |  | +        PanelLink.Panel = null;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // private void ReserveStock_Clicked(object sender, System.Windows.RoutedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     SelectReserved();
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // private void Purchasing_Drop(object sender, DragEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     if(DynamicGridUtils.TryGetDropData(e, out var type, out var table))
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         if(type == typeof(JobRequisitionItem))
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             purchasing.DropItems(table.Rows);
 | 
	
		
			
				|  |  | -    //         }
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private void AddPOButton_Click(object sender, RoutedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     SelectNewPurchaseOrder();
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | +    #region TreatmentPO
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private void TreatmentPO_Click(PanelAction action)
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -470,12 +303,12 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |          var window = new ReservationManagementTreatmentOrderScreen(items);
 | 
	
		
			
				|  |  |          if(window.ShowDialog() == true)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var orders = new List<Tuple<PurchaseOrder, List<(PurchaseOrderItem, JobRequisitionItemLink)>>>();
 | 
	
		
			
				|  |  | +            var orders = new List<Tuple<PurchaseOrder, List<(PurchaseOrderItem, JobRequisitionItemLink, StockForecastTreatmentOrderingResult)>>>();
 | 
	
		
			
				|  |  |              var movements = new List<StockMovement>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var results = window.Results.GroupBy(x => x.Supplier.ID).Select(x => (x.Key, x.ToArray())).ToArray();
 | 
	
		
			
				|  |  | +            var results = window.Results.GroupBy(x => x.Supplier.ID).ToDictionary(x => x.Key, x => x.ToArray());
 | 
	
		
			
				|  |  |              var suppliers = Client.Query(
 | 
	
		
			
				|  |  | -                new Filter<Supplier>(x => x.ID).InList(results.ToArray(x => x.Key)),
 | 
	
		
			
				|  |  | +                new Filter<Supplier>(x => x.ID).InList(results.Keys.ToArray()),
 | 
	
		
			
				|  |  |                  Columns.None<Supplier>().Add(x => x.ID).Add(x => x.DefaultLocation.ID))
 | 
	
		
			
				|  |  |                  .ToObjects<Supplier>()
 | 
	
		
			
				|  |  |                  .ToDictionary(x => x.ID);
 | 
	
	
		
			
				|  | @@ -490,7 +323,7 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  LookupFactory.DoLookup<PurchaseOrder, Supplier, SupplierLink>(order, x => x.SupplierLink, supplierID);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                var orderItems = new List<(PurchaseOrderItem, JobRequisitionItemLink)>();
 | 
	
		
			
				|  |  | +                var orderItems = new List<(PurchaseOrderItem, JobRequisitionItemLink, StockForecastTreatmentOrderingResult)>();
 | 
	
		
			
				|  |  |                  foreach(var item in perSupplier)
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      var orderItem = new PurchaseOrderItem();
 | 
	
	
		
			
				|  | @@ -498,7 +331,7 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |                      orderItem.TaxCode.ID = item.SupplierProduct.TaxCode.ID != Guid.Empty
 | 
	
		
			
				|  |  |                          ? item.SupplierProduct.TaxCode.ID
 | 
	
		
			
				|  |  |                          : item.Item.TreatmentProduct.TaxCode.ID;
 | 
	
		
			
				|  |  | -                    orderItems.Add((orderItem, item.Item.JRI));
 | 
	
		
			
				|  |  | +                    orderItems.Add((orderItem, item.Item.JRI, item));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  LookupFactory.DoLookups<PurchaseOrderItem, Product, ProductLink>(
 | 
	
	
		
			
				|  | @@ -585,153 +418,161 @@ public partial class ReservationManagementPanel : UserControl, IPanel<JobRequisi
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Client.Save(orders.Select(x => x.Item1), "Treatment PO created from Reservation Management screen");
 | 
	
		
			
				|  |  | -            foreach(var (order, orderItems) in orders)
 | 
	
		
			
				|  |  | +            var grid = new SupplierPurchaseOrders();
 | 
	
		
			
				|  |  | +            var windows = new List<ReservationManagementPanelTreatmentPOWindow>();
 | 
	
		
			
				|  |  | +            foreach(var order in orders)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var perSupplier = results.GetValueOrDefault(order.Item1.SupplierLink.ID) ?? [];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var editorWindow = new ReservationManagementPanelTreatmentPOWindow(grid, order, perSupplier, PanelLink);
 | 
	
		
			
				|  |  | +                editorWindow.Form.Show();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                ISubPanelHost.Global.AddSubPanel(editorWindow.Form);
 | 
	
		
			
				|  |  | +                windows.Add(editorWindow);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            grid.OnAfterSave += (editor, items) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var order = items.FirstOrDefault();
 | 
	
		
			
				|  |  | +                var window = windows.FirstOrDefault(x => x.Order == order);
 | 
	
		
			
				|  |  | +                window?.AfterSave();
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            JobRequiItems.SelectedRows = [];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private class ReservationManagementPanelTreatmentPOWindow
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public PurchaseOrder Order { get; private set; }
 | 
	
		
			
				|  |  | +        StockForecastTreatmentOrderingResult[] ResultItems;
 | 
	
		
			
				|  |  | +        PanelWrapper Panel;
 | 
	
		
			
				|  |  | +        public DynamicEditorForm Form { get; private set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public ReservationManagementPanelTreatmentPOWindow(
 | 
	
		
			
				|  |  | +            SupplierPurchaseOrders grid,
 | 
	
		
			
				|  |  | +            Tuple<PurchaseOrder, List<(PurchaseOrderItem, JobRequisitionItemLink, StockForecastTreatmentOrderingResult)>> order,
 | 
	
		
			
				|  |  | +            StockForecastTreatmentOrderingResult[] resultItems,
 | 
	
		
			
				|  |  | +            PanelWrapper panel
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Form = new DynamicEditorForm
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Title = "Edit Treatment PO"
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Order = order.Item1;
 | 
	
		
			
				|  |  | +            ResultItems = resultItems;
 | 
	
		
			
				|  |  | +            Panel = panel;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Form.Form.DoChanged();
 | 
	
		
			
				|  |  | +            Form.SetLayoutType<VerticalDynamicEditorGridLayout>();
 | 
	
		
			
				|  |  | +            grid.InitialiseEditorForm(Form, [order.Item1], type =>
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                foreach(var item in orderItems)
 | 
	
		
			
				|  |  | +                if(type == typeof(PurchaseOrderItem))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    item.Item1.PurchaseOrderLink.ID = order.ID;
 | 
	
		
			
				|  |  | +                    var table = new CoreTable();
 | 
	
		
			
				|  |  | +                    table.LoadColumns(typeof(PurchaseOrderItem));
 | 
	
		
			
				|  |  | +                    table.LoadRows(order.Item2.Select(x => x.Item1));
 | 
	
		
			
				|  |  | +                    return table;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return null;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }, true);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var oneToManyPage = Form.Pages?.OfType<SupplierPurchaseOrderItemOneToMany>().FirstOrDefault();
 | 
	
		
			
				|  |  | +            if(oneToManyPage is null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Logger.Send(LogType.Error, "", "Could not find POI page when saving treatment PO");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                oneToManyPage.OnCustomiseEditor += (form, items, column, editor) =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    if(column.ColumnName == $"{nameof(PurchaseOrderItem.Product)}.{nameof(PurchaseOrderItem.Product.ID)}")
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        editor.Editable = editor.Editable.Combine(Editable.Disabled);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                oneToManyPage.ColumnsLoaded += (o, args) =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var column = args.VisibleColumns.FirstOrDefault(x => x.ColumnName == $"{nameof(PurchaseOrderItem.Product)}.{nameof(PurchaseOrderItem.Product.ID)}");
 | 
	
		
			
				|  |  | +                    if(column is not null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        column.Editor.Editable = column.Editor.Editable.Combine(Editable.Disabled);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +                oneToManyPage.Simplified = true;
 | 
	
		
			
				|  |  | +                oneToManyPage.Reconfigure(options =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    options.AddRows = false;
 | 
	
		
			
				|  |  | +                    options.DeleteRows = false;
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                foreach(var (i, item) in order.Item2.WithIndex())
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var jriPOI = new PurchaseOrderItemAllocation();
 | 
	
		
			
				|  |  | +                    jriPOI.Job.ID = item.Item2.Job.ID;
 | 
	
		
			
				|  |  | +                    jriPOI.JobRequisitionItem.ID = item.Item2.ID;
 | 
	
		
			
				|  |  | +                    jriPOI.Item.ID = item.Item1.ID;
 | 
	
		
			
				|  |  | +                    jriPOI.Quantity = item.Item1.Qty;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    oneToManyPage.Allocations.Add(new(oneToManyPage.Items[i], jriPOI));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            Client.Save(orders.SelectMany(x => x.Item2).Select(x => x.Item1), "Treatment PO created from Reservation Management screen");
 | 
	
		
			
				|  |  | -            Client.Save(orders.SelectMany(x => x.Item2).Select(x =>
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public void AfterSave()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var locationID = Client.Query(
 | 
	
		
			
				|  |  | +                new Filter<Supplier>(x => x.ID).IsEqualTo(Order.SupplierLink.ID),
 | 
	
		
			
				|  |  | +                Columns.None<Supplier>().Add(x => x.DefaultLocation.ID))
 | 
	
		
			
				|  |  | +                .Rows.FirstOrDefault()?.Get<Supplier, Guid>(x => x.DefaultLocation.ID) ?? Guid.Empty;
 | 
	
		
			
				|  |  | +            if (locationID != Guid.Empty)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var jriPOI = new PurchaseOrderItemAllocation();
 | 
	
		
			
				|  |  | -                jriPOI.Job.ID = x.Item2.Job.ID;
 | 
	
		
			
				|  |  | -                jriPOI.JobRequisitionItem.ID = x.Item2.ID;
 | 
	
		
			
				|  |  | -                jriPOI.Item.ID = x.Item1.ID;
 | 
	
		
			
				|  |  | -                jriPOI.Quantity = x.Item1.Qty;
 | 
	
		
			
				|  |  | -                return jriPOI;
 | 
	
		
			
				|  |  | -            }), "Treatment PO created from Reservation Management screen");
 | 
	
		
			
				|  |  | +                var movements = new List<StockMovement>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Client.Save(movements, "Treatment PO created from Reservation Management screen");
 | 
	
		
			
				|  |  | +                foreach(var item in ResultItems)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var tOut = new StockMovement();
 | 
	
		
			
				|  |  | +                    tOut.Job.CopyFrom(item.Item.Job);
 | 
	
		
			
				|  |  | +                    tOut.Style.CopyFrom(item.Item.Style);
 | 
	
		
			
				|  |  | +                    tOut.Location.CopyFrom(item.Item.Location);
 | 
	
		
			
				|  |  | +                    tOut.Product.CopyFrom(item.Item.Product);
 | 
	
		
			
				|  |  | +                    tOut.Dimensions.CopyFrom(item.Item.Dimensions);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    tOut.Employee.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | +                    tOut.Date = DateTime.Now;
 | 
	
		
			
				|  |  | +                    tOut.Issued = item.Quantity;
 | 
	
		
			
				|  |  | +                    tOut.Type = StockMovementType.TransferOut;
 | 
	
		
			
				|  |  | +                    tOut.JobRequisitionItem.CopyFrom(item.Item.JRI);
 | 
	
		
			
				|  |  | +                    tOut.Notes = "Stock movement for treatment purchase order created from Reservation Management";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var tIn = tOut.CreateMovement();
 | 
	
		
			
				|  |  | +                    tIn.Transaction = tOut.Transaction;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    tIn.Style.CopyFrom(item.Item.JRI.Style);
 | 
	
		
			
				|  |  | +                    tIn.Location.ID = locationID;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    tIn.Employee.ID = App.EmployeeID;
 | 
	
		
			
				|  |  | +                    tIn.Date = tOut.Date;
 | 
	
		
			
				|  |  | +                    tIn.Received = item.Quantity;
 | 
	
		
			
				|  |  | +                    tIn.Type = StockMovementType.TransferIn;
 | 
	
		
			
				|  |  | +                    tIn.JobRequisitionItem.CopyFrom(item.Item.JRI);
 | 
	
		
			
				|  |  | +                    tIn.Notes = "Stock movement for treatment purchase order created from Reservation Management";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    movements.Add(tOut);
 | 
	
		
			
				|  |  | +                    movements.Add(tIn);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            MessageWindow.ShowMessage(
 | 
	
		
			
				|  |  | -                $"{orders.Count} treatment purchase order{(orders.Count != 1 ? "s" : "")} {(doIssue ? "issued" : "raised")}:\n" +
 | 
	
		
			
				|  |  | -                $"- {string.Join(',', orders.Select(x => x.Item1.PONumber))}",
 | 
	
		
			
				|  |  | -                "Success");
 | 
	
		
			
				|  |  | +                Client.Save(movements, "Treatment PO created from Reservation Management screen");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            JobRequiItems.SelectedRows = [];
 | 
	
		
			
				|  |  | -            JobRequiItems.Refresh(false, true);
 | 
	
		
			
				|  |  | +            var panel = Panel.Panel;
 | 
	
		
			
				|  |  | +            panel?.JobRequiItems.Refresh(false, true);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     JobRequiItems.Reconfigure();
 | 
	
		
			
				|  |  | -    //     if(CurrentView != e.View)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         CurrentView = e.View;
 | 
	
		
			
				|  |  | -    //         if (e.View != DynamicSplitPanelView.Master)
 | 
	
		
			
				|  |  | -    //         {
 | 
	
		
			
				|  |  | -    //             Refresh();
 | 
	
		
			
				|  |  | -    //         }
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    //private bool _updatingSubstitution = false;
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    // private void JobRequiItems_OnOnSelectItem(object sender, DynamicGridSelectionEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -        // _updatingSubstitution = true;
 | 
	
		
			
				|  |  | -        // try
 | 
	
		
			
				|  |  | -        // {
 | 
	
		
			
				|  |  | -        //     var row = Mode == PanelMode.Reserve && e.Rows?.Length == 1
 | 
	
		
			
				|  |  | -        //         ? e.Rows.FirstOrDefault()
 | 
	
		
			
				|  |  | -        //         : null;
 | 
	
		
			
				|  |  | -        //     var visible =
 | 
	
		
			
				|  |  | -        //         row != null
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.InStock).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.TotalOrders).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.OnOrder).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.TreatmentRequired).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.TreatmentOnOrder).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.Allocated).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.PickRequested).IsEffectivelyEqual(0.0)
 | 
	
		
			
				|  |  | -        //         && row.Get<JobRequisitionItem, double>(x => x.Issued).IsEffectivelyEqual(0.0);
 | 
	
		
			
				|  |  | -        //
 | 
	
		
			
				|  |  | -        //     substitutions.SizeChanged -= Substitutions_OnSizeChanged;
 | 
	
		
			
				|  |  | -        //     SubstitutionSplitterRow.Height = visible ? GridLength.Auto : new GridLength(0.0);
 | 
	
		
			
				|  |  | -        //     SubstitutionRow.Height = visible ? new GridLength(JobRequiItems.UserSettings.SubstitutionGridHeight) : new GridLength(0.0);
 | 
	
		
			
				|  |  | -        //     SubstitutionButtonRow.Height = visible ? GridLength.Auto : new GridLength(0.0);
 | 
	
		
			
				|  |  | -        //     substitutions.SizeChanged += Substitutions_OnSizeChanged;
 | 
	
		
			
				|  |  | -        //     if (visible)
 | 
	
		
			
				|  |  | -        //         substitutions.JRI = row?.ToObject<JobRequisitionItem>() ?? new JobRequisitionItem();
 | 
	
		
			
				|  |  | -        //     SubstitutionFreeStock.IsChecked = JobRequiItems.UserSettings.SubstituteFreeStockOnly;
 | 
	
		
			
				|  |  | -        //     SubstitutionUpdateStyle.IsChecked = JobRequiItems.UserSettings.SubstituteUpdateStyle;
 | 
	
		
			
				|  |  | -        // }
 | 
	
		
			
				|  |  | -        // finally
 | 
	
		
			
				|  |  | -        // {
 | 
	
		
			
				|  |  | -        //     _updatingSubstitution = false;
 | 
	
		
			
				|  |  | -        // }
 | 
	
		
			
				|  |  | -    //}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private void SubstitutionFreeStock_OnChecked(object sender, RoutedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     if (_updatingSubstitution)
 | 
	
		
			
				|  |  | -    //         return;
 | 
	
		
			
				|  |  | -    //     substitutions.FreeStockOnly = SubstitutionFreeStock.IsChecked == true;
 | 
	
		
			
				|  |  | -    //     JobRequiItems.UserSettings.SubstituteFreeStockOnly = substitutions.FreeStockOnly;
 | 
	
		
			
				|  |  | -    //     new UserConfiguration<ReservationManagementUserSettings>().Save(JobRequiItems.UserSettings);
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // private void SubstitutionUpdateStyle_OnChecked(object sender, RoutedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     if (_updatingSubstitution)
 | 
	
		
			
				|  |  | -    //         return;
 | 
	
		
			
				|  |  | -    //     substitutions.UpdateStyle = SubstitutionUpdateStyle.IsChecked == true;
 | 
	
		
			
				|  |  | -    //     JobRequiItems.UserSettings.SubstituteUpdateStyle = substitutions.UpdateStyle;
 | 
	
		
			
				|  |  | -    //     new UserConfiguration<ReservationManagementUserSettings>().Save(JobRequiItems.UserSettings);
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private bool _sizeChanging = false;
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // private void Substitutions_OnSizeChanged(object sender, SizeChangedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     _sizeChanging = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     base.OnPreviewMouseUp(e);
 | 
	
		
			
				|  |  | -    //     if (_sizeChanging)
 | 
	
		
			
				|  |  | -    //     {
 | 
	
		
			
				|  |  | -    //         _sizeChanging = false;
 | 
	
		
			
				|  |  | -    //         JobRequiItems.UserSettings.SubstitutionGridHeight = substitutions.ActualHeight;
 | 
	
		
			
				|  |  | -    //         new UserConfiguration<ReservationManagementUserSettings>().Save(JobRequiItems.UserSettings);
 | 
	
		
			
				|  |  | -    //     }
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // private void ChangeProduct_OnClick(object sender, RoutedEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     var _holding = substitutions.SelectedRows?.FirstOrDefault()?.ToObject<StockHolding>();
 | 
	
		
			
				|  |  | -    //     var _jrirow = JobRequiItems.SelectedRows.FirstOrDefault();
 | 
	
		
			
				|  |  | -    //     if (_holding == null || _jrirow == null)
 | 
	
		
			
				|  |  | -    //         return;
 | 
	
		
			
				|  |  | -    //     var _jri = _jrirow.ToObject<JobRequisitionItem>();
 | 
	
		
			
				|  |  | -    //     _jri.Dimensions.CopyFrom(_holding.Dimensions, true);
 | 
	
		
			
				|  |  | -    //     if (substitutions.UpdateStyle)
 | 
	
		
			
				|  |  | -    //         _jri.Style.CopyFrom(_holding.Style);
 | 
	
		
			
				|  |  | -    //     Client.Save(_jri,"Substituted by Requisition Management Screen");
 | 
	
		
			
				|  |  | -    //     var _xferout = _holding.CreateMovement();
 | 
	
		
			
				|  |  | -    //     _xferout.Issued = Math.Min(_holding.Available, _jri.Qty);
 | 
	
		
			
				|  |  | -    //     _xferout.Notes = "Substituted by Requisition Management Screen";
 | 
	
		
			
				|  |  | -    //     _xferout.Transaction = Guid.NewGuid();
 | 
	
		
			
				|  |  | -    //     _xferout.Type = StockMovementType.TransferOut;
 | 
	
		
			
				|  |  | -    //     var _xferin = _holding.CreateMovement();
 | 
	
		
			
				|  |  | -    //     _xferin.JobRequisitionItem.CopyFrom(_jri);
 | 
	
		
			
				|  |  | -    //     _xferin.Job.CopyFrom(_jri.Job);
 | 
	
		
			
				|  |  | -    //     _xferin.Received = Math.Min(_holding.Available, _jri.Qty);
 | 
	
		
			
				|  |  | -    //     _xferin.Notes = "Substituted by Requisition Management Screen";
 | 
	
		
			
				|  |  | -    //     _xferin.Transaction = _xferout.Transaction;
 | 
	
		
			
				|  |  | -    //     _xferin.Type = StockMovementType.TransferIn;
 | 
	
		
			
				|  |  | -    //     Client.Save(new[] { _xferout, _xferin}, "Substituted by Requisition Management Screen");
 | 
	
		
			
				|  |  | -    //     JobRequiItems.Refresh(false,true);
 | 
	
		
			
				|  |  | -    //     // Allocate Stock (transfer if required)
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // private void Substitutions_OnOnSelectItem(object sender, DynamicGridSelectionEventArgs e)
 | 
	
		
			
				|  |  | -    // {
 | 
	
		
			
				|  |  | -    //     ChangeProduct.IsEnabled = e.Rows?.SingleOrDefault() != null;
 | 
	
		
			
				|  |  | -    // }
 | 
	
		
			
				|  |  | +    #endregion
 | 
	
		
			
				|  |  |  }
 |