Parcourir la source

Added aggregates for JobRequisitionItem

Kenric Nugteren il y a 1 an
Parent
commit
c9df14b009

+ 43 - 0
prs.classes/Entities/Job/Requisitions/JobRequisitionItem.cs

@@ -66,6 +66,33 @@ namespace Comal.Classes
         public FormulaType Type => FormulaType.Virtual;
     }
 
+    public class JobRequisitionItemInStockAggregate : CoreAggregate<JobRequisitionItem, StockMovement, double>
+    {
+        public override Expression<Func<StockMovement, double>> Aggregate => x => x.Units;
+
+        public override Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<JobRequisitionItem, object>>> Links => new Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<JobRequisitionItem, object>>>
+        {
+            { x => x.JobRequisitionItem.ID, x => x.ID }
+        };
+
+        public override AggregateCalculation Calculation => AggregateCalculation.Sum;
+    }
+    public class JobRequisitionItemOnOrderAggregate : CoreAggregate<JobRequisitionItem, JobRequisitionItemPurchaseOrderItem, double>
+    {
+        public override Expression<Func<JobRequisitionItemPurchaseOrderItem, double>> Aggregate => x => x.PurchaseOrderItem.Qty;
+
+        public override Dictionary<Expression<Func<JobRequisitionItemPurchaseOrderItem, object>>, Expression<Func<JobRequisitionItem, object>>> Links => new Dictionary<Expression<Func<JobRequisitionItemPurchaseOrderItem, object>>, Expression<Func<JobRequisitionItem, object>>>
+        {
+            { x => x.JobRequisitionItem.ID, x => x.ID }
+        };
+
+        public override AggregateCalculation Calculation => AggregateCalculation.Sum;
+
+        public override Filter<JobRequisitionItemPurchaseOrderItem>? Filter =>
+            new Filter<JobRequisitionItemPurchaseOrderItem>(x => x.PurchaseOrderItem.ReceivedDate).IsEqualTo(null);
+    }
+
+
     [Caption("Items")]
     [UserTracking(typeof(Job))]
     public class JobRequisitionItem : StockEntity, IRemotable, IPersistent, IOneToMany<JobRequisition>,
@@ -121,13 +148,25 @@ namespace Comal.Classes
         public SupplierLink Supplier { get; set; }
 
         [EnumLookupEditor(typeof(JobRequisitionItemStatus), Editable = Editable.Disabled)]
+        [EditorSequence(9)]
         [LoggableProperty]
         [RequiredColumn]
         public JobRequisitionItemStatus Status { get; set; } = JobRequisitionItemStatus.NotChecked;
 
+        [Aggregate(typeof(JobRequisitionItemInStockAggregate))]
+        [DoubleEditor(Editable = Editable.Disabled)]
+        [EditorSequence(10)]
+        public double InStock { get; set; }
+
+        [Aggregate(typeof(JobRequisitionItemOnOrderAggregate))]
+        [DoubleEditor(Editable = Editable.Disabled)]
+        [EditorSequence(11)]
+        public double OnOrder { get; set; }
+
         [EntityRelationship(DeleteAction.SetNull)]
         [RequiredColumn]
         [Obsolete("Replaced with JobRequisitionItemPurchaseOrderItem")]
+        [NullEditor]
         public PurchaseOrderItemLink PurchaseOrderItem { get; set; }
 
         [Aggregate(typeof(JobRequisitionItemPurchaseOrderNumberAggregate))]
@@ -135,16 +174,20 @@ namespace Comal.Classes
         public string PurchaseOrderNumbers { get; set; }
 
         [RequiredColumn]
+        [EditorSequence(12)]
         public DateTime Cancelled { get; set; } = DateTime.MinValue;
 
         [RequiredColumn]
+        [EditorSequence(13)]
         public DateTime Archived { get; set; } = DateTime.MinValue;
 
         [RequiredColumn]
         [Obsolete("Replaced with JobRequisitionItemPurchaseOrderItem")]
+        [NullEditor]
         public DateTime Ordered { get; set; } = DateTime.MinValue;
 
         [RequiredColumn]
+        [EditorSequence(14)]
         public DateTime OrderRequired { get; set; } = DateTime.MinValue;
 
         [NullEditor]

+ 146 - 147
prs.desktop/Panels/Jobs/JobRequisitionItemGrid.cs

@@ -11,175 +11,174 @@ using InABox.DynamicGrid;
 using InABox.Wpf;
 using InABox.WPF;
 
