StockUtils.cs 5.1 KB

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