StockUtils.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Comal.Classes;
  5. using InABox.Clients;
  6. using InABox.Core;
  7. using InABox.Wpf;
  8. using InABox.WPF;
  9. namespace PRSDesktop;
  10. public static class StockUtils
  11. {
  12. public static bool RecalculateHoldingsOfLocations(Guid[] locationIDs, out List<String> report)
  13. {
  14. return RecalculateHoldings(new Filter<IStockHolding>(x => x.Location.ID).InList(locationIDs), out report);
  15. }
  16. public static bool RecalculateHoldingsOfProducts(Guid[] productIDs, out List<String> report)
  17. {
  18. return RecalculateHoldings(new Filter<IStockHolding>(x => x.Product.ID).InList(productIDs), out report);
  19. }
  20. public static bool RecalculateHoldings(Filter<IStockHolding> filter, out List<String> report)
  21. {
  22. bool result = false;
  23. Dictionary<String, int> messages = new();
  24. void AddMessage(String type)
  25. {
  26. messages.TryGetValue(type, out int count);
  27. messages[type] = ++count;
  28. }
  29. Progress.ShowModal("Recalculating", progress =>
  30. {
  31. progress.Report("Loading Data");
  32. MultiQuery query = new MultiQuery();
  33. query.Add(
  34. filter.Cast<StockHolding>(),
  35. Columns.Required<StockHolding>().Add(x => x.ID)
  36. .Add(x => x.Location.ID)
  37. .Add(x => x.Product.ID)
  38. .Add(x => x.Job.ID)
  39. .Add(x => x.Style.ID)
  40. .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)
  41. .Add(x => x.Units)
  42. .Add(x => x.AverageValue)
  43. .Add(x => x.Available)
  44. .Add(x => x.Qty)
  45. .Add(x => x.Weight)
  46. .Add(x => x.Value)
  47. );
  48. query.Add(
  49. filter.Cast<StockMovement>(),
  50. Columns.None<StockMovement>().Add(x => x.ID)
  51. .Add(x=>x.Location.ID)
  52. .Add(x => x.Product.ID)
  53. .Add(x => x.Job.ID)
  54. .Add(x => x.Style.ID)
  55. .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)
  56. .Add(x => x.Units)
  57. .Add(x => x.Cost)
  58. .Add(x => x.JobRequisitionItem.ID)
  59. );
  60. query.Query();
  61. var holdings = query.Get<StockHolding>();
  62. var toDelete = new List<StockHolding>();
  63. var movements = query.Get<StockMovement>();
  64. double movementcount = (double)movements.Rows.Count;
  65. progress.Report("Processing");
  66. var updates = new List<StockHolding>();
  67. while (movements.Rows.Any())
  68. {
  69. double percent = ((movementcount - movements.Rows.Count) / movementcount) * 100.0;
  70. progress.Report($"Processing ({percent:F2}% complete)");
  71. var first = movements.Rows.First();
  72. var selected = movements.Rows.Where(x => x.IsEqualTo<StockMovement, StockMovement>(first)).ToList();
  73. var holdingrow = holdings.Rows.FirstOrDefault(x => x.IsEqualTo<StockHolding, StockMovement>(first));
  74. StockHolding holding = null;
  75. if (holdingrow != null)
  76. {
  77. holdings.Rows.Remove(holdingrow);
  78. holding = holdingrow.ToObject<StockHolding>();
  79. }
  80. if (holding == null)
  81. {
  82. var firstmovement = first.ToObject<StockMovement>();
  83. holding = new StockHolding();
  84. holding.Location.ID = firstmovement.Location.ID;
  85. holding.Product.ID = firstmovement.Product.ID;
  86. holding.Style.ID = firstmovement.Style.ID;
  87. holding.Job.ID = firstmovement.Job.ID;
  88. holding.Dimensions.CopyFrom(firstmovement.Dimensions);
  89. }
  90. holding.Recalculate(selected.ToObjects<StockMovement>());
  91. if (holding.Units.IsEffectivelyEqual(0.0) && holding.Available.IsEffectivelyEqual(0.0))
  92. {
  93. if (holding.ID != Guid.Empty)
  94. toDelete.Add(holding);
  95. }
  96. else if (holding.IsChanged())
  97. {
  98. AddMessage(holding.ID != Guid.Empty ? "updated" : "added");
  99. updates.Add(holding);
  100. }
  101. foreach (var row in selected)
  102. movements.Rows.Remove(row);
  103. }
  104. toDelete.AddRange(holdings.Rows.ToObjects<StockHolding>());
  105. foreach (var holding in toDelete)
  106. AddMessage("deleted");
  107. if (updates.Any())
  108. {
  109. result = true;
  110. progress.Report($"Updating {updates.Count} Holdings");
  111. new Client<StockHolding>().Save(updates.Where(x => x.IsChanged()), "Updated by Recalculation");
  112. }
  113. if (toDelete.Any())
  114. {
  115. result = true;
  116. progress.Report($"Deleting {toDelete.Count} Holdings");
  117. new Client<StockHolding>().Delete(toDelete, "Removed by Recalculation");
  118. }
  119. });
  120. report = new List<String>();
  121. if (messages.Any())
  122. report.AddRange(messages.Select(x => $"{x.Value} holdings {x.Key}"));
  123. else
  124. report.Add("Nothing to Update");
  125. return result;
  126. }
  127. }