-namespace PRSDesktop
+namespace PRSDesktop;
+
+internal class JobRequisitionItemGrid : DynamicDataGrid<JobRequisitionItem>
 {
-    internal class JobRequisitionItemGrid : DynamicDataGrid<JobRequisitionItem>
+    private Button CancelItemsButton;
+
+    public JobRequisitionItemGrid()
+    {
+        CancelItemsButton = AddButton("Cancel Items", PRSDesktop.Resources.disabled.AsBitmapImage(), CancelItems);
+        CancelItemsButton.Visibility = Security.CanEdit<JobRequisition>() && Security.CanEdit<JobRequisitionItem>()
+            ? System.Windows.Visibility.Visible
+            : System.Windows.Visibility.Hidden;
+    }
+
+    protected override void SelectItems(CoreRow[]? rows)
     {
-        private Button CancelItemsButton;
+        base.SelectItems(rows);
+
+        CancelItemsButton.IsEnabled = rows is not null && rows.Length > 0;
+    }
 
-        public JobRequisitionItemGrid()
+    private bool CancelItems(Button button, CoreRow[] rows)
+    {
+        if(rows.Length == 0)
         {
-            CancelItemsButton = AddButton("Cancel Items", PRSDesktop.Resources.disabled.AsBitmapImage(), CancelItems);
-            CancelItemsButton.Visibility = Security.CanEdit<JobRequisition>() && Security.CanEdit<JobRequisitionItem>()
-                ? System.Windows.Visibility.Visible
-                : System.Windows.Visibility.Hidden;
+            MessageWindow.ShowMessage("Please select at least one item to cancel.", "Select items");
+            return false;
         }
 
-        protected override void SelectItems(CoreRow[]? rows)
-        {
-            base.SelectItems(rows);
+        // Reloading so I can ensure the correct columns without having to add hidden columns to JobRequisitionGrid.
+        var oldRequi = Client.Query(
+            new Filter<JobRequisition>(x => x.ID).IsEqualTo(Requisition.ID),
+            new Columns<JobRequisition>(x => x.Description)
+					.Add(x => x.Number)
+                .Add(x => x.DueDate))
+            .ToObjects<JobRequisition>()
+            .First();
 
-            CancelItemsButton.IsEnabled = rows is not null && rows.Length > 0;
-        }
+        var oldRequiItems = Client.Query(
+            new Filter<JobRequisitionItem>(x => x.ID).InList(rows.Select(x => x.Get<JobRequisitionItem, Guid>(x => x.ID)).ToArray()),
+            new Columns<JobRequisitionItem>(x => x.Qty)
+                .Add(x => x.Sequence)
+                .Add(x => x.Job.ID)
+                .Add(x => x.Product.ID)
+                .Add(x => x.Product.Code)
+                .Add(x => x.Style.ID)
+                .Add(x => x.Style.Code)
+                .Add(x => x.Style.Description)
+                .Add(x => x.Dimensions.Unit.ID)
+                .Add(x => x.Dimensions.Quantity)
+                .Add(x => x.Dimensions.Length)
+                .Add(x => x.Dimensions.Width)
+                .Add(x => x.Dimensions.Height)
+                .Add(x => x.Dimensions.Weight)
+                .Add(x => x.Dimensions.UnitSize)
+                .Add(x => x.Supplier.ID));
 
-        private bool CancelItems(Button button, CoreRow[] rows)
+        var requisition = new JobRequisition
         {
-            if(rows.Length == 0)
-            {
-                MessageWindow.ShowMessage("Please select at least one item to cancel.", "Select items");
-                return false;
-            }
+            Description = $"Adjustment Requisition for Requisition {oldRequi.Number}",
+            DueDate = oldRequi.DueDate
+        };
+        requisition.Job.ID = Requisition.Job.ID;
+        requisition.Job.Synchronise(Requisition.Job);
 
-            // Reloading so I can ensure the correct columns without having to add hidden columns to JobRequisitionGrid.
-            var oldRequi = Client.Query(
-                new Filter<JobRequisition>(x => x.ID).IsEqualTo(Requisition.ID),
-                new Columns<JobRequisition>(x => x.Description)
-					.Add(x => x.Number)
-                    .Add(x => x.DueDate))
-                .ToObjects<JobRequisition>()
-                .First();
-
-            var oldRequiItems = Client.Query(
-                new Filter<JobRequisitionItem>(x => x.ID).InList(rows.Select(x => x.Get<JobRequisitionItem, Guid>(x => x.ID)).ToArray()),
-                new Columns<JobRequisitionItem>(x => x.Qty)
-                    .Add(x => x.Sequence)
-                    .Add(x => x.Job.ID)
-                    .Add(x => x.Product.ID)
-                    .Add(x => x.Product.Code)
-                    .Add(x => x.Style.ID)
-                    .Add(x => x.Style.Code)
-                    .Add(x => x.Style.Description)
-                    .Add(x => x.Dimensions.Unit.ID)
-                    .Add(x => x.Dimensions.Quantity)
-                    .Add(x => x.Dimensions.Length)
-                    .Add(x => x.Dimensions.Width)
-                    .Add(x => x.Dimensions.Height)
-                    .Add(x => x.Dimensions.Weight)
-                    .Add(x => x.Dimensions.UnitSize)
-                    .Add(x => x.Supplier.ID));
-
-            var requisition = new JobRequisition
+        var requiItems = new List<JobRequisitionItem>();
+        foreach(var oldItem in oldRequiItems.ToObjects<JobRequisitionItem>())
+        {
+            var newItem = new JobRequisitionItem
             {
-                Description = $"Adjustment Requisition for Requisition {oldRequi.Number}",
-                DueDate = oldRequi.DueDate
+                Notes = "Adjustment Requisition item",
+                Qty = -oldItem.Qty,
+                Sequence = oldItem.Sequence
             };
-            requisition.Job.ID = Requisition.Job.ID;
-            requisition.Job.Synchronise(Requisition.Job);
-
-            var requiItems = new List<JobRequisitionItem>();
-            foreach(var oldItem in oldRequiItems.ToObjects<JobRequisitionItem>())
-            {
-                var newItem = new JobRequisitionItem
-                {
-                    Notes = "Adjustment Requisition item",
-                    Qty = -oldItem.Qty,
-                    Sequence = oldItem.Sequence
-                };
-                newItem.Job.ID = requisition.Job.ID;
-                newItem.Job.Synchronise(requisition.Job);
-                newItem.Product.ID = oldItem.Product.ID;
-                newItem.Product.Synchronise(oldItem.Product);
-                newItem.Style.ID = oldItem.Style.ID;
-                newItem.Style.Synchronise(oldItem.Style);
-                newItem.Dimensions.CopyFrom(oldItem.Dimensions);
-                newItem.Supplier.ID = oldItem.Supplier.ID;
-                newItem.Supplier.Synchronise(oldItem.Supplier);
-                requiItems.Add(newItem);
-            }
+            newItem.Job.ID = requisition.Job.ID;
+            newItem.Job.Synchronise(requisition.Job);
+            newItem.Product.ID = oldItem.Product.ID;
+            newItem.Product.Synchronise(oldItem.Product);
+            newItem.Style.ID = oldItem.Style.ID;
+            newItem.Style.Synchronise(oldItem.Style);
+            newItem.Dimensions.CopyFrom(oldItem.Dimensions);
+            newItem.Supplier.ID = oldItem.Supplier.ID;
+            newItem.Supplier.Synchronise(oldItem.Supplier);
+            requiItems.Add(newItem);
+        }
 
-            var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicGrid<>), typeof(JobRequisition));
-            if (grid.EditItems(new JobRequisition[] { requisition }, t =>
-            {
-                if (t == typeof(JobRequisitionItem))
-                {
-                    var table = new CoreTable();
-                    table.LoadColumns(typeof(JobRequisitionItem));
-                    table.LoadRows(requiItems);
-                    return table;
-                }
-                return null;
-            }))
-            {
-                MessageWindow.ShowMessage($"Created requisition {requisition.Number}", "Created Requisition");
-                return true;
-            }
-            else
+        var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicGrid<>), typeof(JobRequisition));
+        if (grid.EditItems(new JobRequisition[] { requisition }, t =>
+        {
+            if (t == typeof(JobRequisitionItem))
             {
-                return false;
+                var table = new CoreTable();
+                table.LoadColumns(typeof(JobRequisitionItem));
+                table.LoadRows(requiItems);
+                return table;
             }
-        }
-
-        protected override void DoReconfigure(FluentList<DynamicGridOption> options)
+            return null;
+        }))
         {
-            base.DoReconfigure(options);
-            options.AddRange(
-                DynamicGridOption.RecordCount,
-                DynamicGridOption.SelectColumns,
-                DynamicGridOption.FilterRows,
-                DynamicGridOption.MultiSelect
-                );
+            MessageWindow.ShowMessage($"Created requisition {requisition.Number}", "Created Requisition");
+            return true;
         }
