Преглед изворни кода

Obsoleted JobRequisitionItem.PurchaseORderItem, overhauling the Reservation Management screen in the process to allow for multiple purchaseorders for a single item.

Kenric Nugteren пре 1 година
родитељ
комит
046457b31a

+ 2 - 7
prs.desktop/Panels/Jobs/JobRequisitionItemGrid.cs

@@ -66,8 +66,7 @@ namespace PRSDesktop
                     .Add(x => x.Dimensions.Height)
                     .Add(x => x.Dimensions.Weight)
                     .Add(x => x.Dimensions.UnitSize)
-                    .Add(x => x.Supplier.ID)
-                    .Add(x => x.PurchaseOrderItem.ID));
+                    .Add(x => x.Supplier.ID));
 
             var requisition = new JobRequisition
             {
@@ -95,8 +94,6 @@ namespace PRSDesktop
                 newItem.Dimensions.CopyFrom(oldItem.Dimensions);
                 newItem.Supplier.ID = oldItem.Supplier.ID;
                 newItem.Supplier.Synchronise(oldItem.Supplier);
-                newItem.PurchaseOrderItem.ID = oldItem.PurchaseOrderItem.ID;
-                newItem.PurchaseOrderItem.Synchronise(oldItem.PurchaseOrderItem);
                 requiItems.Add(newItem);
             }
 
@@ -177,9 +174,7 @@ namespace PRSDesktop
             columns.Add<JobRequisitionItem, string>(x => x.Style.Description, 150, "Style", "", Alignment.MiddleLeft);
             columns.Add<JobRequisitionItem, double>(x => x.Qty, 50, "Qty", "", Alignment.MiddleLeft);
             columns.Add<JobRequisitionItem, string>(x => x.Dimensions.UnitSize, 50, "Size", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.DueDate, 80, "Due", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.ReceivedDate, 80, "Received", "", Alignment.MiddleLeft);
+            columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderNumbers, 80, "PO Numbers", "", Alignment.MiddleLeft);
             columns.Add<JobRequisitionItem, JobRequisitionItemStatus>(x => x.Status, 80, "Status", "", Alignment.MiddleLeft);
             columns.Add<JobRequisitionItem, string>(x => x.Notes, 300, "Notes", "", Alignment.MiddleLeft);
 

+ 154 - 210
prs.desktop/Panels/Products/Reservation Management/JobRequisitionPurchasing.xaml.cs

@@ -4,6 +4,7 @@ using InABox.Core;
 using InABox.DynamicGrid;
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Linq;
 using System.Windows.Controls;
@@ -13,84 +14,117 @@ namespace PRSDesktop;
 /// <summary>
 /// Interaction logic for JobRequisitionPurchasing.xaml
 /// </summary>
