JobScope.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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 class JobScopeActivityCost : CoreAggregate<JobScope, JobScopeActivity, double>
  48. {
  49. public override Expression<Func<JobScopeActivity, double>> Aggregate => x => x.Cost;
  50. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  51. public override Dictionary<Expression<Func<JobScopeActivity, object?>>, Expression<Func<JobScope, object?>>> Links =>
  52. new Dictionary<Expression<Func<JobScopeActivity, object>>, Expression<Func<JobScope, object>>>()
  53. {
  54. { JobScopeActivity => JobScopeActivity.Scope.ID, JobScope => JobScope.ID }
  55. };
  56. }
  57. public class JobScopeActivitySell : CoreAggregate<JobScope, JobScopeActivity, double>
  58. {
  59. public override Expression<Func<JobScopeActivity, double>> Aggregate => x => x.Sell;
  60. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  61. public override Dictionary<Expression<Func<JobScopeActivity, object?>>, Expression<Func<JobScope, object?>>> Links =>
  62. new Dictionary<Expression<Func<JobScopeActivity, object>>, Expression<Func<JobScope, object>>>()
  63. {
  64. { JobScopeActivity => JobScopeActivity.Scope.ID, JobScope => JobScope.ID }
  65. };
  66. }
  67. public class JobScopeCostCentreCost : CoreAggregate<JobScope, JobScopeCostCentre, double>
  68. {
  69. public override Expression<Func<JobScopeCostCentre, double>> Aggregate => x => x.Cost;
  70. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  71. public override Dictionary<Expression<Func<JobScopeCostCentre, object?>>, Expression<Func<JobScope, object?>>> Links =>
  72. new Dictionary<Expression<Func<JobScopeCostCentre, object>>, Expression<Func<JobScope, object>>>()
  73. {
  74. { JobScopeCostCentre => JobScopeCostCentre.Scope.ID, JobScope => JobScope.ID }
  75. };
  76. }
  77. public class JobScopeCostCentreSell : CoreAggregate<JobScope, JobScopeCostCentre, double>
  78. {
  79. public override Expression<Func<JobScopeCostCentre, double>> Aggregate => x => x.Sell;
  80. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  81. public override Dictionary<Expression<Func<JobScopeCostCentre, object?>>, Expression<Func<JobScope, object?>>> Links =>
  82. new Dictionary<Expression<Func<JobScopeCostCentre, object>>, Expression<Func<JobScope, object>>>()
  83. {
  84. { JobScopeCostCentre => JobScopeCostCentre.Scope.ID, JobScope => JobScope.ID }
  85. };
  86. }
  87. public interface IJobScopedItem
  88. {
  89. JobLink JobLink { get; set; }
  90. JobScopeLink JobScope { get; set; }
  91. }
  92. [UserTracking(typeof(Job))]
  93. public class JobScope : Entity, IRemotable, IPersistent, ITaxable, IStringAutoIncrement<JobScope>, ILicense<ProjectManagementLicense>
  94. {
  95. [NullEditor]
  96. public InternalJobLink Job { get; set; }
  97. [EnumLookupEditor(typeof(JobScopeType), Visible = Visible.Default)]
  98. [EditorSequence(1)]
  99. public JobScopeType Type { get; set; } = JobScopeType.Variation;
  100. [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]
  101. [EditorSequence(2)]
  102. public string Number { get; set; }
  103. [MemoEditor(Visible = Visible.Default)]
  104. [EditorSequence(3)]
  105. public string Description { get; set; }
  106. [EditorSequence(4)]
  107. [TextBoxEditor]
  108. public string SourceRef{ get; set; }
  109. private class JobScopeLookup : LookupDefinitionGenerator<JobScope, JobScope>
  110. {
  111. public override Filter<JobScope> DefineFilter(JobScope[] items)
  112. {
  113. if (items?.Any() != true)
  114. return Filter.None<JobScope>();
  115. var data = Client.Query(
  116. Filter<JobScope>.Where(x =>x.Job.ID).IsEqualTo(items.First().Job.ID),
  117. Columns.None<JobScope>().Add(x => x.ID).Add(x => x.Parent.ID));
  118. var nodes = new CoreTreeNodes<Guid>(Guid.Empty);
  119. nodes.Load<JobScope>(data, x => x.ID, x => x.Parent.ID);
  120. var exclusions = items.SelectMany(x => nodes.GetChildren(x.ID)).ToArray();
  121. var ids = exclusions.Select(x => x.ID).ToArray();
  122. return Filter<JobScope>.Where(x =>x.Job.ID).IsEqualTo(items.First().Job.ID).And(x => x.ID).NotInList(ids);
  123. }
  124. public override Columns<JobScope> DefineFilterColumns()
  125. => Columns.None<JobScope>().Add(x => x.ID).Add(x => x.Parent.ID).Add(x => x.Number);
  126. }
  127. [LookupDefinition(typeof(JobScopeLookup))]
  128. [EditorSequence(4)]
  129. public JobScopeLink Parent { get; set; }
  130. private class MaterialsCostAggregate : ComplexFormulaGenerator<JobScope, double>
  131. {
  132. public override IComplexFormulaNode<JobScope, double> GetFormula()
  133. => Aggregate<JobScopeCostCentre>(AggregateCalculation.Sum, x => x.Property(p => p.Cost))
  134. .WithLink(x => x.Scope.ID, x => x.ID);
  135. }
  136. [ComplexFormula(typeof(MaterialsCostAggregate))]
  137. [EditorSequence(5)]
  138. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional, Editable = Editable.Hidden)]
  139. public double MaterialsCost { get; set; }
  140. private class MaterialsSellAggregate : ComplexFormulaGenerator<JobScope, double>
  141. {
  142. public override IComplexFormulaNode<JobScope, double> GetFormula()
  143. => Aggregate<JobScopeCostCentre>(AggregateCalculation.Sum, x => x.Property(p => p.Sell))
  144. .WithLink(x => x.Scope.ID, x => x.ID);
  145. }
  146. [ComplexFormula(typeof(MaterialsSellAggregate))]
  147. [EditorSequence(6)]
  148. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional, Editable = Editable.Hidden)]
  149. public double MaterialsSell { get; set; }
  150. private class MaterialsMarginFormula : ComplexFormulaGenerator<JobScope, double>
  151. {
  152. public override IComplexFormulaNode<JobScope, double> GetFormula()
  153. => Formula(FormulaOperator.Divide,
  154. Formula(FormulaOperator.Subtract, Property(x => x.MaterialsSell), Property(x => x.MaterialsCost)),
  155. Property(x => x.MaterialsSell)
  156. );
  157. }
  158. [ComplexFormula(typeof(MaterialsMarginFormula))]
  159. [EditorSequence(7)]
  160. [DoubleEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]
  161. public double MaterialMargin { get; set; }
  162. private class MaterialsMarkupFormula : ComplexFormulaGenerator<JobScope, double>
  163. {
  164. public override IComplexFormulaNode<JobScope, double> GetFormula()
  165. => Formula(FormulaOperator.Divide,
  166. Formula(FormulaOperator.Subtract, Property(x => x.MaterialsSell), Property(x => x.MaterialsCost)),
  167. Property(x => x.MaterialsCost)
  168. );
  169. }
  170. [ComplexFormula(typeof(MaterialsMarkupFormula))]
  171. [EditorSequence(8)]
  172. [DoubleEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]
  173. public double MaterialMarkup { get; set; }
  174. private class LabourCostAggregate : ComplexFormulaGenerator<JobScope, double>
  175. {
  176. public override IComplexFormulaNode<JobScope, double> GetFormula()
  177. => Aggregate<JobScopeActivity>(AggregateCalculation.Sum, x => x.Property(p => p.Cost))
  178. .WithLink(x => x.Scope.ID, x => x.ID);
  179. }
  180. [ComplexFormula(typeof(LabourCostAggregate))]
  181. [EditorSequence(9)]
  182. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional, Editable = Editable.Hidden)]
  183. public double LabourCost { get; set; }
  184. private class LabourSellAggregate : ComplexFormulaGenerator<JobScope, double>
  185. {
  186. public override IComplexFormulaNode<JobScope, double> GetFormula()
  187. => Aggregate<JobScopeActivity>(AggregateCalculation.Sum, x => x.Property(p => p.Sell))
  188. .WithLink(x => x.Scope.ID, x => x.ID);
  189. }
  190. [ComplexFormula(typeof(LabourSellAggregate))]
  191. [EditorSequence(10)]
  192. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional, Editable = Editable.Hidden)]
  193. public double LabourSell { get; set; }
  194. private class LabourMarginFormula : ComplexFormulaGenerator<JobScope, double>
  195. {
  196. public override IComplexFormulaNode<JobScope, double> GetFormula()
  197. => Formula(FormulaOperator.Divide,
  198. Formula(FormulaOperator.Subtract, Property(x => x.LabourSell), Property(x => x.LabourCost)),
  199. Property(x => x.LabourSell)
  200. );
  201. }
  202. [ComplexFormula(typeof(LabourMarginFormula))]
  203. [EditorSequence(11)]
  204. [DoubleEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]
  205. public double LabourMargin { get; set; }
  206. private class LabourMarkupFormula : ComplexFormulaGenerator<JobScope, double>
  207. {
  208. public override IComplexFormulaNode<JobScope, double> GetFormula()
  209. => Formula(FormulaOperator.Divide,
  210. Formula(FormulaOperator.Subtract, Property(x => x.LabourSell), Property(x => x.LabourCost)),
  211. Property(x => x.LabourCost)
  212. );
  213. }
  214. [ComplexFormula(typeof(LabourMarkupFormula))]
  215. [EditorSequence(12)]
  216. [DoubleEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]
  217. public double LabourMarkup { get; set; }
  218. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Default)]
  219. [EditorSequence(13)]
  220. public double ExTax { get; set; }
  221. [EditorSequence(14)]
  222. public TaxCodeLink TaxCode { get; set; }
  223. [CurrencyEditor(Summary = Summary.Sum, Visible = Visible.Optional)]
  224. [EditorSequence(15)]
  225. public double IncTax { get; set; }
  226. [EditorSequence(16)]
  227. public JobScopeStatusLink Status { get; set; }
  228. private class InvoiceExTaxAggregate : ComplexFormulaGenerator<JobScope, double>
  229. {
  230. public override IComplexFormulaNode<JobScope, double> GetFormula()
  231. => Aggregate<InvoiceLine>(AggregateCalculation.Sum, x => x.Property(p => p.ExTax))
  232. .WithLink(x => x.Scope.ID, x => x.ID);
  233. }
  234. [ComplexFormula(typeof(LabourSellAggregate))]
  235. [Aggregate(typeof(JobScopeInvoiceExTax))]
  236. [EditorSequence(17)]
  237. [CurrencyEditor(Visible = Visible.Default, Editable = Editable.Hidden, Summary = Summary.Sum)]
  238. public double InvoiceExTax { get; set; }
  239. [Aggregate(typeof(JobScopeInvoiceTax))]
  240. [EditorSequence(18)]
  241. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  242. public double InvoiceTax { get; set; }
  243. [Aggregate(typeof(JobScopeInvoiceIncTax))]
  244. [EditorSequence(19)]
  245. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  246. public double InvoiceIncTax { get; set; }
  247. [Formula(typeof(JobScopeUninvoicedExTax))]
  248. [EditorSequence(20)]
  249. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  250. public double UninvoiceIncTax { get; set; }
  251. private class MaterialsExTaxFormula : ComplexFormulaGenerator<JobScope, double>
  252. {
  253. public override IComplexFormulaNode<JobScope, double> GetFormula() =>
  254. Formula(FormulaOperator.Subtract,
  255. Aggregate<StockMovement>(AggregateCalculation.Sum, x => x.Property(x => x.Value))
  256. .WithFilter(
  257. Filter<StockMovement>.Where(x => x.Type).IsEqualTo(StockMovementType.Issue))
  258. .WithLink(x => x.JobScope.ID, x => x.ID));
  259. }
  260. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  261. [ComplexFormula(typeof(MaterialsExTaxFormula))]
  262. public double MaterialsExTax { get; set; }
  263. private class UninvoicedMaterial : ComplexFormulaGenerator<JobScope, double>
  264. {
  265. public override IComplexFormulaNode<JobScope, double> GetFormula() =>
  266. Formula(FormulaOperator.Subtract,
  267. Aggregate<StockMovement>(AggregateCalculation.Sum, x => x.Property(x => x.Value))
  268. .WithFilter(
  269. Filter<StockMovement>.Where(x => x.Invoice.ID).IsEqualTo(Guid.Empty)
  270. .And(x => x.Type).IsEqualTo(StockMovementType.Issue))
  271. .WithLink(x => x.JobScope.ID, x => x.ID));
  272. }
  273. [CurrencyEditor(Visible = Visible.Optional, Editable = Editable.Hidden, Summary = Summary.Sum)]
  274. [ComplexFormula(typeof(UninvoicedMaterial))]
  275. public double UninvoicedMaterialsExTax { get; set; }
  276. public Expression<Func<JobScope, string>> AutoIncrementField() => x => x.Number;
  277. public Filter<JobScope> AutoIncrementFilter() => Filter<JobScope>.Where(x => x.Job.ID).IsEqualTo(Job.ID);
  278. public String AutoIncrementPrefix() => "";
  279. public string AutoIncrementFormat() => "{0:D3}";
  280. public int AutoIncrementDefault() => 0;
  281. [NullEditor]
  282. public double TaxRate { get; set; }
  283. [NullEditor(Summary = Summary.Sum, Visible = Visible.Optional)]
  284. public double Tax { get; set; }
  285. static JobScope()
  286. {
  287. LinkedProperties.Register<JobScope, TaxCodeLink, double>(x=>x.TaxCode, x => x.Rate, x => x.TaxRate);
  288. }
  289. public static void LinkScopeProperties<TScoped>() where TScoped : class, IJobScopedItem
  290. {
  291. LinkedProperties.Register<TScoped, JobScopeLink, Guid>(ass => ass.JobLink.DefaultScope, scope => scope.ID, ass => ass.JobScope.ID);
  292. LinkedProperties.Register<TScoped, JobScopeLink, String>(ass => ass.JobLink.DefaultScope, scope => scope.Number, ass => ass.JobScope.Number);
  293. LinkedProperties.Register<TScoped, JobScopeLink, String>(ass => ass.JobLink.DefaultScope, scope => scope.Description, ass => ass.JobScope.Description);
  294. }
  295. }
  296. }