-        
-        public JobRequisition Requisition { get; set; }
-
-        protected override void Reload(Filters<JobRequisitionItem> criteria, Columns<JobRequisitionItem> columns,
-            ref SortOrder<JobRequisitionItem>? sort,
-            Action<CoreTable?, Exception?> action)
+        else
         {
-            criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.ID).IsEqualTo(Requisition.ID));
-            base.Reload(criteria, columns, ref sort, action);
+            return false;
         }
+    }
 
-        protected override JobRequisitionItem CreateItem()
-        {
-            var result = base.CreateItem();
-            result.Requisition.ID = Requisition.ID;
-            result.Requisition.Synchronise(Requisition);
-            result.Job.ID = Requisition.Job.ID;
-            result.Job.Synchronise(Requisition.Job);
-            result.Qty = 1;
-            return result;
-        }
-        
-        protected override void OnAfterEditorValueChanged(DynamicEditorGrid? grid, JobRequisitionItem[] items, AfterEditorValueChangedArgs args, Dictionary<string, object?> changes)
-        {
-            base.OnAfterEditorValueChanged(grid, items, args, changes);
-            if (args.ColumnName.Equals("Product.ID") || args.ColumnName.Equals("Dimensions") || args.ColumnName.StartsWith("Dimensions.") || args.ColumnName.Equals("Style.ID") || args.ColumnName.Equals("Supplier.ID"))
-            {
-                JobRequisitionItem.UpdateCosts(
-                    items, 
-                    changes
-                );
-            }
-        }
+    protected override void DoReconfigure(FluentList<DynamicGridOption> options)
+    {
+        base.DoReconfigure(options);
+        options.AddRange(
+            DynamicGridOption.RecordCount,
+            DynamicGridOption.SelectColumns,
+            DynamicGridOption.FilterRows,
+            DynamicGridOption.MultiSelect
+            );
+    }
+    
+    public JobRequisition Requisition { get; set; }
+
+    protected override void Reload(Filters<JobRequisitionItem> criteria, Columns<JobRequisitionItem> columns,
+        ref SortOrder<JobRequisitionItem>? sort,
+        Action<CoreTable?, Exception?> action)
+    {
+        criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.ID).IsEqualTo(Requisition.ID));
+        base.Reload(criteria, columns, ref sort, action);
+    }
 