-public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynamicEditorHost
+public partial class JobRequisitionPurchasing : UserControl
 {
     public delegate void PurchaseOrderSaved();
-    public event PurchaseOrderSaved OnPurchaseOrderSaved;
+    public event PurchaseOrderSaved? OnPurchaseOrderSaved;
 
-    public List<JobRequisitionItem> JobRequiItems;
+    private PurchaseOrder Order { get; set; } = new PurchaseOrder();
 
-    public event DataModelUpdateEvent? OnUpdateDataModel;
+    private List<JobRequiItemLinking> JobRequiItems = new List<JobRequiItemLinking>();
 
-    public PurchaseOrder Order { get; set; } = new PurchaseOrder();
-
-    bool bLoaded = false;
-    public void LoadFromRequiLine()
+    private class JobRequiItemLinking
     {
-        if (bLoaded || JobRequiItems.Count == 0)
-            return;
+        public JobRequisitionItem JobRequiItem { get; set; }
 
-        var poid = JobRequiItems[0].PurchaseOrderItem.PurchaseOrderLink.ID;
-        if (poid != Guid.Empty && poid != Order.ID)
-            LoadPO(poid);              
-        else if (poid == Guid.Empty)
-            ClearEditor();
-    }
+        public JobRequisitionItemPurchaseOrderItem? JobRequisitionItemPurchaseOrderItem { get; set; }
 
-    private void LoadPO(Guid poid)
-    {
-        var po = new Client<PurchaseOrder>().Query(
-                    new Filter<PurchaseOrder>(x => x.ID).IsEqualTo(poid),
-                    new Columns<PurchaseOrder>
-                    (
-                        x => x.ID,
-                        x => x.SupplierLink.ID,
-                        x => x.SupplierLink.Code,
-                        x => x.SupplierLink.Name,
-                        x => x.Description,
-                        x => x.Category.ID,
-                        x => x.Category.Code,
-                        x => x.Category.Description,
-                        x => x.RaisedBy.ID,
-                        x => x.RaisedBy.Code,
-                        x => x.RaisedBy.Name,
-                        x => x.DueDate,
-                        x => x.IssuedBy.ID,
-                        x => x.IssuedBy.Code,
-                        x => x.IssuedBy.Name,
-                        x => x.IssuedDate,
-                        x => x.ClosedDate,
-                        x => x.PONumber
-                        ))
-                    .Rows.FirstOrDefault()?.ToObject<PurchaseOrder>();
-        if (po != null)
+        public PurchaseOrderItem? PurchaseOrderItem { get; set; }
+
+        public JobRequiItemLinking(JobRequisitionItem jobRequiItem, PurchaseOrderItem purchaseOrderItem)
         {
-            Order = po;
-            CreatePOEditor(new BaseObject[] { po });
+            JobRequiItem = jobRequiItem;
+            PurchaseOrderItem = purchaseOrderItem;
+            JobRequisitionItemPurchaseOrderItem = null;
         }
-    }
 
-    public IEnumerable<DynamicGridColumn> Columns => throw new NotImplementedException();
-
-    public bool IsReady { get; set; }
+        public JobRequiItemLinking(JobRequisitionItem jobRequiItem, JobRequisitionItemPurchaseOrderItem jobRequisitionItemPurchaseOrderItem)
+        {
+            JobRequiItem = jobRequiItem;
+            PurchaseOrderItem = null;
+            JobRequisitionItemPurchaseOrderItem = jobRequisitionItemPurchaseOrderItem;
+        }
+    }
 
-    public string SectionName { get; set; }
+    bool bLoaded = false;
+    public bool EditorChanged { get; private set; }
 
     public JobRequisitionPurchasing()
     {
         InitializeComponent();
-        empName = new Client<Employee>().Query(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).Rows.FirstOrDefault().Get<Employee, string>(x => x.Name);
         CreatePOEditor();
-        //JobRequiItems = new List<JobRequisitionItem>();
     }
 
-    private string CheckDate(DateTime date)
+    private void ReloadJobRequiItems(Guid orderID)
     {
-        return date.IsEmpty() ? "" : date.ToShortDateString();
+        JobRequiItems.Clear();
+
+        if(orderID != Guid.Empty)
+        {
+            var poItems = Client.Query(
+                new Filter<JobRequisitionItemPurchaseOrderItem>(x => x.PurchaseOrderItem.PurchaseOrderLink.ID)
+                    .IsEqualTo(orderID),
+                new Columns<JobRequisitionItemPurchaseOrderItem>(x => x.ID).Add(x => x.JobRequisitionItem.ID))
+                .ToObjects<JobRequisitionItemPurchaseOrderItem>();
+            foreach (var jriPoi in poItems)
+            {
+                var jri = new JobRequisitionItem
+                {
+                    ID = jriPoi.JobRequisitionItem.ID
+                };
+                JobRequiItems.Add(new JobRequiItemLinking(jri, jriPoi));
+            }
+        }
     }
 
