using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Security; using InABox.Clients; using InABox.Core; namespace Comal.Classes { public class JobScopeInvoiceExTax : CoreAggregate { public override Expression> Aggregate => x => x.ExTax; public override AggregateCalculation Calculation => AggregateCalculation.Sum; public override Dictionary>, Expression>> Links => new Dictionary>, Expression>>() { { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID } }; } public class JobScopeInvoiceTax : CoreAggregate { public override Expression> Aggregate => x => x.Tax; public override AggregateCalculation Calculation => AggregateCalculation.Sum; public override Dictionary>, Expression>> Links => new Dictionary>, Expression>>() { { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID } }; } public class JobScopeInvoiceIncTax : CoreAggregate { public override Expression> Aggregate => x => x.IncTax; public override AggregateCalculation Calculation => AggregateCalculation.Sum; public override Dictionary>, Expression>> Links => new Dictionary>, Expression>>() { { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID } }; } public class JobScopeUninvoicedExTax : IFormula { public Expression> Value => x => x.ExTax; public Expression>[] Modifiers => new Expression>[] { x => x.InvoiceExTax }; public FormulaOperator Operator => FormulaOperator.Subtract; public FormulaType Type => FormulaType.Virtual; } public interface IJobScopedItem { JobLink JobLink { get; set; } JobScopeLink JobScope { get; set; } } [UserTracking(typeof(Job))] public class JobScope : Entity, IRemotable, IPersistent, ITaxable, IStringAutoIncrement, ILicense { [NullEditor] public InternalJobLink Job { get; set; } [EnumLookupEditor(typeof(JobScopeType), Visible = Visible.Default)] [EditorSequence(1)] public JobScopeType Type { get; set; } = JobScopeType.Variation; [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)] [EditorSequence(2)] public string Number { get; set; } [MemoEditor(Visible = Visible.Default)] [EditorSequence(3)] public string Description { get; set; } [EditorSequence(4)] [TextBoxEditor] public string SourceRef{ get; set; } private class JobScopeLookup : LookupDefinitionGenerator { public override Filter DefineFilter(JobScope[] items) { if (items?.Any() != true) return Filter.None(); var data = Client.Query( new Filter(x=>x.Job.ID).IsEqualTo(items.First().Job.ID), Columns.None().Add(x => x.ID).Add(x => x.Parent.ID)); var nodes = new CoreTreeNodes(); nodes.Load(data, x => x.ID, x => x.Parent.ID); var exclusions = items.SelectMany(x => nodes.GetChildren(x.ID)).ToArray(); var ids = exclusions.Select(x => x.ID).ToArray(); return new Filter(x=>x.Job.ID).IsEqualTo(items.First().Job.ID).And(x => x.ID).NotInList(ids); } public override Columns DefineFilterColumns() => Columns.None().Add(x => x.ID).Add(x => x.Parent.ID).Add(x => x.Number); } [LookupDefinition(typeof(JobScopeLookup))] [EditorSequence(4)] public JobScopeLink Parent { get; set; } [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Default)] [EditorSequence(5)] public double ExTax { get; set; } [EditorSequence(6)] public TaxCodeLink TaxCode { get; set; } [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional)] [EditorSequence(7)] public double IncTax { get; set; } [EditorSequence(8)] public JobScopeStatusLink Status { get; set; } [CurrencyEditor(Visible = Visible.Default, Editable = Editable.Hidden, Summary = Summary.Sum)] [Aggregate(typeof(JobScopeInvoiceExTax))] public double InvoiceExTax { get; set; } [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)] [Aggregate(typeof(JobScopeInvoiceTax))] public double InvoiceTax { get; set; } [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)] [Aggregate(typeof(JobScopeInvoiceIncTax))] public double InvoiceIncTax { get; set; } [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)] [Formula(typeof(JobScopeUninvoicedExTax))] public double UninvoiceIncTax { get; set; } private class MaterialsExTaxFormula : ComplexFormulaGenerator { public override IComplexFormulaNode GetFormula() => Formula(FormulaOperator.Subtract, Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.Value)) .WithFilter( new Filter(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 { public override IComplexFormulaNode GetFormula() => Formula(FormulaOperator.Subtract, Aggregate(AggregateCalculation.Sum, x => x.Property(x => x.Value)) .WithFilter( new Filter(x => x.Invoice.ID).IsEqualTo(Guid.Empty) .And(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(UninvoicedMaterial))] public double UninvoicedMaterialsExTax { get; set; } public Expression> AutoIncrementField() => x => x.Number; public Filter AutoIncrementFilter() => new Filter(x => x.Job.ID).IsEqualTo(Job.ID); public String AutoIncrementPrefix() => ""; public string AutoIncrementFormat() => "{0:D3}"; [NullEditor] public double TaxRate { get; set; } [NullEditor(Summary = Summary.Sum, Visible = Visible.Optional)] public double Tax { get; set; } static JobScope() { LinkedProperties.Register(x=>x.TaxCode, x => x.Rate, x => x.TaxRate); } public static void LinkScopeProperties() where TScoped : class, IJobScopedItem { LinkedProperties.Register(ass => ass.JobLink.DefaultScope, scope => scope.ID, ass => ass.JobScope.ID); LinkedProperties.Register(ass => ass.JobLink.DefaultScope, scope => scope.Number, ass => ass.JobScope.Number); LinkedProperties.Register(ass => ass.JobLink.DefaultScope, scope => scope.Description, ass => ass.JobScope.Description); } } }