StockLocation.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using InABox.Core;
  6. namespace Comal.Classes
  7. {
  8. public class StockLocationHoldings : CoreAggregate<StockLocation, StockHolding, Guid>
  9. {
  10. public override Expression<Func<StockHolding, Guid>> Aggregate => x => x.Product.ID;
  11. public override Dictionary<Expression<Func<StockHolding, object>>, Expression<Func<StockLocation, object>>> Links =>
  12. new Dictionary<Expression<Func<StockHolding, object>>, Expression<Func<StockLocation, object>>>()
  13. {
  14. { StockHolding => StockHolding.Location.ID, StockLocation => StockLocation.ID },
  15. };
  16. public override AggregateCalculation Calculation => AggregateCalculation.Count;
  17. }
  18. public enum StockTakeFrequency
  19. {
  20. Never,
  21. Daily,
  22. Weekly,
  23. Fortnightly,
  24. Monthly,
  25. Quarterly,
  26. TwiceYearly,
  27. Yearly
  28. }
  29. [UserTracking(typeof(StockMovement))]
  30. public class StockLocation : Entity, IRemotable, IPersistent, IStockLocation, ILicense<WarehouseLicense>, IExportable, IImportable
  31. {
  32. [UniqueCodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]
  33. [EditorSequence(1)]
  34. public string Code { get; set; }
  35. [TextBoxEditor]
  36. [EditorSequence(2)]
  37. public string Description { get; set; }
  38. [EntityRelationship(DeleteAction.SetNull)]
  39. [EditorSequence(3)]
  40. public StockWarehouseLink Warehouse { get; set; }
  41. private class StockAreaLookup : LookupDefinitionGenerator<StockArea, StockLocation>
  42. {
  43. public override Filter<StockArea> DefineFilter(StockLocation[] items)
  44. {
  45. var ids = items.Select(x => x.Warehouse.ID).Distinct().ToArray();
  46. if (ids.Length == 1)
  47. return new Filter<StockArea>(x => x.Warehouse.ID).IsEqualTo(ids[0]).And(x => x.Active).IsEqualTo(true);
  48. return new Filter<StockArea>(x => x.ID).IsEqualTo(CoreUtils.FullGuid);
  49. }
  50. public override Columns<StockLocation> DefineFilterColumns()
  51. => new Columns<StockLocation>(x => x.Warehouse.ID);
  52. }
  53. [LookupDefinition(typeof(StockAreaLookup))]
  54. [EntityRelationship(DeleteAction.SetNull)]
  55. [EditorSequence(4)]
  56. public StockAreaLink Area { get; set; }
  57. [EditorSequence(5)]
  58. public JobLink Job { get; set; }
  59. /// <summary>
  60. /// Is the location a "shelf" (ie permanent) or "pack" (ie transient)
  61. /// </summary>
  62. [EnumLookupEditor(typeof(StockLocationType))]
  63. [EditorSequence(6)]
  64. public StockLocationType Type { get; set; }
  65. /// <summary>
  66. /// Is the Stock Location Active?
  67. /// </summary>
  68. [EditorSequence(7)]
  69. public bool Active { get; set; }
  70. /// <summary>
  71. /// Mark this location as the default receival location for the warehouse
  72. /// </summary>
  73. [EditorSequence(8)]
  74. public bool Default { get; set; }
  75. /// <summary>
  76. /// Mark this location as a favourite which shows up in Timebench Transfer module for quick selection
  77. /// </summary>
  78. [EditorSequence(9)]
  79. public bool Favourite { get; set; } = false;
  80. [Aggregate(typeof(StockLocationHoldings))]
  81. [DoubleEditor(Editable = Editable.Hidden)]
  82. [EditorSequence(10)]
  83. public double Holdings { get; set; }
  84. [DateEditor]
  85. [EditorSequence("Stocktake",1)]
  86. public DateTime LastStocktake { get; set; } = DateTime.MinValue;
  87. [EnumLookupEditor(typeof(StockTakeFrequency))]
  88. [EditorSequence("Stocktake",2)]
  89. public StockTakeFrequency StocktakeFrequency { get; set; } = StockTakeFrequency.Never;
  90. [DateEditor]
  91. [EditorSequence("Stocktake",3)]
  92. public DateTime NextStocktake { get; set; } = DateTime.MaxValue;
  93. [EditorSequence("Stocktake",4)]
  94. [DateEditor]
  95. public DateTime CurrentStocktake { get; set; } = DateTime.MinValue;
  96. private static DateTime CalculateNextStockTake(DateTime last, StockTakeFrequency frequency)
  97. {
  98. DateTime CheckDate(DateTime date, Func<DateTime> action) => date.IsEmpty() ? DateTime.Today : action();
  99. return frequency switch
  100. {
  101. StockTakeFrequency.Daily => CheckDate(last,() => last.AddDays(1)),
  102. StockTakeFrequency.Weekly => CheckDate(last,() => last.AddDays(1)),
  103. StockTakeFrequency.Fortnightly => CheckDate(last,() => last.AddDays(1)),
  104. StockTakeFrequency.Monthly => CheckDate(last,() => last.AddMonths(1)),
  105. StockTakeFrequency.Quarterly => CheckDate(last,() => last.AddMonths(3)),
  106. StockTakeFrequency.TwiceYearly => CheckDate(last,() => last.AddMonths(6)),
  107. StockTakeFrequency.Yearly => CheckDate(last,() => last.AddYears(1)),
  108. _ => DateTime.MinValue
  109. };
  110. }
  111. protected override void DoPropertyChanged(string name, object? before, object? after)
  112. {
  113. base.DoPropertyChanged(name, before, after);
  114. if (String.Equals(name, nameof(LastStocktake)))
  115. NextStocktake = CalculateNextStockTake((DateTime)(after ?? DateTime.MinValue), StocktakeFrequency);
  116. else if (String.Equals(name, nameof(StocktakeFrequency)))
  117. NextStocktake = CalculateNextStockTake(LastStocktake, (StockTakeFrequency)(after ?? StockTakeFrequency.Never));
  118. }
  119. }
  120. }