-    public bool EditorChanged {get; private set; }
-    private string empName = "";
+    public void LoadFromRequiLine(Guid orderID)
+    {
+        if (bLoaded)
+            return;
+
+        ReloadJobRequiItems(orderID);
+
+        if (orderID != Guid.Empty)
+        {
+            if (orderID != Order.ID)
+            {
+                LoadPO(orderID);
+            }
+        }
+        else
+            ClearEditor();
+    }
+
+    private void LoadPO(Guid orderID)
+    {
+        var po = Client.Query(
+            new Filter<PurchaseOrder>(x => x.ID).IsEqualTo(orderID),
+            new Columns<PurchaseOrder>(
+                x => x.ID,
+                x => x.SupplierLink.ID,
+                x => x.SupplierLink.Code,
+                x => x.SupplierLink.Name,
+                x => x.Description,
+                x => x.Category.ID,
+                x => x.Category.Code,
+                x => x.Category.Description,
+                x => x.RaisedBy.ID,
+                x => x.RaisedBy.Code,
+                x => x.RaisedBy.Name,
+                x => x.DueDate,
+                x => x.IssuedBy.ID,
+                x => x.IssuedBy.Code,
+                x => x.IssuedBy.Name,
+                x => x.IssuedDate,
+                x => x.ClosedDate,
+                x => x.PONumber))
+            .ToObjects<PurchaseOrder>().FirstOrDefault();
+        if (po is not null)
+        {
+            Order = po;
+            CreatePOEditor(new BaseObject[] { po });
+        }
+    }
 
     private void CreatePOEditor(BaseObject[]? items = null)
     {
@@ -118,7 +152,9 @@ public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynami
             var cancel = new System.ComponentModel.CancelEventArgs();
             Editor.SaveItem(cancel);
             Editor.HideButtons = true;
-            UpdateJobRequiItems();
+
+            SaveJRIPOIs();
+
             OnPurchaseOrderSaved?.Invoke();
             EditorChanged = false;
             bLoaded = false;
@@ -127,7 +163,14 @@ public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynami
         {                
             Editor.HideButtons = true;
             bLoaded = false;
-            ClearEditor();
+
+            var orderID = Order.ID;
+
+            Order = new PurchaseOrder();
+            JobRequiItems.Clear();
+
+            LoadFromRequiLine(orderID);
+
             EditorChanged = false;
         };
         Editor.OnChanged += (sender, args) =>
@@ -139,7 +182,7 @@ public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynami
         DetailBorder.Child = Editor;
 
         var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(PurchaseOrder));
