Quellcode durchsuchen

Implemented Product Group Tree into Master Product List

frogsoftware vor 1 Jahr
Ursprung
Commit
7307fa2c2e

+ 1 - 1
prs.classes/Entities/Product/ProductGroup/ProductGroup.cs

@@ -36,7 +36,7 @@ namespace Comal.Classes
                 var nodes = new CoreTreeNodes();
                 nodes.Load<ProductGroup>(data,x=>x.ID,x=>x.Parent.ID,x=>x.Description);
                 foreach (var item in items)
-                    nodes.GetChildren(exclusions,item.ID);
+                    nodes.GetThisAndAllChildren(exclusions,item.ID);
                 return new Filter<ProductGroup>(x => x.ID).NotInList(exclusions.ToArray());
             }
 

+ 1 - 1
prs.classes/Entities/Product/ProductGroup/ProductGroupLink.cs

@@ -8,7 +8,7 @@ namespace Comal.Classes
     public class ProductGroupLink : EntityLink<ProductGroup>
     {
         [EditorSequence(1)]
-        [LookupEditor(typeof(ProductGroup))]
+        [PopupEditor(typeof(ProductGroup))]
         public override Guid ID { get; set; }
 
         [EditorSequence(2)]

+ 1 - 1
prs.desktop/Panels/Jobs/DocumentSets/JobDocumentSetPanel.xaml.cs

@@ -187,7 +187,7 @@ namespace PRSDesktop
         private void LoadDocuments(Guid folderid)
         {
             List<Guid> folders = new List<Guid>();
-            this.Folders.Nodes.GetChildren(folders, folderid);
+            this.Folders.Nodes.GetThisAndAllChildren(folders, folderid);
             Documents.FolderIDs = folders.ToArray();
             Documents.Refresh();
         }

+ 110 - 0
prs.desktop/Panels/Products/Master List/ProductGroupTree.cs

@@ -0,0 +1,110 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Windows;
+using System.Windows.Controls;
+using Comal.Classes;
+using InABox.Clients;
+using InABox.Core;
+using InABox.DynamicGrid;
+using InABox.WPF;
+
+namespace PRSDesktop;
+
+public class ProductGroupTree: DynamicTreeView<ProductGroup>
+{
+    protected override Expression<Func<ProductGroup, Guid>> ID => x => x.ID;
+    protected override Expression<Func<ProductGroup, Guid>> ParentID => x => x.Parent.ID;
+    protected override Expression<Func<ProductGroup, string>> Description => x => x.Description;
+    
+    public ProductGroupTree() : base()
+    {
+        Options.AddRange(DynamicTreeOption.Add, DynamicTreeOption.Edit, DynamicTreeOption.Delete);
+        MaxRowHeight = 30D;
+        ExpandMode = DynamicTreeGridExpandMode.Root;
+        //OnContextMenuOpening += ProductTree_OnContextMenuOpening;
+    }
+
+    // private void ProductTree_OnContextMenuOpening(CoreTreeNode node, ContextMenu menu)
+    // {
+    //     menu.AddItem("Add Child Group", null, node, (n) => DoAddItem(n.ID,true));
+    //     
+    // }
+
+    protected override ProductGroup DoCreateItem(Guid parent)
+    {
+        var selectedid = SelectedID == CoreUtils.FullGuid ? Guid.Empty : SelectedID;
+        var result = base.DoCreateItem(selectedid);
+        return result;
+    }
+
+    protected override ProductGroup? DoLoadItem(Guid id)
+    {
+        if (id == CoreUtils.FullGuid)
+        {
+            MessageBox.Show("This item cannot be edited.");
+            return null;
+        }
+
+        return new Client<ProductGroup>()
+            .Query(new Filter<ProductGroup>(x => x.ID).IsEqualTo(id))
+            .Rows
+            .FirstOrDefault()?
+            .ToObject<ProductGroup>();
+    }
+
+    protected override void DoSaveItem(ProductGroup item)
+    {
+        if (item.ID != CoreUtils.FullGuid)
+            new Client<ProductGroup>().Save(item, "Edited by User");
+    }
+
+    protected override bool DoDeleteItem(Guid id)
+    {
+        if(id == CoreUtils.FullGuid)
+        {
+            MessageBox.Show("This group cannot be deleted.");
+            return false;
+        }
+
+        CoreRow? row = Data.Rows.FirstOrDefault(r=>r.Get<ProductGroup, Guid>(x => x.ID) == id);
+        if(row == null)
+        {
+            MessageBox.Show("Error: Row does not exist!");
+            Logger.Send(LogType.Error, ClientFactory.UserID, $"Error: Product Group {id} does not exist or is not loaded");
+            return false;
+        }
+        
+        new Client<ProductGroup>().Delete(new ProductGroup() { ID = id }, "Deleted by User");
+        return true;
+    }
+
+    protected override void DoRefresh(Action<CoreTable?, Exception?> action)
+    {
+        try
+        {
+            var data = new Client<ProductGroup>().Query(
+                LookupFactory.DefineFilter<ProductGroup>(),
+                null
+            );
+
+            foreach (var row in data.Rows)
+            {
+                if (row.Get<ProductGroup,Guid>(x=>x.Parent.ID) == Guid.Empty)
+                    row.Set<ProductGroup, Guid>(x => x.Parent.ID, CoreUtils.FullGuid);
+            }
+
+            var newRow = data.NewRow();
+            newRow.Set<ProductGroup, Guid>(x => x.ID, CoreUtils.FullGuid);
+            newRow.Set<ProductGroup, Guid>(x => x.Parent.ID, Guid.Empty );
+            newRow.Set<ProductGroup, string>(x => x.Description, "All Groups");
+            data.Rows.Insert(0, newRow);
+
+            action(data, null);
+        }
+        catch (Exception e)
+        {
+            action(null, e);
+        }
+    }
+}

+ 4 - 0
prs.desktop/Panels/Products/Master List/ProductsGrid.cs

@@ -18,6 +18,8 @@ namespace PRSDesktop
 
         private List<ProductPriceComponent> pricecomponents;
         private readonly Button ToggleExpiredButton;
+        
+        public Guid[]? Groups { get; set; }
 
         public ProductsGrid()
         {
@@ -275,6 +277,8 @@ namespace PRSDesktop
         protected override void Reload(Filters<Product> criteria, Columns<Product> columns, ref SortOrder<Product>? sort,
             Action<CoreTable?, Exception?> action)
         {
+            if (Groups != null)
+                criteria.Add(new Filter<Product>(x => x.Group.ID).InList(Groups));
             if (!_includeexpired)
                 criteria.Add(new Filter<Product>(x => x.Expired).IsEqualTo(DateTime.MinValue));
             sort = new SortOrder<Product>(x => x.Code);

+ 131 - 103
prs.desktop/Panels/Products/Master List/ProductsPanel.xaml

@@ -8,125 +8,153 @@
              xmlns:sf="http://schemas.syncfusion.com/wpf"
              mc:Ignorable="d"
              d:DesignHeight="450" d:DesignWidth="800">
-    <dynamicgrid:DynamicSplitPanel x:Name="SplitPanel" View="Combined" AnchorWidth="500" Anchor="Detail" MasterCaption="Product List"
-                                   DetailCaption="Product Details" OnChanged="SplitPanel_OnChanged">
-
+    
+    <dynamicgrid:DynamicSplitPanel
+        AllowableViews="Detail,Combined"
+        View="Combined"
+        Anchor="Master"
+        AnchorWidth="250">
         <dynamicgrid:DynamicSplitPanel.Header>
             <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25">
-                <Label Content="Master Product List" HorizontalContentAlignment="Center"
+                <Label Content="Product Groups" HorizontalContentAlignment="Center"
                        VerticalContentAlignment="Center" />
             </Border>
         </dynamicgrid:DynamicSplitPanel.Header>
-
         <dynamicgrid:DynamicSplitPanel.Master>
-            <local:ProductsGrid Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" x:Name="Products"
-                                AfterRefresh="Products_AfterRefresh"/>
+            <local:ProductGroupTree
+                x:Name="Groups"
+                Grid.Row="0"
+                Grid.Column="0"
+                GridLines="None"
+                OnSelectItem="Groups_OnOnSelectItem"/>
         </dynamicgrid:DynamicSplitPanel.Master>
-
         <dynamicgrid:DynamicSplitPanel.Detail>
-            <Grid>
+    
+    
+            <dynamicgrid:DynamicSplitPanel x:Name="SplitPanel" View="Combined" AnchorWidth="500" Anchor="Detail" MasterCaption="Product List" AllowableViews="Master,Combined"
+                                           DetailCaption="Product Details" OnChanged="SplitPanel_OnChanged">
+
+                <dynamicgrid:DynamicSplitPanel.Header>
+                    <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25">
+                        <Label Content="Master Product List" HorizontalContentAlignment="Center"
+                               VerticalContentAlignment="Center" />
+                    </Border>
+                </dynamicgrid:DynamicSplitPanel.Header>
+
+                <dynamicgrid:DynamicSplitPanel.Master>
+                    
+                    <local:ProductsGrid 
+                        x:Name="Products"
+                        AfterRefresh="Products_AfterRefresh"/>
 
-                <Grid.RowDefinitions>
-                    <RowDefinition Height="*" />
-                    <RowDefinition Height="0" />
-                </Grid.RowDefinitions>
+                </dynamicgrid:DynamicSplitPanel.Master>
 
-                <dynamicgrid:DynamicTabControl Grid.Row="0" x:Name="ProductDetails" SelectionChanged="ProductDetails_SelectionChanged"
-                                   BorderThickness="0" Background="WhiteSmoke">
+                <dynamicgrid:DynamicSplitPanel.Detail>
+                    <Grid>
 
-                    <dynamicgrid:DynamicTabItem x:Name="Holdings" Header="Holdings">
-                        <Grid>
-                            <Grid.RowDefinitions>
-                                <RowDefinition Height="Auto"/>
-                                <RowDefinition Height="*"/>
-                                <RowDefinition Height="Auto"/>                                
-                                <RowDefinition Height="3*"/>
-                            </Grid.RowDefinitions>
-                            <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25"
-                                    Grid.Row="0" Margin="0,2">
-                                <Label Content="Product Instances" HorizontalContentAlignment="Center"
-                                       VerticalContentAlignment="Center" />
-                            </Border>
-                            <local:ProductInstanceControl x:Name="ProductInstances" UseWaitCursor="False" Grid.Row="1"
-                                                          OnChanged="ProductInstances_OnChanged"/>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="*" />
+                            <RowDefinition Height="0" />
+                        </Grid.RowDefinitions>
+
+                        <dynamicgrid:DynamicTabControl Grid.Row="0" x:Name="ProductDetails" SelectionChanged="ProductDetails_SelectionChanged"
+                                           BorderThickness="0" Background="WhiteSmoke">
+
+                            <dynamicgrid:DynamicTabItem x:Name="Holdings" Header="Holdings">
+                                <Grid>
+                                    <Grid.RowDefinitions>
+                                        <RowDefinition Height="Auto"/>
+                                        <RowDefinition Height="*"/>
+                                        <RowDefinition Height="Auto"/>                                
+                                        <RowDefinition Height="3*"/>
+                                    </Grid.RowDefinitions>
+                                    <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25"
+                                            Grid.Row="0" Margin="0,2">
+                                        <Label Content="Product Instances" HorizontalContentAlignment="Center"
+                                               VerticalContentAlignment="Center" />
+                                    </Border>
+                                    <local:ProductInstanceControl x:Name="ProductInstances" UseWaitCursor="False" Grid.Row="1"
+                                                                  OnChanged="ProductInstances_OnChanged"/>
+                                    
+                                    <sf:SfGridSplitter Grid.Row="2" Height="4"
+                                                       HorizontalAlignment="Stretch"
+                                                       Background="Transparent"
+                                                       ResizeBehavior="PreviousAndNext"
+                                                       Template="{StaticResource HorizontalSplitter}"
+                                                       PreviewStyle="{StaticResource HorizontalSplitterPreview}"/>
+                                    <DockPanel Grid.Row="3">
+                                    <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25"
+                                            DockPanel.Dock="Top" Margin="0,2">
+                                        <Label Content="Product Holdings" HorizontalContentAlignment="Center"
+                                               VerticalContentAlignment="Center" />
+                                    </Border>
+                                    <local:ProductHoldingControl x:Name="ProductHoldings" UseWaitCursor="false"
+                                                                 DockPanel.Dock="Top"/>
+                                    </DockPanel>
+                                </Grid>
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Movements" Header="Movements">
+                                <local:ProductMovementSummaryControl x:Name="ProductMovements" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Orders" Header="Orders">
+                                <local:ProductOrderSummaryControl x:Name="ProductOrders" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Kits" Header="Kits">
+                                <local:ProductKitControl x:Name="ProductKits" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Suppliers" Header="Suppliers">
+                                <local:ProductSuppliersControl x:Name="ProductSuppliers" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Customers" Header="Customers">
+                                <local:ProductCustomersControl x:Name="ProductCustomers" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                            <dynamicgrid:DynamicTabItem x:Name="Documents" Header="Documents">
+                                <local:ProductDocumentControl x:Name="ProductDocuments" UseWaitCursor="false" Grid.Row="1" Margin="0,2,0,0" />
+                            </dynamicgrid:DynamicTabItem>
                             
-                            <sf:SfGridSplitter Grid.Row="2" Height="4"
-                                               HorizontalAlignment="Stretch"
-                                               Background="Transparent"
-                                               ResizeBehavior="PreviousAndNext"
-                                               Template="{StaticResource HorizontalSplitter}"
-                                               PreviewStyle="{StaticResource HorizontalSplitterPreview}"/>
-                            <DockPanel Grid.Row="3">
-                            <Border BorderBrush="Gray" BorderThickness="0.75" Background="WhiteSmoke" Height="25"
-                                    DockPanel.Dock="Top" Margin="0,2">
-                                <Label Content="Product Holdings" HorizontalContentAlignment="Center"
-                                       VerticalContentAlignment="Center" />
+                            <dynamicgrid:DynamicTabItem x:Name="Spreadsheets" Header="Spreadsheets">
+                                <local:ProductSpreadsheetControl x:Name="ProductSpreadsheets" UseWaitCursor="false" />
+                            </dynamicgrid:DynamicTabItem>
+                            
+                        </dynamicgrid:DynamicTabControl>
+
+                        <DockPanel Grid.Row="1" Margin="2,5,2,0">
+                            <Border CornerRadius="0,0,0,0" BorderBrush="Gray" BorderThickness="0.75" DockPanel.Dock="Top"
+                                    Background="WhiteSmoke">
+                                <Label Content="Product Image" HorizontalContentAlignment="Center" />
+                            </Border>
+                            <Border BorderBrush="Gray" BorderThickness="0.75" Margin="0,2,0,0" DockPanel.Dock="Top"
+                                    Background="LightYellow">
+                                <Border.ContextMenu>
+                                    <ContextMenu x:Name="ImageMenu" Opened="ImageMenu_Opened">
+                                        <MenuItem x:Name="LoadImageFromFile" Header="Load From File"
+                                                  Click="LoadImageFromFile_Click" />
+                                        <MenuItem x:Name="SaveImageToFile" Header="Save To File" Click="SaveImageToFile_Click" />
+                                        <Separator />
+                                        <MenuItem x:Name="CopyImageToClipboard" Header="Copy To Clipboard"
+                                                  Click="CopyImageToClipboard_Click" />
+                                        <MenuItem x:Name="PasteImageFromClipboard" Header="Paste from Clipboard"
+                                                  Click="PasteImageFromClipboard_Click" />
+                                        <Separator />
+                                        <MenuItem x:Name="ClearImage" Header="Clear Image" Click="ClearImage_Click" />
+                                    </ContextMenu>
+                                </Border.ContextMenu>
+                                <Image x:Name="ProductImage" />
                             </Border>
-                            <local:ProductHoldingControl x:Name="ProductHoldings" UseWaitCursor="false"
-                                                         DockPanel.Dock="Top"/>
-                            </DockPanel>
-                        </Grid>
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Movements" Header="Movements">
-                        <local:ProductMovementSummaryControl x:Name="ProductMovements" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Orders" Header="Orders">
-                        <local:ProductOrderSummaryControl x:Name="ProductOrders" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Kits" Header="Kits">
-                        <local:ProductKitControl x:Name="ProductKits" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Suppliers" Header="Suppliers">
-                        <local:ProductSuppliersControl x:Name="ProductSuppliers" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Customers" Header="Customers">
-                        <local:ProductCustomersControl x:Name="ProductCustomers" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Documents" Header="Documents">
-                        <local:ProductDocumentControl x:Name="ProductDocuments" UseWaitCursor="false" Grid.Row="1" Margin="0,2,0,0" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                    <dynamicgrid:DynamicTabItem x:Name="Spreadsheets" Header="Spreadsheets">
-                        <local:ProductSpreadsheetControl x:Name="ProductSpreadsheets" UseWaitCursor="false" />
-                    </dynamicgrid:DynamicTabItem>
-                    
-                </dynamicgrid:DynamicTabControl>
 
-                <DockPanel Grid.Row="1" Margin="2,5,2,0">
-                    <Border CornerRadius="0,0,0,0" BorderBrush="Gray" BorderThickness="0.75" DockPanel.Dock="Top"
-                            Background="WhiteSmoke">
-                        <Label Content="Product Image" HorizontalContentAlignment="Center" />
-                    </Border>
-                    <Border BorderBrush="Gray" BorderThickness="0.75" Margin="0,2,0,0" DockPanel.Dock="Top"
-                            Background="LightYellow">
-                        <Border.ContextMenu>
-                            <ContextMenu x:Name="ImageMenu" Opened="ImageMenu_Opened">
-                                <MenuItem x:Name="LoadImageFromFile" Header="Load From File"
-                                          Click="LoadImageFromFile_Click" />
-                                <MenuItem x:Name="SaveImageToFile" Header="Save To File" Click="SaveImageToFile_Click" />
-                                <Separator />
-                                <MenuItem x:Name="CopyImageToClipboard" Header="Copy To Clipboard"
-                                          Click="CopyImageToClipboard_Click" />
-                                <MenuItem x:Name="PasteImageFromClipboard" Header="Paste from Clipboard"
-                                          Click="PasteImageFromClipboard_Click" />
-                                <Separator />
-                                <MenuItem x:Name="ClearImage" Header="Clear Image" Click="ClearImage_Click" />
-                            </ContextMenu>
-                        </Border.ContextMenu>
-                        <Image x:Name="ProductImage" />
-                    </Border>
+                        </DockPanel>
+                    </Grid>
 
-                </DockPanel>
-            </Grid>
+                </dynamicgrid:DynamicSplitPanel.Detail>
 
-        </dynamicgrid:DynamicSplitPanel.Detail>
+            </dynamicgrid:DynamicSplitPanel>
 
+        </dynamicgrid:DynamicSplitPanel.Detail>
     </dynamicgrid:DynamicSplitPanel>
-
 </UserControl>

+ 14 - 3
prs.desktop/Panels/Products/Master List/ProductsPanel.xaml.cs

@@ -88,9 +88,9 @@ namespace PRSDesktop
 
         public void Refresh()
         {
-            ProductDetails.IsEnabled = false;
-            Products.Refresh(false, true);
-            //RefreshSubPage(ProductDetails.SelectedContent as IProductGrid);
+            Groups.Refresh();
+            //ProductDetails.IsEnabled = false;
+            //Products.Refresh(false, true);
         }
 
         public void Heartbeat(TimeSpan time)
@@ -403,5 +403,16 @@ namespace PRSDesktop
 
             MessageBox.Show(string.Format("Cleared image from [{0}]", string.Join(", ", SelectedProducts())));
         }
+
+        private void Groups_OnOnSelectItem(CoreTreeNode node)
+        {
+            if (node != null)
+            {
+                Products.Groups = node.ID == CoreUtils.FullGuid
+                    ? null
+                    : Groups.Nodes.GetThisAndAllChildren(node.ID).ToArray();
+                Products.Refresh(false, true);
+            }
+        }
     }
 }

