StockHolding.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using InABox.Core;
  5. using PRSClasses;
  6. namespace Comal.Classes
  7. {
  8. // public class StockHoldingUnitAggregate : CoreAggregate<StockHolding, StockMovement, double>
  9. // {
  10. // public override Expression<Func<StockMovement, double>> Aggregate => x => x.Units;
  11. //
  12. // public override Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>> Links =>
  13. // new Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>>()
  14. // {
  15. // { StockMovement => StockMovement.Product.ID, StockHolding => StockHolding.Product.ID },
  16. // { StockMovement => StockMovement.Job.ID, StockHolding => StockHolding.Job.ID },
  17. // { StockMovement => StockMovement.Location.ID, StockHolding => StockHolding.Location.ID },
  18. // { StockMovement => StockMovement.Style.ID, StockHolding => StockHolding.Style.ID },
  19. // { StockMovement => StockMovement.Dimensions.Unit.ID, StockHolding => StockHolding.Dimensions.Unit.ID },
  20. // { StockMovement => StockMovement.Dimensions.Quantity, StockHolding => StockHolding.Dimensions.Quantity },
  21. // { StockMovement => StockMovement.Dimensions.Length, StockHolding => StockHolding.Dimensions.Length },
  22. // { StockMovement => StockMovement.Dimensions.Width, StockHolding => StockHolding.Dimensions.Width },
  23. // { StockMovement => StockMovement.Dimensions.Height, StockHolding => StockHolding.Dimensions.Height },
  24. // { StockMovement => StockMovement.Dimensions.Weight, StockHolding => StockHolding.Dimensions.Weight },
  25. // };
  26. //
  27. // public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  28. // }
  29. //
  30. // public class StockHoldingValueAggregate : CoreAggregate<StockHolding, StockMovement, double>
  31. // {
  32. // public override Expression<Func<StockMovement, double>> Aggregate => x => x.Value;
  33. //
  34. // public override Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>> Links =>
  35. // new Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>>()
  36. // {
  37. // { StockMovement => StockMovement.Product.ID, StockHolding => StockHolding.Product.ID },
  38. // { StockMovement => StockMovement.Job.ID, StockHolding => StockHolding.Job.ID },
  39. // { StockMovement => StockMovement.Location.ID, StockHolding => StockHolding.Location.ID },
  40. // { StockMovement => StockMovement.Style.ID, StockHolding => StockHolding.Style.ID },
  41. // { StockMovement => StockMovement.Dimensions.Unit.ID, StockHolding => StockHolding.Dimensions.Unit.ID },
  42. // { StockMovement => StockMovement.Dimensions.Quantity, StockHolding => StockHolding.Dimensions.Quantity },
  43. // { StockMovement => StockMovement.Dimensions.Length, StockHolding => StockHolding.Dimensions.Length },
  44. // { StockMovement => StockMovement.Dimensions.Width, StockHolding => StockHolding.Dimensions.Width },
  45. // { StockMovement => StockMovement.Dimensions.Height, StockHolding => StockHolding.Dimensions.Height },
  46. // { StockMovement => StockMovement.Dimensions.Weight, StockHolding => StockHolding.Dimensions.Weight },
  47. // };
  48. //
  49. // public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  50. // }
  51. //
  52. // public class StockHoldingAverageValueFormula : IFormula<StockHolding, double>
  53. // {
  54. // public Expression<Func<StockHolding, double>> Value => x => x.Value;
  55. //
  56. // public Expression<Func<StockHolding, double>>[] Modifiers => new Expression<Func<StockHolding, double>>[] { x => x.Units };
  57. //
  58. // public FormulaOperator Operator => FormulaOperator.Divide;
  59. //
  60. // public FormulaType Type => FormulaType.Virtual;
  61. // }
  62. //
  63. // public class StockHoldingQuantityAggregate : CoreAggregate<StockHolding, StockMovement, double>
  64. // {
  65. // public override Expression<Func<StockMovement, double>> Aggregate => x => x.Qty;
  66. //
  67. // public override Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>> Links =>
  68. // new Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>>()
  69. // {
  70. // { StockMovement => StockMovement.Product.ID, StockHolding => StockHolding.Product.ID },
  71. // { StockMovement => StockMovement.Job.ID, StockHolding => StockHolding.Job.ID },
  72. // { StockMovement => StockMovement.Location.ID, StockHolding => StockHolding.Location.ID },
  73. // { StockMovement => StockMovement.Style.ID, StockHolding => StockHolding.Style.ID },
  74. // { StockMovement => StockMovement.Dimensions.Unit.ID, StockHolding => StockHolding.Dimensions.Unit.ID },
  75. // { StockMovement => StockMovement.Dimensions.Quantity, StockHolding => StockHolding.Dimensions.Quantity },
  76. // { StockMovement => StockMovement.Dimensions.Length, StockHolding => StockHolding.Dimensions.Length },
  77. // { StockMovement => StockMovement.Dimensions.Width, StockHolding => StockHolding.Dimensions.Width },
  78. // { StockMovement => StockMovement.Dimensions.Height, StockHolding => StockHolding.Dimensions.Height },
  79. // { StockMovement => StockMovement.Dimensions.Weight, StockHolding => StockHolding.Dimensions.Weight },
  80. // };
  81. //
  82. // public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  83. // }
  84. // public class StockHoldingAvailableAggregate : CoreAggregate<StockHolding, StockMovement, double>
  85. // {
  86. // public override Expression<Func<StockMovement, double>> Aggregate => x => x.Units;
  87. //
  88. // public override Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>> Links =>
  89. // new Dictionary<Expression<Func<StockMovement, object>>, Expression<Func<StockHolding, object>>>()
  90. // {
  91. // { StockMovement => StockMovement.Product.ID, StockHolding => StockHolding.Product.ID },
  92. // { StockMovement => StockMovement.Job.ID, StockHolding => StockHolding.Job.ID },
  93. // { StockMovement => StockMovement.Location.ID, StockHolding => StockHolding.Location.ID },
  94. // { StockMovement => StockMovement.Style.ID, StockHolding => StockHolding.Style.ID },
  95. // { StockMovement => StockMovement.Dimensions.Unit.ID, StockHolding => StockHolding.Dimensions.Unit.ID },
  96. // { StockMovement => StockMovement.Dimensions.Quantity, StockHolding => StockHolding.Dimensions.Quantity },
  97. // { StockMovement => StockMovement.Dimensions.Length, StockHolding => StockHolding.Dimensions.Length },
  98. // { StockMovement => StockMovement.Dimensions.Width, StockHolding => StockHolding.Dimensions.Width },
  99. // { StockMovement => StockMovement.Dimensions.Height, StockHolding => StockHolding.Dimensions.Height },
  100. // { StockMovement => StockMovement.Dimensions.Weight, StockHolding => StockHolding.Dimensions.Weight },
  101. // };
  102. //
  103. // public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  104. //
  105. // public override Filter<StockMovement>? Filter => new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsEqualTo(Guid.Empty);
  106. // }
  107. // public class StockHoldingWeightFormula : IFormula<StockHolding, double>
  108. // {
  109. // public Expression<Func<StockHolding, double>> Value => x => x.Qty;
  110. //
  111. // public Expression<Func<StockHolding, double>>[] Modifiers => new Expression<Func<StockHolding, double>>[] { x => x.Dimensions.Weight };
  112. //
  113. // public FormulaOperator Operator => FormulaOperator.Multiply;
  114. //
  115. // public FormulaType Type => FormulaType.Virtual;
  116. // }
  117. //
  118. // public class StockHoldingIsRemnantCondition : ICondition<StockHolding, double, object>
  119. // {
  120. // public Expression<Func<StockHolding, double>> Left => x => x.Dimensions.Value;
  121. //
  122. // public Condition Condition => Condition.LessThan;
  123. //
  124. // public Expression<Func<StockHolding, double>> Right => x => x.Product.DefaultInstance.Dimensions.Value;
  125. //
  126. // public Expression<Func<StockHolding, object>> True => x => true;
  127. //
  128. // public Expression<Func<StockHolding, object>> False => x => null;
  129. //
  130. // public ConditionType Type => ConditionType.Virtual;
  131. // }
  132. // public class StockHoldingUnionGenerator : AutoEntityUnionGenerator<IStockHolding>
  133. // {
  134. // protected override void Configure()
  135. // {
  136. // AddTable<StockMovement>();
  137. // }
  138. //
  139. // public override bool Distinct => true;
  140. //
  141. // public override Column<IStockHolding>[] IDColumns => Columns;
  142. //
  143. // public static Column<IStockHolding>[] Columns => new Column<IStockHolding>[]
  144. // {
  145. // new Column<IStockHolding>(x => x.Job.ID),
  146. // new Column<IStockHolding>(x => x.Location.ID),
  147. // new Column<IStockHolding>(x => x.Product.ID),
  148. // new Column<IStockHolding>(x => x.Style.ID),
  149. // new Column<IStockHolding>(x => x.Dimensions.Unit.ID),
  150. // new Column<IStockHolding>(x => x.Dimensions.Quantity),
  151. // new Column<IStockHolding>(x => x.Dimensions.Length),
  152. // new Column<IStockHolding>(x => x.Dimensions.Width),
  153. // new Column<IStockHolding>(x => x.Dimensions.Height),
  154. // new Column<IStockHolding>(x => x.Dimensions.Weight),
  155. // };
  156. //
  157. // public static Filter<StockMovement>? GetFilter(IStockHolding holding)
  158. // {
  159. // var filter = new Filters<StockMovement>();
  160. //
  161. // foreach(var column in Columns)
  162. // {
  163. // filter.Add(new Filter<StockMovement>(column.Cast<StockMovement>()).IsEqualTo(CoreUtils.GetPropertyValue(holding, column.Property)));
  164. // }
  165. //
  166. // return filter.Combine();
  167. // }
  168. // }
  169. //
  170. // [UserTracking(typeof(StockMovement))]
  171. // [AutoEntity(typeof(StockHoldingUnionGenerator))]
  172. // public class StockHoldingView : StockEntity, IRemotable, IPersistent, IOneToMany<StockLocation>, IOneToMany<Product>,
  173. // IStockHolding, ILicense<WarehouseLicense>
  174. // {
  175. //
  176. // public override ProductLink Product { get; set; }
  177. //
  178. // public ProductStyleLink Style { get; set; }
  179. //
  180. // public StockLocationLink Location { get; set; }
  181. //
  182. // public JobLink Job { get; set; }
  183. //
  184. // [RequiredColumn]
  185. // [DimensionsEditor(typeof(StockDimensions), AllowEditingUnit = false)]
  186. // public override StockDimensions Dimensions { get; set; }
  187. //
  188. // [Condition(typeof(StockHoldingIsRemnantCondition))]
  189. // [NullEditor]
  190. // public bool IsRemnant { get; set; }
  191. //
  192. // [Aggregate(typeof(StockHoldingUnitAggregate))]
  193. // [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  194. // public double Units { get; set; }
  195. //
  196. // [Aggregate(typeof(StockHoldingQuantityAggregate))]
  197. // [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  198. // public double Qty { get; set; }
  199. //
  200. // [Formula(typeof(StockHoldingWeightFormula))]
  201. // [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  202. // public double Weight { get; set; }
  203. //
  204. // [Aggregate(typeof(StockHoldingValueAggregate))]
  205. // [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  206. // public double Value { get; set; }
  207. //
  208. // [Formula(typeof(StockHoldingAverageValueFormula))]
  209. // [DoubleEditor(Editable = Editable.Disabled)]
  210. // public double AverageValue { get; set; }
  211. // }
  212. // FV 6/2/24: This used to be a view (see above), but we were running into performance issues trying to
  213. // get aggregates fof stock locations (ie show me how many holdings in a given location was taking upwrds of
  214. // 20 seconds. Have moved update logic to StockHoldingStore / StockMovementStore so updates are a bit slower,
  215. // but reads are now much faster.
  216. [UserTracking(typeof(StockMovement))]
  217. public class StockHolding : StockEntity, IRemotable, IPersistent, IOneToMany<StockLocation>, IOneToMany<Product>,
  218. IStockHolding, ILicense<WarehouseLicense>
  219. {
  220. [Editable(Editable.Disabled)]
  221. [EditorSequence(1)]
  222. public StockLocationLink Location { get; set; }
  223. [Editable(Editable.Disabled)]
  224. [EditorSequence(2)]
  225. public override ProductLink Product { get; set; }
  226. [DimensionsEditor(typeof(StockDimensions), AllowEditingUnit = false)]
  227. [Editable(Editable.Disabled)]
  228. [EditorSequence(3)]
  229. public override StockDimensions Dimensions { get; set; }
  230. [Editable(Editable.Disabled)]
  231. [EditorSequence(4)]
  232. public ProductStyleLink Style { get; set; }
  233. [Editable(Editable.Disabled)]
  234. [EditorSequence(4)]
  235. public JobLink Job { get; set; }
  236. [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  237. [EditorSequence(5)]
  238. public double Units { get; set; }
  239. [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  240. [EditorSequence(6)]
  241. public double Qty { get; set; }
  242. [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  243. [EditorSequence(7)]
  244. public double Weight { get; set; }
  245. [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  246. [EditorSequence(8)]
  247. public double Value { get; set; }
  248. [DoubleEditor(Editable = Editable.Disabled)]
  249. [EditorSequence(9)]
  250. public double AverageValue { get; set; }
  251. [DoubleEditor(Editable = Editable.Disabled, Summary = Summary.Sum)]
  252. [EditorSequence(10)]
  253. public double Available { get; set; }
  254. public static Column<IStockHolding>[] Columns => new Column<IStockHolding>[]
  255. {
  256. new Column<IStockHolding>(x => x.Job.ID),
  257. new Column<IStockHolding>(x => x.Location.ID),
  258. new Column<IStockHolding>(x => x.Product.ID),
  259. new Column<IStockHolding>(x => x.Style.ID),
  260. new Column<IStockHolding>(x => x.Dimensions.Unit.ID),
  261. new Column<IStockHolding>(x => x.Dimensions.Quantity),
  262. new Column<IStockHolding>(x => x.Dimensions.Length),
  263. new Column<IStockHolding>(x => x.Dimensions.Width),
  264. new Column<IStockHolding>(x => x.Dimensions.Height),
  265. new Column<IStockHolding>(x => x.Dimensions.Weight),
  266. };
  267. public static Filter<StockMovement>? GetFilter(IStockHolding holding)
  268. {
  269. var filter = new Filters<StockMovement>();
  270. foreach(var column in Columns)
  271. {
  272. filter.Add(new Filter<StockMovement>(column.Cast<StockMovement>()).IsEqualTo(CoreUtils.GetPropertyValue(holding, column.Property)));
  273. }
  274. return filter.Combine();
  275. }
  276. }
  277. }