JobScope.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Security;
  6. using InABox.Clients;
  7. using InABox.Core;
  8. namespace Comal.Classes
  9. {
  10. public class JobScopeInvoiceExTax : CoreAggregate<JobScope, InvoiceLine, double>
  11. {
  12. public override Expression<Func<InvoiceLine, double>> Aggregate => x => x.ExTax;
  13. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  14. public override Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>> Links =>
  15. new Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>>()
  16. {
  17. { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID }
  18. };
  19. }
  20. public class JobScopeInvoiceTax : CoreAggregate<JobScope, InvoiceLine, double>
  21. {
  22. public override Expression<Func<InvoiceLine, double>> Aggregate => x => x.Tax;
  23. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  24. public override Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>> Links =>
  25. new Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>>()
  26. {
  27. { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID }
  28. };
  29. }
  30. public class JobScopeInvoiceIncTax : CoreAggregate<JobScope, InvoiceLine, double>
  31. {
  32. public override Expression<Func<InvoiceLine, double>> Aggregate => x => x.IncTax;
  33. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  34. public override Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>> Links =>
  35. new Dictionary<Expression<Func<InvoiceLine, object>>, Expression<Func<JobScope, object>>>()
  36. {
  37. { InvoiceLine => InvoiceLine.Scope.ID, JobPrice => JobPrice.ID }
  38. };
  39. }
  40. public class JobScopeUninvoicedExTax : IFormula<JobScope, double>
  41. {
  42. public Expression<Func<JobScope, double>> Value => x => x.ExTax;
  43. public Expression<Func<JobScope, double>>[] Modifiers => new Expression<Func<JobScope, double>>[] { x => x.InvoiceExTax };
  44. public FormulaOperator Operator => FormulaOperator.Subtract;
  45. public FormulaType Type => FormulaType.Virtual;
  46. }
  47. public interface IJobScopedItem
  48. {
  49. JobLink JobLink { get; set; }
  50. JobScopeLink JobScope { get; set; }
  51. }
  52. [UserTracking(typeof(Job))]
  53. public class JobScope : Entity, IRemotable, IPersistent, ITaxable, IStringAutoIncrement<JobScope>, ILicense<ProjectManagementLicense>
  54. {
  55. [NullEditor]
  56. public InternalJobLink Job { get; set; }
  57. [EnumLookupEditor(typeof(JobScopeType), Visible = Visible.Default)]
  58. [EditorSequence(1)]
  59. public JobScopeType Type { get; set; } = JobScopeType.Variation;
  60. [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]
  61. [EditorSequence(2)]
  62. public string Number { get; set; }
  63. [MemoEditor(Visible = Visible.Default)]
  64. [EditorSequence(3)]
  65. public string Description { get; set; }
  66. [EditorSequence(4)]
  67. [TextBoxEditor]
  68. public string SourceRef{ get; set; }
  69. private class JobScopeLookup : LookupDefinitionGenerator<JobScope, JobScope>
  70. {
  71. public override Filter<JobScope> DefineFilter(JobScope[] items)
  72. {
  73. if (items?.Any() != true)
  74. return Filter.None<JobScope>();
  75. var data = Client.Query(
  76. new Filter<JobScope>(x=>x.Job.ID).IsEqualTo(items.First().Job.ID),
  77. Columns.None<JobScope>().Add(x => x.ID).Add(x => x.Parent.ID));
  78. var nodes = new CoreTreeNodes<Guid>(Guid.Empty);
  79. nodes.Load<JobScope>(data, x => x.ID, x => x.Parent.ID);
  80. var exclusions = items.SelectMany(x => nodes.GetChildren(x.ID)).ToArray();
  81. var ids = exclusions.Select(x => x.ID).ToArray();
  82. return new Filter<JobScope>(x=>x.Job.ID).IsEqualTo(items.First().Job.ID).And(x => x.ID).NotInList(ids);
  83. }
  84. public override Columns<JobScope> DefineFilterColumns()
  85. => Columns.None<JobScope>().Add(x => x.ID).Add(x => x.Parent.ID).Add(x => x.Number);
  86. }
  87. [LookupDefinition(typeof(JobScopeLookup))]
  88. [EditorSequence(4)]
  89. public JobScopeLink Parent { get; set; }
  90. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Default)]
  91. [EditorSequence(5)]
  92. public double ExTax { get; set; }
  93. [EditorSequence(6)]
  94. public TaxCodeLink TaxCode { get; set; }
  95. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional)]
  96. [EditorSequence(7)]
  97. public double IncTax { get; set; }
  98. [EditorSequence(8)]
  99. public JobScopeStatusLink Status { get; set; }
  100. [CurrencyEditor(Visible = Visible.Default, Editable = Editable.Hidden, Summary = Summary.Sum)]
  101. [Aggregate(typeof(JobScopeInvoiceExTax))]
  102. public double InvoiceExTax { get; set; }
  103. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  104. [Aggregate(typeof(JobScopeInvoiceTax))]
  105. public double InvoiceTax { get; set; }
  106. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  107. [Aggregate(typeof(JobScopeInvoiceIncTax))]
  108. public double InvoiceIncTax { get; set; }
  109. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  110. [Formula(typeof(JobScopeUninvoicedExTax))]
  111. public double UninvoiceIncTax { get; set; }
  112. private class MaterialsExTaxFormula : ComplexFormulaGenerator<JobScope, double>
  113. {
  114. public override IComplexFormulaNode<JobScope, double> GetFormula() =>
  115. Formula(FormulaOperator.Subtract,
  116. Aggregate<StockMovement>(AggregateCalculation.Sum, x => x.Property(x => x.Value))
  117. .WithFilter(
  118. new Filter<StockMovement>(x => x.Type).IsEqualTo(StockMovementType.Issue))
  119. .WithLink(x => x.JobScope.ID, x => x.ID));
  120. }
  121. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  122. [ComplexFormula(typeof(MaterialsExTaxFormula))]
  123. public double MaterialsExTax { get; set; }
  124. private class UninvoicedMaterial : ComplexFormulaGenerator<JobScope, double>
  125. {
  126. public override IComplexFormulaNode<JobScope, double> GetFormula() =>
  127. Formula(FormulaOperator.Subtract,
  128. Aggregate<StockMovement>(AggregateCalculation.Sum, x => x.Property(x => x.Value))
  129. .WithFilter(
  130. new Filter<StockMovement>(x => x.Invoice.ID).IsEqualTo(Guid.Empty)
  131. .And(x => x.Type).IsEqualTo(StockMovementType.Issue))
  132. .WithLink(x => x.JobScope.ID, x => x.ID));
  133. }
  134. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  135. [ComplexFormula(typeof(UninvoicedMaterial))]
  136. public double UninvoicedMaterialsExTax { get; set; }
  137. public Expression<Func<JobScope, string>> AutoIncrementField() => x => x.Number;
  138. public Filter<JobScope> AutoIncrementFilter() => new Filter<JobScope>(x => x.Job.ID).IsEqualTo(Job.ID);
  139. public String AutoIncrementPrefix() => "";
  140. public string AutoIncrementFormat() => "{0:D3}";
  141. [NullEditor]
  142. public double TaxRate { get; set; }
  143. [NullEditor(Summary = Summary.Sum, Visible = Visible.Optional)]
  144. public double Tax { get; set; }
  145. static JobScope()
  146. {
  147. LinkedProperties.Register<JobScope, TaxCodeLink, double>(x=>x.TaxCode, x => x.Rate, x => x.TaxRate);
  148. }
  149. public static void LinkScopeProperties<TScoped>() where TScoped : class, IJobScopedItem
  150. {
  151. LinkedProperties.Register<TScoped, JobScopeLink, Guid>(ass => ass.JobLink.DefaultScope, scope => scope.ID, ass => ass.JobScope.ID);
  152. LinkedProperties.Register<TScoped, JobScopeLink, String>(ass => ass.JobLink.DefaultScope, scope => scope.Number, ass => ass.JobScope.Number);
  153. LinkedProperties.Register<TScoped, JobScopeLink, String>(ass => ass.JobLink.DefaultScope, scope => scope.Description, ass => ass.JobScope.Description);
  154. }
  155. }
  156. }