-        public override DynamicGridColumns GenerateColumns()
+    protected override JobRequisitionItem CreateItem()
+    {
+        var result = base.CreateItem();
+        result.Requisition.ID = Requisition.ID;
+        result.Requisition.Synchronise(Requisition);
+        result.Job.ID = Requisition.Job.ID;
+        result.Job.Synchronise(Requisition.Job);
+        result.Qty = 1;
+        return result;
+    }
+    
+    protected override void OnAfterEditorValueChanged(DynamicEditorGrid? grid, JobRequisitionItem[] items, AfterEditorValueChangedArgs args, Dictionary<string, object?> changes)
+    {
+        base.OnAfterEditorValueChanged(grid, items, args, changes);
+        if (args.ColumnName.Equals("Product.ID") || args.ColumnName.Equals("Dimensions") || args.ColumnName.StartsWith("Dimensions.") || args.ColumnName.Equals("Style.ID") || args.ColumnName.Equals("Supplier.ID"))
         {
-            var columns = new DynamicGridColumns();
-            columns.Add<JobRequisitionItem, DateTime>(x => x.Created, 80, "Date", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, string>(x => x.Requisition.Job.JobNumber, 70, "Job", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, int>(x => x.Requisition.Number, 50, "NO.", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, string>(x => x.Product.Code, 70, "Code", "", Alignment.MiddleLeft);
-            columns.Add<JobRequisitionItem, string>(x => x.Product.Name, 200, "Product Name", "", Alignment.MiddleLeft);
-            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.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);
-
-            columns.AddRange(base.GenerateColumns());
-            return columns;
+            JobRequisitionItem.UpdateCosts(
+                items, 
+                changes
+            );
         }
     }
+
+    public override DynamicGridColumns GenerateColumns()
+    {
+        var columns = new DynamicGridColumns();
+        columns.Add<JobRequisitionItem, DateTime>(x => x.Created, 80, "Date", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, string>(x => x.Requisition.Job.JobNumber, 70, "Job", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, int>(x => x.Requisition.Number, 50, "NO.", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, string>(x => x.Product.Code, 70, "Code", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, string>(x => x.Product.Name, 200, "Product Name", "", Alignment.MiddleLeft);
+        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.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);
+
+        columns.AddRange(base.GenerateColumns());
+        return columns;
+    }
 }

+ 3 - 0
prs.desktop/Panels/Products/Reservation Management/JobRequisitionReviewGrid.cs

@@ -130,6 +130,9 @@ 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, JobRequisitionItemStatus>(x => x.Status, 70, "Status", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, double>(x => x.InStock, 50, "Stock", "", Alignment.MiddleLeft);
+        columns.Add<JobRequisitionItem, double>(x => x.OnOrder, 50, "On Order", "", 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;