-        grid.InitialiseEditorForm(Editor, items ?? new object[] { Activator.CreateInstance(typeof(PurchaseOrder))! });
+        grid.InitialiseEditorForm(Editor, items ?? new object[] { new PurchaseOrder() });
 
         var loadPO = new Button
         {
@@ -154,7 +197,7 @@ public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynami
 
     private void LoadPO_Click(object sender, System.Windows.RoutedEventArgs e)
     {
-        var popup = new PopupList(typeof(PurchaseOrder), Guid.Empty, new string[0]);
+        var popup = new PopupList(typeof(PurchaseOrder), Guid.Empty, Array.Empty<string>());
         if(popup.ShowDialog() == true)
         {
             bLoaded = true;
@@ -162,176 +205,77 @@ public partial class JobRequisitionPurchasing : UserControl, IBasePanel, IDynami
         }
     }
 
-    private void UpdateJobRequiItems()
-    {
-        var page = Editor.Pages.Find(x => x.GetType() == typeof(SupplierPurchaseOrderItemOneToMany)) as SupplierPurchaseOrderItemOneToMany;
-        if (page.Items.Count != 0)
-            MatchRequiItems(page.Items);
-    }
-
-    private void MatchRequiItems(List<PurchaseOrderItem> poItems)
+    private void SaveJRIPOIs()
     {
-        List<JobRequisitionItem> toSave = new List<JobRequisitionItem>();
-        foreach (var JobReqItem in JobRequiItems)
+        var toSave = new List<JobRequisitionItemPurchaseOrderItem>();
+        foreach(var item in JobRequiItems)
         {
-            if (JobReqItem.PurchaseOrderItem.ID == Guid.Empty)
-                foreach (var item in poItems)
-                    if (MatchReqItemToPOItem(JobReqItem, item))
-                        toSave.Add(UpdateJobReqItemWithPODetails(JobReqItem, item));
+            if(item.PurchaseOrderItem is not null)
+            {
+                var jriPoi = new JobRequisitionItemPurchaseOrderItem();
+                jriPoi.JobRequisitionItem.ID = item.JobRequiItem.ID;
+                jriPoi.PurchaseOrderItem.ID = item.PurchaseOrderItem.ID;
+                toSave.Add(jriPoi);
+                item.JobRequisitionItemPurchaseOrderItem = jriPoi;
+            }
         }
-        if (toSave.Count > 0)
-            new Client<JobRequisitionItem>().Save(toSave, "Updated from Job Requi Review Create Purchase Order");
-    }
 
-    private bool MatchReqItemToPOItem(JobRequisitionItem JobReqItem, PurchaseOrderItem item)
-    {
-        if (JobReqItem.Product.ID == item.Product.ID &&
-                            JobReqItem.Dimensions.UnitSize == item.Dimensions.UnitSize &&
-                            JobReqItem.Requisition.Job.ID == item.Job.ID)
-            return true;
-        else
-            return false;
-    }
-
-    private JobRequisitionItem UpdateJobReqItemWithPODetails(JobRequisitionItem JobReqItem, PurchaseOrderItem poItem)
-    {
-        JobReqItem.PurchaseOrderItem.ID = poItem.ID;
-        JobReqItem.PurchaseOrderItem.DueDate = poItem.DueDate;
-        if (JobReqItem.Status != JobRequisitionItemStatus.OnOrder)
-        {
-            JobReqItem.Notes = JobReqItem.Notes + Environment.NewLine + "Line marked as On Order by " + empName + " on " + DateTime.Now.ToString("dd MMM yy");
-            JobReqItem.Ordered = poItem.Created;
-        }
-        return JobReqItem;
+        Client.Save(
+            toSave,
+            "Updated from Job Requi Review Create Purchase Order");
     }
 
     private void ClearEditor()
     {
         Order = new PurchaseOrder();
         CreatePOEditor();
-
-        //if (Popup is not null)
-        //{
-        //    Popup.Value = Guid.Empty;
-        //}
     }
 
-    public void DropItems(CoreRow[] rows)
+    public void DropItems(IEnumerable<CoreRow> rows)
     {
         var page = Editor.Pages.OfType<SupplierPurchaseOrderItemOneToMany>().First();
-        if (page.Items.Count == 0)
-            page.LoadItems(CreatePOItemsFromRequiItems(rows).ToArray());
-        else
-            page.LoadItems(CombineItems(rows, page.Items));
-    }
 
-    private PurchaseOrderItem[] CombineItems(CoreRow[] selected, List<PurchaseOrderItem> existingItems)
-    {
-        List<PurchaseOrderItem> items = new List<PurchaseOrderItem>();
-        items.AddRange(existingItems);
-        items.AddRange(CreatePOItemsFromRequiItems(selected, existingItems));
-        return items.ToArray();
+        if(CreatePOItemsFromRequiItems(rows.ToObjects<JobRequisitionItem>(), page.Items))
+        {
+            page.Refresh(false, true);
+            page.DoChanged();
+        }
     }
 
-    private List<PurchaseOrderItem> CreatePOItemsFromRequiItems(CoreRow[] selected, List<PurchaseOrderItem>? comparison = null)
+    private bool CreatePOItemsFromRequiItems(IEnumerable<JobRequisitionItem> selected, List<PurchaseOrderItem> items)
     {
-        List<PurchaseOrderItem> items = new List<PurchaseOrderItem>();
-        foreach (CoreRow row in selected)
+        var changed = false;
+        foreach (var jobRequisitionItem in selected)
         {
-            JobRequisitionItem JobReqItem = row.ToObject<JobRequisitionItem>();
-            JobRequiItems.Add(JobReqItem);
-            if (JobReqItem.PurchaseOrderItem.ID != Guid.Empty)
+            // We only want not checked or order required.
+            if(jobRequisitionItem.Status != JobRequisitionItemStatus.NotChecked &&
+                jobRequisitionItem.Status != JobRequisitionItemStatus.OrderRequired)
+            {
                 continue;
-
-            PurchaseOrderItem POItem = new PurchaseOrderItem();
-            POItem.Product.ID = JobReqItem.Product.ID;
-            POItem.Product.Synchronise(JobReqItem.Product);
-            POItem.Description = JobReqItem.Product.Name;
-            POItem.Qty = JobReqItem.Qty;
-            POItem.Dimensions.CopyFrom(JobReqItem.Dimensions);
-            POItem.Style.ID = JobReqItem.Style.ID;
-            POItem.Style.Code = JobReqItem.Style.Code;
-            POItem.Style.Description = JobReqItem.Style.Description;
-            POItem.Job.ID = JobReqItem.Requisition.Job.ID;
-            POItem.Job.JobNumber = JobReqItem.Requisition.Job.JobNumber;
-            POItem.Job.Name = JobReqItem.Requisition.Job.Name;
-            POItem.Dimensions.UnitSize = JobReqItem.Dimensions.UnitSize;
-            if (comparison != null && !Duplicated(POItem, comparison))
-                items.Add(POItem);
-            else if (comparison == null)
-                items.Add(POItem);
+            }
+            // Filter out ones we've already got.
+            if(JobRequiItems.Any(x => x.JobRequiItem.ID == jobRequisitionItem.ID))
+            {
+                continue;
+            }
+
+            var poItem = new PurchaseOrderItem
+            {
+                Description = jobRequisitionItem.Product.Name,
+                Qty = jobRequisitionItem.Qty
+            };
+            poItem.Product.ID = jobRequisitionItem.Product.ID;
+            poItem.Product.Synchronise(jobRequisitionItem.Product);
+            poItem.Dimensions.CopyFrom(jobRequisitionItem.Dimensions);
+            poItem.Style.ID = jobRequisitionItem.Style.ID;
+            poItem.Style.Synchronise(jobRequisitionItem.Style);
+            poItem.Job.ID = jobRequisitionItem.Requisition.Job.ID;
+            poItem.Job.Synchronise(jobRequisitionItem.Requisition.Job);
+            items.Add(poItem);
+
+            JobRequiItems.Add(new JobRequiItemLinking(jobRequisitionItem, poItem));
+            changed = true;
         }
-        return items;
-    }
-
-    private bool Duplicated(PurchaseOrderItem newItem, List<PurchaseOrderItem> existing)
-    {
-        if (existing.Find(x =>
-            x.Product.ID == newItem.Product.ID
-            && x.Qty == newItem.Qty
-            && x.Style.ID == newItem.Style.ID
-            && x.Job.ID == newItem.Job.ID
-            && x.Dimensions.UnitSize == newItem.Dimensions.UnitSize
-            )
-            != null)
-            return true;
-
-        return false;
-    }
-
-
-    public void LoadColumns(string column, Dictionary<string, string> columns)
-    {
-
-    }
-
-    public IFilter? DefineFilter(Type type) => LookupFactory.DefineFilter(type);
-
-    public void LoadLookups(ILookupEditorControl sender)
-    {
-        var editor = sender.EditorDefinition as ILookupEditor;
-        var colname = sender.ColumnName;
-
-        var values = editor.Values(colname, Editor.Items);
-        sender.LoadLookups(values);
-    }
-
-    object?[] IDynamicEditorHost.GetItems() => Editor.Items;
-
-    public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor();
-
-    public void CreateToolbarButtons(IPanelHost host)
-    {
-
-    }
-
-    public Dictionary<string, object[]> Selected()
-    {
-        return new Dictionary<string, object[]>();
-    }
-
-    public void Heartbeat(TimeSpan time)
-    {
-
-    }
-
-    public void Setup()
-    {
-
-    }
-
-    public void Shutdown(CancelEventArgs? cancel)
-    {
-
-    }
-
-    public void Refresh()
-    {
-
-    }
-
-    public DataModel DataModel(Selection selection)
-    {
-        return new EmptyDataModel();
+        return changed;
     }
 }

