StockForecastOrderScreen.xaml.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. using Comal.Classes;
  2. using InABox.Core;
  3. using InABox.Wpf;
  4. using InABox.WPF;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Linq;
  9. using System.Runtime.CompilerServices;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Input;
  17. using System.Windows.Media;
  18. using System.Windows.Media.Imaging;
  19. using System.Windows.Shapes;
  20. using InABox.Configuration;
  21. using InABox.Clients;
  22. namespace PRSDesktop;
  23. public class StockForecastOrderScreenSettings : IGlobalConfigurationSettings
  24. {
  25. public StockForecastOrderingType OrderingType { get; set; } =
  26. StockForecastOrderingType.StockOrder;
  27. public StockForecastOrderingStrategy OrderingStrategy { get; set; } =
  28. StockForecastOrderingStrategy.LowestOverallPrice;
  29. }
  30. /// <summary>
  31. /// Interaction logic for StockForecastOrderScreen.xaml
  32. /// </summary>
  33. public partial class StockForecastOrderScreen : Window, INotifyPropertyChanged
  34. {
  35. private StockForecastOrderScreenSettings settings;
  36. private bool _canSave;
  37. public bool CanSave
  38. {
  39. get => _canSave;
  40. set
  41. {
  42. _canSave = true;
  43. OnPropertyChanged();
  44. }
  45. }
  46. public StockForecastOrderingType OrderType
  47. {
  48. get => Grid.OrderType;
  49. set => Grid.OrderType = value;
  50. }
  51. public StockForecastOrderingStrategy Strategy
  52. {
  53. get => Grid.OrderStrategy;
  54. set => Grid.OrderStrategy = value;
  55. }
  56. public IEnumerable<StockForecastOrderingResult> Results => Grid.Results;
  57. public StockForecastOrderScreen(List<StockForecastOrderData> items, bool allowstockOrder = true)
  58. {
  59. settings = new GlobalConfiguration<StockForecastOrderScreenSettings>().Load();
  60. InitializeComponent();
  61. if (allowstockOrder)
  62. {
  63. OrderType = settings.OrderingType;
  64. OrderTypeBox.ItemsSource = Enum.GetValues<StockForecastOrderingType>()
  65. .Select(x => new KeyValuePair<StockForecastOrderingType, string>(x, CoreUtils.Neatify(x.ToString())));
  66. OrderTypeBox.SelectedValuePath = "Key";
  67. OrderTypeBox.DisplayMemberPath = "Value";
  68. OrderTypeBox.VerticalContentAlignment = VerticalAlignment.Center;
  69. OrderTypeBox.Bind(ComboBox.SelectedValueProperty, this, x => x.OrderType);
  70. }
  71. else
  72. {
  73. OrderType = StockForecastOrderingType.Breakup;
  74. OrderTypeBox.Visibility = System.Windows.Visibility.Collapsed;
  75. OrderTypeLabel.Visibility = System.Windows.Visibility.Collapsed;
  76. }
  77. Strategy = settings.OrderingStrategy;
  78. OrderStrategyBox.ItemsSource = Enum.GetValues<StockForecastOrderingStrategy>()
  79. .Select(x => new KeyValuePair<StockForecastOrderingStrategy, string>(x, CoreUtils.Neatify(x.ToString())));
  80. OrderStrategyBox.SelectedValuePath = "Key";
  81. OrderStrategyBox.DisplayMemberPath = "Value";
  82. OrderStrategyBox.VerticalContentAlignment = VerticalAlignment.Center;
  83. OrderStrategyBox.Bind(ComboBox.SelectedValueProperty, this, x => x.Strategy);
  84. Grid.OrderData = items;
  85. Grid.Refresh(true, true);
  86. }
  87. private void CancelButton_Click(object sender, RoutedEventArgs e)
  88. {
  89. DialogResult = false;
  90. Close();
  91. }
  92. private void OKButton_Click(object sender, RoutedEventArgs e)
  93. {
  94. DialogResult = true;
  95. Close();
  96. }
  97. public event PropertyChangedEventHandler? PropertyChanged;
  98. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
  99. {
  100. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  101. }
  102. private void Grid_OnChanged(object sender, EventArgs e)
  103. {
  104. CanSave = Grid.TotalQuantity > 0;
  105. }
  106. private void OrderTypeBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  107. {
  108. if (Grid.OrderData == null)
  109. return;
  110. settings.OrderingType = (StockForecastOrderingType)OrderTypeBox.SelectedValue;
  111. new GlobalConfiguration<StockForecastOrderScreenSettings>().Save(settings);
  112. }
  113. private void OrderStrategyBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  114. {
  115. if (Grid.OrderData == null)
  116. return;
  117. settings.OrderingStrategy = (StockForecastOrderingStrategy)OrderStrategyBox.SelectedValue;
  118. new GlobalConfiguration<StockForecastOrderScreenSettings>().Save(settings);
  119. }
  120. public void CreateOrders(string screenName)
  121. {
  122. var orders = new List<Tuple<PurchaseOrder, Dictionary<StockForecastOrderingResult,PurchaseOrderItem>>>();
  123. Progress.ShowModal("Creating Orders", progress =>
  124. {
  125. int iOrder = 1;
  126. foreach(var perSupplier in Results.GroupBy(x => x.Supplier.ID))
  127. {
  128. progress.Report($"Creating Orders ({iOrder++}/{Results.ToArray().Length})");
  129. var order = new PurchaseOrder();
  130. order.Description = $"Purchase Order created from {screenName} Screen";
  131. order.RaisedBy.ID = App.EmployeeID;
  132. LookupFactory.DoLookup<PurchaseOrder, Supplier, SupplierLink>(order, x => x.SupplierLink, perSupplier.Key);
  133. var orderItems = new Dictionary<StockForecastOrderingResult,PurchaseOrderItem>();
  134. var results = perSupplier.ToArray();
  135. foreach(var item in results)
  136. {
  137. var orderItem = new PurchaseOrderItem();
  138. orderItem.Product.ID = item.Item.Product.ID;
  139. orderItem.Style.ID = item.Item.Style.ID;
  140. orderItem.Job.ID = item.SupplierProduct.Job.ID;
  141. orderItems[item] = orderItem;
  142. }
  143. LookupFactory.DoLookups<PurchaseOrderItem, Job, JobLink>(
  144. orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Job.ID)),
  145. x => x.Job);
  146. LookupFactory.DoLookups<PurchaseOrderItem, Product, ProductLink>(
  147. orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Product.ID)),
  148. x => x.Product);
  149. LookupFactory.DoLookups<PurchaseOrderItem, ProductStyle, ProductStyleLink>(
  150. orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.Style.ID)),
  151. x => x.Style);
  152. LookupFactory.DoLookups<PurchaseOrderItem, TaxCode, TaxCodeLink>(
  153. orderItems.Values.Select(x => new Tuple<PurchaseOrderItem, Guid>(x, x.TaxCode.ID)),
  154. x => x.TaxCode);
  155. foreach(var item in results)
  156. {
  157. var orderItem = orderItems[item];
  158. orderItem.Dimensions.CopyFrom(item.SupplierProduct.Dimensions);
  159. orderItem.Qty = item.Quantity;
  160. orderItem.ForeignCurrencyCost = item.SupplierProduct.ForeignCurrencyPrice;
  161. orderItem.Cost = item.SupplierProduct.CostPrice;
  162. }
  163. orders.Add(new(order, orderItems));
  164. }
  165. progress.Report($"Saving {orders.Count} Orders");
  166. Client.Save(orders.Select(x => x.Item1), $"Created from {screenName} screen");
  167. foreach(var (order, orderItems) in orders)
  168. {
  169. foreach(var pair in orderItems)
  170. pair.Value.PurchaseOrderLink.ID = order.ID;
  171. }
  172. Client.Save(orders.SelectMany(x => x.Item2.Values), $"Created from {screenName} screen");
  173. var allocations = new List<PurchaseOrderItemAllocation>();
  174. progress.Report($"Processing Breakups");
  175. foreach(var (order, orderItems) in orders)
  176. {
  177. foreach(var (result, poi) in orderItems)
  178. {
  179. foreach (var breakup in result.Breakups)
  180. {
  181. // Skip the nominated job.
  182. if (breakup.JobID == poi.Job.ID && breakup.JobRequiItemID == Guid.Empty) continue;
  183. var alloc = new PurchaseOrderItemAllocation();
  184. alloc.Item.ID = poi.ID;
  185. alloc.Job.ID = breakup.JobID;
  186. alloc.JobRequisitionItem.ID = breakup.JobRequiItemID;
  187. alloc.Quantity = breakup.Quantity;
  188. allocations.Add(alloc);
  189. }
  190. }
  191. }
  192. if (allocations.Count != 0)
  193. Client.Save(allocations, $"Created from {screenName} Screen");
  194. });
  195. MessageWindow.ShowMessage($"The following orders were created:\n- {string.Join("\n- ",orders.Select(x=>x.Item1.PONumber))}", $"Created {orders.Count} orders");
  196. }
  197. }