Ver código fonte

Progress claim window now takes all movements and assignments into account.

Kenric Nugteren 10 meses atrás
pai
commit
95ae7c58d6

+ 13 - 0
prs.classes/Entities/Job/JobScopes/JobScope.cs

@@ -137,6 +137,19 @@ namespace Comal.Classes
         [Formula(typeof(JobScopeUninvoicedExTax))]
         public double UninvoiceIncTax { get; set; }
 
+        private class MaterialsExTaxFormula : ComplexFormulaGenerator<JobScope, double>
+        {
+            public override IComplexFormulaNode<JobScope, double> GetFormula() =>
+                Formula(FormulaOperator.Subtract,
+                    Aggregate<StockMovement>(AggregateCalculation.Sum, x => x.Property(x => x.Value))
+                        .WithFilter(
+                            new Filter<StockMovement>(x => x.Type).IsEqualTo(StockMovementType.Issue))
+                        .WithLink(x => x.JobScope.ID, x => x.ID));
+        }
+        [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
+        [ComplexFormula(typeof(MaterialsExTaxFormula))]
+        public double MaterialsExTax { get; set; }
+
         private class UninvoicedMaterial : ComplexFormulaGenerator<JobScope, double>
         {
             public override IComplexFormulaNode<JobScope, double> GetFormula() =>

+ 35 - 55
prs.desktop/Panels/Invoices/ProgressClaimGrid.cs → prs.desktop/Panels/Invoices/ProgressClaim/ProgressClaimGrid.cs

@@ -2,6 +2,7 @@
 using InABox.Clients;
 using InABox.Core;
 using InABox.DynamicGrid;
+using PRSDesktop.Panels.Invoices;
 using Syncfusion.Windows.Shared;
 using System;
 using System.Collections.Generic;
@@ -99,11 +100,11 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
         options.SelectColumns = false;
     }
 
-    private Job job;
-    private JobScope[] scopes;
-    private Invoice[] invoices;
-    private Invoice invoice;
-    private List<InvoiceLine> invoicelines;
+    private Job Job;
+    private JobScope[] Scopes;
+    private Invoice[] Invoices;
+    private Invoice Invoice;
+    private List<InvoiceLine> InvoiceLines;
     
     private bool _loadedData = false;
     private void LoadData()
@@ -118,7 +119,7 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
                 .Add(x => x.TaxCode.Rate)
                 .Add(x=>x.Tax)
                 .Add(x => x.Description)
-                .Add(x => x.UninvoicedMaterialsExTax)
+                .Add(x => x.MaterialsExTax)
                 .Add(x => x.Job.DefaultScope.ID)
                 .Add(x=>x.Type);
 
@@ -133,6 +134,7 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
         query.Add(
             new Filter<Job>(x=>x.ID).IsEqualTo(JobID),
             Columns.None<Job>()
+                .Add(x => x.ID)
                 .Add(x=>x.Retention.Maximum)
                 .Add(x=>x.Retention.Rate)
                 .Add(x=>x.Retention.IncludeVariations)
@@ -144,43 +146,49 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
                 columns);
         
         query.Add(
-            new Filter<Assignment>(x => x.JobLink.ID).IsEqualTo(JobID)
-                .And(x => x.Invoice.ID).IsEqualTo(Guid.Empty),
+            new Filter<Assignment>(x => x.JobLink.ID).IsEqualTo(JobID),
             Columns.None<Assignment>().Add(x => x.JobScope.ID)
                 .Add(x => x.Actual.Duration)
                 .Add(x => x.EmployeeLink.HourlyRate));
 
-        query.Add(new Filter<Invoice>(x=>x.JobLink.ID).IsEqualTo(JobID));
+        query.Add(
+            new Filter<Invoice>(x=>x.JobLink.ID).IsEqualTo(JobID),
+            Columns.None<Invoice>().Add(x => x.ID).Add(x => x.Retained));
         
         if (InvoiceID != Guid.Empty)
-            query.Add(new Filter<InvoiceLine>(x=>x.InvoiceLink.ID).IsEqualTo(InvoiceID));
+            query.Add(
+                new Filter<InvoiceLine>(x=>x.InvoiceLink.ID).IsEqualTo(InvoiceID),
+                Columns.None<InvoiceLine>()
+                    .Add(x => x.ID)
+                    .Add(x => x.Scope.ID)
+                    .Add(x => x.ExTax));
         
         query.Query();
 
-        job = query.Get<Job>().ToObjects<Job>().FirstOrDefault() ?? new Job();
+        Job = query.Get<Job>().ToObjects<Job>().FirstOrDefault() ?? new Job();
 
-        scopes = query.Get<JobScope>().ToArray<JobScope>();
+        Scopes = query.Get<JobScope>().ToArray<JobScope>();
 
         var assignments = query.Get<Assignment>().ToObjects<Assignment>()
             .GroupBy(x => x.JobScope.ID)
             .ToDictionary(x => x.Key, x => x.Sum(x => x.Actual.Duration.TotalHours * x.EmployeeLink.HourlyRate));
 
-        invoices = query.Get<Invoice>().ToArray<Invoice>();
+        Invoices = query.Get<Invoice>().ToArray<Invoice>();
         
-        invoice = invoices.FirstOrDefault(x => x.ID == InvoiceID) ?? new Invoice();
+        Invoice = Invoices.FirstOrDefault(x => x.ID == InvoiceID) ?? new Invoice();
         
-        invoicelines = InvoiceID != Guid.Empty
+        InvoiceLines = InvoiceID != Guid.Empty
             ? query.Get<InvoiceLine>().ToObjects<InvoiceLine>().ToList()
             : new List<InvoiceLine>();
         
         
         var items = new List<ProgressClaim>();
-        foreach(var scope in scopes)
+        foreach(var scope in Scopes)
         {
             var newItem = new ProgressClaim();
             newItem.JobScope.CopyFrom(scope);
             
-            var invoiceline = invoicelines.FirstOrDefault(x =>
+            var invoiceline = InvoiceLines.FirstOrDefault(x =>
                 x.Scope.ID == scope.ID || (x.Scope.ID == Guid.Empty && scope.ID == scope.Job.DefaultScope.ID));
             if (invoiceline != null)
             {
@@ -196,7 +204,7 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
                 newItem.PercentCost = newItem.PreviouslyClaimedPercent;
                 newItem.Cost = 0;
             }
-            newItem.Materials = scope.UninvoicedMaterialsExTax;
+            newItem.Materials = scope.MaterialsExTax;
             newItem.Labour = assignments.GetValueOrDefault(scope.ID);
             
             items.Add(newItem);
@@ -216,8 +224,8 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
 
     private void CalculateTotals()
     {
-        Guid[] contractscopeids = scopes.Where(x => x.Type == JobScopeType.Contract).Select(x => x.ID).ToArray();
-        Guid[] variationscopeids = scopes.Where(x => x.Type != JobScopeType.Contract).Select(x => x.ID).ToArray();
+        Guid[] contractscopeids = Scopes.Where(x => x.Type == JobScopeType.Contract).Select(x => x.ID).ToArray();
+        Guid[] variationscopeids = Scopes.Where(x => x.Type != JobScopeType.Contract).Select(x => x.ID).ToArray();
         
         ProjectContract = Items.Where(x => contractscopeids.Contains(x.JobScope.ID)).Sum(x => x.JobScope.ExTax);
         
@@ -271,19 +279,19 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
             ? 0.0
             : CompletedSubTotal * 100.0 / ProjectSubTotal;
         
-        var retentionbase = job.Retention.IncludeVariations
+        var retentionbase = Job.Retention.IncludeVariations
             ? ProjectSubTotal
             : ProjectContract;
-        ProjectRetention = retentionbase * job.Retention.Maximum / 100.0;
-        ProjectRetentionPercent = job.Retention.Maximum;
+        ProjectRetention = retentionbase * Job.Retention.Maximum / 100.0;
+        ProjectRetentionPercent = Job.Retention.Maximum;
         
         
-        PreviousRetention = invoices.Where(x => x.ID != InvoiceID).Sum(x=>x.Retained);
+        PreviousRetention = Invoices.Where(x => x.ID != InvoiceID).Sum(x=>x.Retained);
         PreviousRetentionPercent = retentionbase.IsEffectivelyEqual(0.0)
             ? 0.0
             : PreviousRetention * 100.0 / retentionbase;
         
-        CurrentRetention = Math.Min(ProjectRetention - PreviousRetention,CurrentSubTotal * job.Retention.Rate / 100.0);
+        CurrentRetention = Math.Min(ProjectRetention - PreviousRetention,CurrentSubTotal * Job.Retention.Rate / 100.0);
         CurrentRetentionPercent = retentionbase.IsEffectivelyEqual(0.0)
             ? 0.0
             : CurrentRetention * 100.0 / retentionbase;
@@ -336,42 +344,14 @@ public class ProgressClaimGrid : DynamicItemsListGrid<ProgressClaim>
             var claim = LoadItem(args.Row);
             if(new Column<ProgressClaim>(x => x.Materials).IsEqualTo(gridColumn.ColumnName))
             {
-                var grid = (DynamicGridUtils.CreateDynamicGrid<StockMovement>(typeof(DynamicDataGrid<>)) as DynamicDataGrid<StockMovement>)!;
-                grid.ColumnsTag = $"{nameof(ProgressClaim)}.Materials";
-                grid.Reconfigure(options =>
-                {
-                    options.Clear();
-                    options.FilterRows = true;
-                    options.SelectColumns = true;
-                });
-
-                grid.OnDefineFilter += t =>
-                {
-                    return new Filter<StockMovement>(x => x.Type).IsEqualTo(StockMovementType.Issue)
-                        .And(x => x.Invoice.ID).IsEqualTo(Guid.Empty)
-                        .And(x => x.JobScope.ID).IsEqualTo(claim.JobScope.ID);
-                };
+                var grid = new ProgressClaimMaterialsGrid(claim, Invoice);
 
                 var window = DynamicGridUtils.CreateGridWindow($"Materials", grid);
                 window.ShowDialog();
             }
             else if(new Column<ProgressClaim>(x => x.Labour).IsEqualTo(gridColumn.ColumnName))
             {
-                var grid = (DynamicGridUtils.CreateDynamicGrid<Assignment>(typeof(DynamicDataGrid<>)) as DynamicDataGrid<Assignment>)!;
-                grid.ColumnsTag = $"{nameof(ProgressClaim)}.Labour";
-                grid.Reconfigure(options =>
-                {
-                    options.Clear();
-                    options.FilterRows = true;
-                    options.SelectColumns = true;
-                });
-
-                grid.OnDefineFilter += t =>
-                {
-                    return new Filter<Assignment>(x => x.JobLink.ID).IsEqualTo(JobID)
-                        .And(x => x.Invoice.ID).IsEqualTo(Guid.Empty)
-                        .And(x => x.JobScope.ID).IsEqualTo(claim.JobScope.ID);
-                };
+                var grid = new ProgressClaimLabourGrid(claim, Invoice, Job);
 
                 var window = DynamicGridUtils.CreateGridWindow($"Labour", grid);
                 window.ShowDialog();

+ 86 - 0
prs.desktop/Panels/Invoices/ProgressClaim/ProgressClaimLabourGrid.cs

@@ -0,0 +1,86 @@
+using Comal.Classes;
+using InABox.Core;
+using InABox.DynamicGrid;
+using InABox.WPF;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Media;
+
+namespace PRSDesktop.Panels.Invoices;
+
+internal class ProgressClaimLabourGrid : DynamicDataGrid<Assignment>, ISpecificGrid
+{
+    public ProgressClaim Claim { get; set; }
+
+    public Invoice? Invoice { get; set; }
+
+    public Job Job { get; set; }
+
+    public ProgressClaimLabourGrid(ProgressClaim claim, Invoice? invoice, Job job)
+    {
+        Claim = claim;
+        Invoice = invoice;
+        Job = job;
+    }
+
+    protected override void Init()
+    {
+        base.Init();
+
+        HiddenColumns.Add(x => x.Invoice.ID);
+
+        ColumnsTag = $"{nameof(ProgressClaim)}.Labour";
+    }
+
+    protected override IDynamicGridUIComponent<Assignment> CreateUIComponent()
+    {
+        return new UIComponent(this);
+    }
+    private class UIComponent : DynamicGridGridUIComponent<Assignment>
+    {
+        private ProgressClaimLabourGrid Grid;
+
+        public UIComponent(ProgressClaimLabourGrid grid)
+        {
+            Parent = grid;
+            Grid = grid;
+        }
+
+        protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)
+        {
+            var invoiceID = row.Get<Assignment, Guid>(x => x.Invoice.ID);
+            if(invoiceID == (Grid.Invoice?.ID ?? Guid.Empty))
+            {
+                return Colors.LightGreen.ToBrush(0.5);
+            }
+            else
+            {
+                return Colors.Silver.ToBrush(0.5);
+            }
+        }
+    }
+
+    protected override void DoReconfigure(DynamicGridOptions options)
+    {
+        base.DoReconfigure(options);
+
+        options.FilterRows = true;
+        options.SelectColumns = true;
+    }
+
+    public override DynamicGridColumns GenerateColumns()
+    {
+        return base.GenerateColumns();
+    }
+
+    protected override void Reload(Filters<Assignment> criteria, Columns<Assignment> columns, ref SortOrder<Assignment>? sort, CancellationToken token, Action<CoreTable?, Exception?> action)
+    {
+        criteria.Add(new Filter<Assignment>(x => x.JobScope.ID).IsEqualTo(Claim.JobScope.ID));
+        criteria.Add(new Filter<Assignment>(x => x.JobLink.ID).IsEqualTo(Job.ID));
+        base.Reload(criteria, columns, ref sort, token, action);
+    }
+}

+ 83 - 0
prs.desktop/Panels/Invoices/ProgressClaim/ProgressClaimMaterialsGrid.cs

@@ -0,0 +1,83 @@
+using Comal.Classes;
+using InABox.Core;
+using InABox.DynamicGrid;
+using InABox.WPF;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Media;
+
+namespace PRSDesktop.Panels.Invoices;
+
+internal class ProgressClaimMaterialsGrid : DynamicDataGrid<StockMovement>, ISpecificGrid
+{
+    public ProgressClaim Claim { get; set; }
+
+    public Invoice? Invoice { get; set; }
+
+    public ProgressClaimMaterialsGrid(ProgressClaim claim, Invoice? invoice)
+    {
+        Claim = claim;
+        Invoice = invoice;
+    }
+
+    protected override void Init()
+    {
+        base.Init();
+
+        HiddenColumns.Add(x => x.Invoice.ID);
+
+        ColumnsTag = $"{nameof(ProgressClaim)}.Materials";
+    }
+
+    protected override IDynamicGridUIComponent<StockMovement> CreateUIComponent()
+    {
+        return new UIComponent(this);
+    }
+    private class UIComponent : DynamicGridGridUIComponent<StockMovement>
+    {
+        private ProgressClaimMaterialsGrid Grid;
+
+        public UIComponent(ProgressClaimMaterialsGrid grid)
+        {
+            Parent = grid;
+            Grid = grid;
+        }
+
+        protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)
+        {
+            var invoiceID = row.Get<StockMovement, Guid>(x => x.Invoice.ID);
+            if(invoiceID == (Grid.Invoice?.ID ?? Guid.Empty))
+            {
+                return Colors.LightGreen.ToBrush(0.5);
+            }
+            else
+            {
+                return Colors.Silver.ToBrush(0.5);
+            }
+        }
+    }
+
+    protected override void DoReconfigure(DynamicGridOptions options)
+    {
+        base.DoReconfigure(options);
+
+        options.FilterRows = true;
+        options.SelectColumns = true;
+    }
+
+    public override DynamicGridColumns GenerateColumns()
+    {
+        return StockMovementGrid.StandardColumns();
+    }
+
+    protected override void Reload(Filters<StockMovement> criteria, Columns<StockMovement> columns, ref SortOrder<StockMovement>? sort, CancellationToken token, Action<CoreTable?, Exception?> action)
+    {
+        criteria.Add(new Filter<StockMovement>(x => x.Type).IsEqualTo(StockMovementType.Issue));
+        criteria.Add(new Filter<StockMovement>(x => x.JobScope.ID).IsEqualTo(Claim.JobScope.ID));
+        base.Reload(criteria, columns, ref sort, token, action);
+    }
+}

+ 0 - 0
prs.desktop/Panels/Invoices/ProgressClaimWindow.xaml → prs.desktop/Panels/Invoices/ProgressClaim/ProgressClaimWindow.xaml


+ 0 - 0
prs.desktop/Panels/Invoices/ProgressClaimWindow.xaml.cs → prs.desktop/Panels/Invoices/ProgressClaim/ProgressClaimWindow.xaml.cs