+ 23 - 13
prs.desktop/Panels/Products/Reservation Management/JobRequisitionReviewGrid.cs

@@ -60,10 +60,6 @@ public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
         HiddenColumns.Add(x => x.Requisition.Job.JobNumber);
         HiddenColumns.Add(x => x.Requisition.Job.Name);
         HiddenColumns.Add(x => x.Requisition.Number);
-        HiddenColumns.Add(x => x.PurchaseOrderItem.ID);
-        HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.ID);
-        HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber);
-        HiddenColumns.Add(x => x.PurchaseOrderItem.DueDate);
         HiddenColumns.Add(x => x.Job.ID);
         HiddenColumns.Add(x => x.Job.Name);
         HiddenColumns.Add(x => x.Job.JobNumber);
@@ -96,12 +92,12 @@ public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
     {
         base.DoReconfigure(options);
 
-        options.BeginUpdate().AddRange(
-            DynamicGridOption.FilterRows,
-            DynamicGridOption.SelectColumns,
-            DynamicGridOption.RecordCount,
-            DynamicGridOption.DragSource
-            )
+        options.BeginUpdate()
+            .AddRange(
+                DynamicGridOption.FilterRows,
+                DynamicGridOption.SelectColumns,
+                DynamicGridOption.RecordCount,
+                DynamicGridOption.DragSource)
             .Remove(DynamicGridOption.AddRows)
             .Remove(DynamicGridOption.ImportData)
             .Remove(DynamicGridOption.ExportData)
@@ -127,9 +123,7 @@ public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
         columns.Add<JobRequisitionItem, string>(x => x.Style.Description, 150, "Style", "", Alignment.MiddleLeft);
         columns.Add<JobRequisitionItem, double>(x => x.Qty, 50, "Qty", "", Alignment.MiddleLeft);
         columns.Add<JobRequisitionItem, string>(x => x.Dimensions.UnitSize, 50, "Size", "", Alignment.MiddleLeft);
-        columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
-        columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.DueDate, 80, "Due", "", Alignment.MiddleLeft);
-        columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.ReceivedDate, 80, "Received", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderNumbers, 80, "PO Numbers", "", Alignment.MiddleLeft);
         columns.Add<JobRequisitionItem, string>(x => x.Notes, 300, "Notes", "", Alignment.MiddleLeft);
         return columns;
     }