+ 1 - 1
prs.desktop/prsdesktop.iss

@@ -5,7 +5,7 @@
 #pragma verboselevel 9
 
 #define MyAppName "PRS Desktop"
-#define MyAppVersion "7.78a"
+#define MyAppVersion "7.78b"
 #define MyAppPublisher "PRS Digital"
 #define MyAppURL "https://www.prs-software.com.au"
 #define MyAppExeName "PRSDesktop.exe"

+ 1 - 1
prs.licensing/PRSLicensing.iss

@@ -5,7 +5,7 @@
 #pragma verboselevel 9
 
 #define MyAppName "PRS Licensing"
-#define MyAppVersion "7.78a"
+#define MyAppVersion "7.78b"
 #define MyAppPublisher "PRS Digital"
 #define MyAppURL "https://www.prs-software.com.au"
 #define MyAppExeName "PRSLicensing.exe"

+ 1 - 1
prs.server/PRSServer.iss

@@ -5,7 +5,7 @@
 #pragma verboselevel 9
 
 #define MyAppName "PRS Server"
-#define MyAppVersion "7.78a"
+#define MyAppVersion "7.78b"
 #define MyAppPublisher "PRS Digital"
 #define MyAppURL "https://www.prs-software.com.au"
 #define MyAppExeName "PRSServer.exe"