Bladeren bron

Added subpanel host stuff.

Kenric Nugteren 8 maanden geleden
bovenliggende
commit
eb34680de4

+ 4 - 2
prs.desktop/MainWindow.xaml.cs

@@ -82,7 +82,6 @@ public partial class MainWindow : IPanelHostControl
 {
     //private const int WM_LBUTTONDOWN = 0x201;
 
-
     private static PipeServer<string>? _client;
 
     private IRpcClientTransport? _transport;
@@ -139,7 +138,6 @@ public partial class MainWindow : IPanelHostControl
 
     private PanelHost PanelHost;
 
-
     public MainWindow()
     {
         PanelHost = new PanelHost(this);
@@ -2472,6 +2470,10 @@ public partial class MainWindow : IPanelHostControl
             return;
         }*/
         PanelHost.UnloadPanel(e);
+        if (!e.Cancel)
+        {
+            ISubPanelHost.Global.ShutdownSubPanels(e);
+        }
         if (e.Cancel)
         {
             return;

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

@@ -381,7 +381,6 @@ public class PanelHost : IPanelHost
 
     #endregion
 
-
     #region Public Interface
 
     public void InitialiseSetupMenu(ContextMenu menu)

+ 53 - 7
prs.desktop/Panels/PurchaseOrders/SupplierPurchaseOrderItemOneToMany.cs

@@ -17,12 +17,24 @@ namespace PRSDesktop;
 public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseOrder,PurchaseOrderItem>
 {
     private Button bill;
+    private Button? catalog;
     private Button? createConsignment;
     //private Button? viewconsign;
     private Button receive;
     private Button assignLocation;
 
-    private readonly List<Tuple<PurchaseOrderItem, PurchaseOrderItemAllocation>> Allocations = new();
+    public List<Tuple<PurchaseOrderItem, PurchaseOrderItemAllocation>> Allocations { get; private set; } = new();
+
+    private bool _simplified = false;
+    public bool Simplified
+    {
+        get => _simplified;
+        set
+        {
+            _simplified = value;
+            UpdateButtonVisibility();
+        }
+    }
 
     public SupplierPurchaseOrderItemOneToMany() : base()
     {
@@ -82,11 +94,41 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
         ActionColumns.Add(new DynamicImageColumn(FormsImage) { Position = DynamicActionColumnPosition.Start, ToolTip = FormsToolTip });
     }
 
+    private void UpdateButtonVisibility()
+    {
+        if (Simplified)
+        {
+            if(catalog is not null)
+                catalog.Visibility = Visibility.Collapsed;
+            if(createConsignment is not null)
+                createConsignment.Visibility = Visibility.Collapsed;
+            if(receive is not null)
+                receive.Visibility = Visibility.Collapsed;
+            if(bill is not null)
+                bill.Visibility = Visibility.Collapsed;
+            if(assignLocation is not null)
+                assignLocation.Visibility = Visibility.Collapsed;
+        }
+        else
+        {
+            if(catalog is not null)
+                catalog.Visibility = Visibility.Visible;
+            if(createConsignment is not null)
+                createConsignment.Visibility = Visibility.Visible;
+            if(receive is not null)
+                receive.Visibility = Visibility.Visible;
+            if(bill is not null)
+                bill.Visibility = Visibility.Visible;
+            if(assignLocation is not null)
+                assignLocation.Visibility = Visibility.Visible;
+        }
+    }
+
     protected override void Init()
     {
         base.Init();
         
-        AddButton("Catalog", PRSDesktop.Resources.product.AsBitmapImage(), SearchProducts);
+        catalog = AddButton("Catalog", PRSDesktop.Resources.product.AsBitmapImage(), SearchProducts);
 
         if (Security.IsAllowed<CanViewConsignmentModule>())
         {
@@ -144,6 +186,7 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
     private void BuildFormsMenu(DynamicMenuColumn column, CoreRow? row)
     {
         if (row == null) return;
+        var poiID = row.Get<PurchaseOrderItem, Guid>(x => x.ID);
 
         if (Security.CanEdit<PurchaseOrderItem>())
         {
@@ -155,11 +198,14 @@ public class SupplierPurchaseOrderItemOneToMany : DynamicOneToManyGrid<PurchaseO
             column.AddItem("View Consignment", null, ViewConsignment);
         }
 
-        var formsItem = column.AddItem("Digital Forms", PRSDesktop.Resources.kanban, null);
-        DynamicGridUtils.PopulateFormMenu<PurchaseOrderItemForm, PurchaseOrderItem, PurchaseOrderItemLink>(
-            formsItem,
-            row.Get<PurchaseOrderItem, Guid>(x => x.ID),
-            row.ToObject<PurchaseOrderItem>);
+        if(poiID != Guid.Empty)
+        {
+            var formsItem = column.AddItem("Digital Forms", PRSDesktop.Resources.kanban, null);
+            DynamicGridUtils.PopulateFormMenu<PurchaseOrderItemForm, PurchaseOrderItem, PurchaseOrderItemLink>(
+                formsItem,
+                poiID,
+                row.ToObject<PurchaseOrderItem>);
+        }
     }
 
     private void SplitLine(CoreRow? row)

+ 1 - 1
prs.desktop/Panels/PurchaseOrders/SupplierPurchaseOrderItemSplitWindow.xaml

@@ -6,7 +6,7 @@
         xmlns:local="clr-namespace:PRSDesktop.Panels.PurchaseOrders"
         xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
         mc:Ignorable="d"
-        Title="SupplierPurchaseOrderItemSplitWindow" Height="400" Width="550"
+        Title="Split Items" Height="400" Width="550"
         x:Name="Window">
     <Grid Margin="5" DataContext="{Binding ElementName=Window}">
         <Grid.RowDefinitions>

+ 165 - 324
prs.desktop/Panels/Reservation Management/ReservationManagementPanel.xaml.cs

@@ -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
 }

+ 3 - 3
prs.desktop/Panels/Reservation Management/Treatment PO/ReservationManagementTreatmentOrderGrid.cs

@@ -71,7 +71,7 @@ public class ReservationManagementTreatmentPOItem : BaseObject
     }
 }
 
-public class StockForecastOrderingResult
+public class StockForecastTreatmentOrderingResult
 {
     public SupplierLink Supplier { get; set; }
 
@@ -81,7 +81,7 @@ public class StockForecastOrderingResult
 
     public double Quantity { get; set; }
 
-    public StockForecastOrderingResult(SupplierLink supplier, ReservationManagementTreatmentPOItem item, double quantity, SupplierProduct supplierProduct)
+    public StockForecastTreatmentOrderingResult(SupplierLink supplier, ReservationManagementTreatmentPOItem item, double quantity, SupplierProduct supplierProduct)
     {
         Supplier = supplier;
         Item = item;
@@ -104,7 +104,7 @@ public class ReservationManagementTreatmentOrderGrid: DynamicItemsListGrid<Reser
 
     private static BitmapImage _warning = PRSDesktop.Resources.warning.AsBitmapImage();
 
-    public IEnumerable<StockForecastOrderingResult> Results
+    public IEnumerable<StockForecastTreatmentOrderingResult> Results
     {
         get
         {

+ 1 - 1
prs.desktop/Panels/Reservation Management/Treatment PO/ReservationManagementTreatmentOrderScreen.xaml.cs

@@ -33,7 +33,7 @@ public partial class ReservationManagementTreatmentOrderScreen : Window, INotify
         }
     }
 
-    public IEnumerable<StockForecastOrderingResult> Results => Grid.Results;
+    public IEnumerable<StockForecastTreatmentOrderingResult> Results => Grid.Results;
 
     public ReservationManagementTreatmentOrderScreen(List<ReservationManagementTreatmentPOItem> items)
     {