@@ -245,6 +239,22 @@ public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
         column.AddItem("Split Line", PRSDesktop.Resources.split, SplitLine_Clicked);
         column.AddItem("Archive", PRSDesktop.Resources.archive, Archive_Clicked);
     }
+
+    protected override DragDropEffects OnRowsDragStart(CoreRow[] rows)
+    {
+        // Only allow dragging the selected rows.
+        var selected = SelectedRows.Select(x => x.Get<JobRequisitionItem, Guid>(x => x.ID)).ToHashSet();
+        var draggedRows = rows.Where(x => selected.Contains(x.Get<JobRequisitionItem, Guid>(x => x.ID))).ToArray();
+
+        if(draggedRows.Length == 0)
+        {
+            return DragDropEffects.None;
+        }
+        else
+        {
+            return base.OnRowsDragStart(draggedRows);
+        }
+    }
 }
 
 public class JobRequiReviewDashboardFilterItem

+ 26 - 17
prs.desktop/Panels/Products/Reservation Management/JobRequisitionsPanel.xaml

@@ -5,17 +5,19 @@
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:local="clr-namespace:PRSDesktop" xmlns:dynamicgrid="clr-namespace:InABox.DynamicGrid;assembly=InABox.Wpf"
              mc:Ignorable="d" 
-             d:DesignHeight="450" d:DesignWidth="900">
+             d:DesignHeight="450" d:DesignWidth="900"
+             x:Name="Panel">
     <dynamicgrid:DynamicSplitPanel 
         MasterCaption="Job Requisition Items" 
         DetailCaption="Available Stock" 
         Anchor="Detail" 
         AnchorWidth="600" 
-        AllowableViews="Combined" 
-        View="Combined">
+        AllowableViews="Master,Combined" 
+        View="Combined"
+        DataContext="{Binding ElementName=Panel}">
        
         <dynamicgrid:DynamicSplitPanel.Master>
-            <local:JobRequisitionReviewGrid  x:Name="JobRequiItems" Margin="0,2,0,0" MouseMove="Grid_MouseMove"/>
+            <local:JobRequisitionReviewGrid  x:Name="JobRequiItems" Margin="0,2,0,0"/>
         </dynamicgrid:DynamicSplitPanel.Master>
 
         <dynamicgrid:DynamicSplitPanel.Detail>
@@ -24,19 +26,26 @@
                     <RowDefinition Height="auto"/>
                     <RowDefinition Height="*"/>
                 </Grid.RowDefinitions>
-      
-                <Grid Grid.Row="0">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="*"/>
-                    </Grid.ColumnDefinitions>
-                    <Button Grid.Column="0" Content="Reserve Stock" Height="30"  FontWeight="DemiBold" x:Name="reserveBtn"
-                            BorderBrush="DarkGray" Margin="0,2,1,0" Padding="13,3,13,3" BorderThickness="1.25"
-                            Click="ReserveStock_Clicked"/>
-                    <Button Grid.Column="1" Content="Purchase Stock" Height="30" FontWeight="DemiBold" x:Name="purchaseBtn"
-                            BorderBrush="DarkGray" Margin="1,2,0,0" Padding="13,3,13,3"  BorderThickness="1.25"
-                            Click="PurchaseStock_Clicked"/>
-                </Grid>
+
+                <ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="Auto"/>
+                            <ColumnDefinition Width="Auto"/>
+                        </Grid.ColumnDefinitions>
+                        <Button Grid.Column="0" Content="Reserve Stock" Height="30"  FontWeight="DemiBold" x:Name="reserveBtn"
+                                BorderBrush="DarkGray" Margin="0,2,1,0" Padding="13,3,13,3" BorderThickness="1.25"
+                                Click="ReserveStock_Clicked"/>
+                        <StackPanel Grid.Column="1" Orientation="Horizontal" x:Name="PurchaseOrderButtons"/>
+                        <Button x:Name="AddPOButton" Grid.Column="2" Height="30" FontWeight="DemiBold"
+                                Content="New"
+                                BorderBrush="DarkGray" BorderThickness="1.25"
+                                Margin="1,2,0,0"
+                                Padding="13,3"
+                                Click="AddPOButton_Click"/>
+                    </Grid>
+                </ScrollViewer>
                 <Grid Grid.Row="1">
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="*" x:Name="reserveCol"/>

+ 118 - 68
prs.desktop/Panels/Products/Reservation Management/JobRequisitionsPanel.xaml.cs

@@ -15,6 +15,8 @@ using System.Windows.Input;
 using System.Windows.Media;
 using InABox.WPF.Themes;
 using NPOI.SS.Formula.Functions;
+using System.Collections.ObjectModel;
+using InABox.Clients;
 
 namespace PRSDesktop
 {
@@ -24,14 +26,12 @@ namespace PRSDesktop
         public ProductStyleLink ProductStyle { get; set; }
     }
 
-
     /// <summary>
     /// Interaction logic for JobRequisitionsPanel.xaml
     /// </summary>
     public partial class JobRequisitionsPanel : UserControl, IPanel<JobRequisitionItem>
     {
-        Guid JobID = Guid.Empty;
-        private JobRequisitionPanelSettings _settings = null;
+        private JobRequisitionPanelSettings _settings = null!; // Initialised in Setup()
 
         public JobRequisitionsPanel()
         {
@@ -56,47 +56,64 @@ namespace PRSDesktop
             Purchase
         }
 
-        private PanelMode mode;
+        private PanelMode Mode { get; set; }
 
-        private PanelMode Mode
+        private void SelectDetailButton(Button button)
         {
-            get => mode;
-            set
+            reserveBtn.Background = new SolidColorBrush(Colors.WhiteSmoke);
+            reserveBtn.Foreground = new SolidColorBrush(Colors.Black);
+            foreach(var btn in PurchaseOrderButtons.Children.OfType<Button>())
             {
-                mode = value;
-                SetPanelDetail();
+                btn.Background = new SolidColorBrush(Colors.WhiteSmoke);
+                btn.Foreground = new SolidColorBrush(Colors.Black);
             }
+            AddPOButton.Background = new SolidColorBrush(Colors.WhiteSmoke);
+            AddPOButton.Foreground = new SolidColorBrush(Colors.Black);
+            button.Background = ThemeManager.SelectedTabItemBackgroundBrush;
+            button.Foreground = ThemeManager.SelectedTabItemForegroundBrush;
         }
-
-        private void SetPanelDetail()
+        private void SelectReserved()
         {
-            JobRequiItems.Reconfigure();
-            if (Mode == PanelMode.Reserve)
+            SelectDetailButton(reserveBtn);
+
+            reserveCol.Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
+            purchaseCol.Width = new System.Windows.GridLength(0);
+
+            if(Mode != PanelMode.Reserve)
             {
-                reserveCol.Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
-                purchaseCol.Width = new System.Windows.GridLength(0);
+                Mode = PanelMode.Reserve;
+                JobRequiItems.Reconfigure();
+            }
+        }
+        private void SelectNewPurchaseOrder()
+        {
+            SelectDetailButton(AddPOButton);
 
-                reserveBtn.Background = ThemeManager.SelectedTabItemBackgroundBrush;
-                reserveBtn.Foreground = ThemeManager.SelectedTabItemForegroundBrush;
-                purchaseBtn.Background = new SolidColorBrush(Colors.WhiteSmoke);
-                purchaseBtn.Foreground = new SolidColorBrush(Colors.Black);
+            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;
+                JobRequiItems.Reconfigure();
             }
-            else if (Mode == PanelMode.Purchase)
+
+            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)
             {
-                reserveCol.Width = new System.Windows.GridLength(0);
-                purchaseCol.Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
-
-                reserveBtn.Background = new SolidColorBrush(Colors.WhiteSmoke);
-                reserveBtn.Foreground = new SolidColorBrush(Colors.Black);
-                purchaseBtn.Background = ThemeManager.SelectedTabItemBackgroundBrush;
-                reserveBtn.Foreground = ThemeManager.SelectedTabItemForegroundBrush;
-                if (JobRequiItems.SelectedRows.Any())
-                {
-                    purchasing.JobRequiItems = CreateList(JobRequiItems.SelectedRows);
-                    purchasing.LoadFromRequiLine();
-                }
+                Mode = PanelMode.Purchase;
+                JobRequiItems.Reconfigure();
             }
+
+            purchasing.LoadFromRequiLine(order.ID);
         }
 
         public bool IsReady { get; set; }
@@ -139,14 +156,15 @@ namespace PRSDesktop
 
         public Dictionary<string, object[]> Selected()
         {
-            var result = new Dictionary<string, object[]>();
-            result[typeof(JobRequisitionItem).EntityName()] = JobRequiItems.SelectedRows;
-            return result;
+            return new Dictionary<string, object[]>
+            {
+                [typeof(JobRequisitionItem).EntityName()] = JobRequiItems.SelectedRows
+            };
         }
 
         public void Setup()
         {
-            Mode = PanelMode.Reserve;
+            SelectReserved();
 
             JobRequiItems.OnSelectItem += OnJobRequiItemSelected;
             JobRequiItems.Refresh(true, false);
@@ -162,10 +180,60 @@ namespace PRSDesktop
         private void OnJobRequiItemSelected(object sender, DynamicGridSelectionEventArgs e)
         {
             holdings.Item = e.Rows?.FirstOrDefault()?.ToObject<JobRequisitionItem>();
-            if (mode == PanelMode.Purchase)
+            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<JobRequisitionItemPurchaseOrderItem>(x => x.JobRequisitionItem.ID)
+                        .InList(requiIDs),
+                    x => x.PurchaseOrderItem.PurchaseOrderLink.ID),
+                new Columns<PurchaseOrder>(x => x.ID)
+                    .Add(x => x.PONumber))
+                .ToObjects<PurchaseOrder>().ToList();
+
+            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(1, 2, 0, 0),
+                    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)
             {
-                purchasing.JobRequiItems = e.Rows?.ToObjects<JobRequisitionItem>().ToList() ?? new List<JobRequisitionItem>();
-                purchasing.LoadFromRequiLine();
+                SelectReserved();
             }
         }
 
@@ -174,15 +242,6 @@ namespace PRSDesktop
             Refresh();
         }
 
-        private List<JobRequisitionItem> CreateList(CoreRow[] rows)
-        {
-            List<JobRequisitionItem> list = new List<JobRequisitionItem>();
-            foreach (var row in rows)
-                list.Add(row.ToObject<JobRequisitionItem>());
-
-            return list;
-        }
-
         private void CheckSaved(CancelEventArgs cancel)
         {
             if (!purchasing.EditorChanged)
@@ -203,12 +262,6 @@ namespace PRSDesktop
                 cancel.Cancel = true;
             }
         }
-        private bool CheckSaved()
-        {
-            var cancel = new CancelEventArgs();
-            CheckSaved(cancel);
-            return !cancel.Cancel;
-        }
 
         public void Shutdown(CancelEventArgs? cancel)
         {
@@ -220,26 +273,23 @@ namespace PRSDesktop
 
         private void ReserveStock_Clicked(object sender, System.Windows.RoutedEventArgs e)
         {
-            Mode = PanelMode.Reserve;
-        }
-
-        private void PurchaseStock_Clicked(object sender, System.Windows.RoutedEventArgs e)
-        {
-            Mode = PanelMode.Purchase;
+            SelectReserved();
         }
 
-        private void Grid_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
+        private void Purchasing_Drop(object sender, DragEventArgs e)
         {
-            if (e.LeftButton == MouseButtonState.Pressed
-                && e.OriginalSource.GetType() != typeof(Border)
-                && e.OriginalSource.GetType() != typeof(Thumb)
-                )
-                DragDrop.DoDragDrop(JobRequiItems, JobRequiItems.SelectedRows, DragDropEffects.Link);
+            if(DynamicGridUtils.TryGetDropData(e, out var type, out var table))
+            {
+                if(type == typeof(JobRequisitionItem))
+                {
+                    purchasing.DropItems(table.Rows);
+                }
+            }
         }
 
-        private void Purchasing_Drop(object sender, DragEventArgs e)
+        private void AddPOButton_Click(object sender, RoutedEventArgs e)
         {
-            purchasing.DropItems(JobRequiItems.SelectedRows);
+            SelectNewPurchaseOrder();
         }
     }
 }