ReservationManagementPurchasing.xaml.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using Comal.Classes;
  2. using InABox.Clients;
  3. using InABox.Core;
  4. using InABox.DynamicGrid;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.ComponentModel;
  9. using System.Linq;
  10. using System.Windows.Controls;
  11. namespace PRSDesktop;
  12. /// <summary>
  13. /// Interaction logic for JobRequisitionPurchasing.xaml
  14. /// </summary>
  15. public partial class ReservationManagementPurchasing : UserControl
  16. {
  17. public delegate void PurchaseOrderSaved();
  18. public event PurchaseOrderSaved? OnPurchaseOrderSaved;
  19. private PurchaseOrder Order { get; set; } = new PurchaseOrder();
  20. private List<JobRequiItemLinking> JobRequiItems = new List<JobRequiItemLinking>();
  21. private class JobRequiItemLinking
  22. {
  23. public JobRequisitionItem JobRequiItem { get; set; }
  24. public PurchaseOrderItemAllocation? POAllocation { get; set; }
  25. public PurchaseOrderItem? PurchaseOrderItem { get; set; }
  26. public JobRequiItemLinking(JobRequisitionItem jobRequiItem, PurchaseOrderItem purchaseOrderItem)
  27. {
  28. JobRequiItem = jobRequiItem;
  29. PurchaseOrderItem = purchaseOrderItem;
  30. POAllocation = null;
  31. }
  32. public JobRequiItemLinking(JobRequisitionItem jobRequiItem, PurchaseOrderItemAllocation poAllocation)
  33. {
  34. JobRequiItem = jobRequiItem;
  35. PurchaseOrderItem = null;
  36. POAllocation = poAllocation;
  37. }
  38. }
  39. bool bLoaded = false;
  40. public bool EditorChanged { get; private set; }
  41. public ReservationManagementPurchasing()
  42. {
  43. InitializeComponent();
  44. CreatePOEditor();
  45. }
  46. private void ReloadJobRequiItems(Guid orderID)
  47. {
  48. JobRequiItems.Clear();
  49. if(orderID != Guid.Empty)
  50. {
  51. var _allocations = Client.Query(
  52. new Filter<PurchaseOrderItemAllocation>(x => x.Item.PurchaseOrderLink.ID).IsEqualTo(orderID),
  53. Columns.None<PurchaseOrderItemAllocation>().Add(x => x.ID).Add(x => x.JobRequisitionItem.ID))
  54. .ToObjects<PurchaseOrderItemAllocation>();
  55. foreach (var _allocation in _allocations)
  56. {
  57. var jri = new JobRequisitionItem
  58. {
  59. ID = _allocation.JobRequisitionItem.ID
  60. };
  61. JobRequiItems.Add(new JobRequiItemLinking(jri, _allocation));
  62. }
  63. }
  64. }
  65. public void LoadFromRequiLine(Guid orderID)
  66. {
  67. if (bLoaded)
  68. return;
  69. ReloadJobRequiItems(orderID);
  70. if (orderID != Guid.Empty)
  71. {
  72. if (orderID != Order.ID)
  73. {
  74. LoadPO(orderID);
  75. }
  76. }
  77. else
  78. ClearEditor();
  79. }
  80. private void LoadPO(Guid orderID)
  81. {
  82. var po = Client.Query(
  83. new Filter<PurchaseOrder>(x => x.ID).IsEqualTo(orderID),
  84. Columns.None<PurchaseOrder>().Add(
  85. x => x.ID,
  86. x => x.SupplierLink.ID,
  87. x => x.SupplierLink.Code,
  88. x => x.SupplierLink.Name,
  89. x => x.Description,
  90. x => x.Category.ID,
  91. x => x.Category.Code,
  92. x => x.Category.Description,
  93. x => x.RaisedBy.ID,
  94. x => x.RaisedBy.Code,
  95. x => x.RaisedBy.Name,
  96. x => x.DueDate,
  97. x => x.IssuedBy.ID,
  98. x => x.IssuedBy.Code,
  99. x => x.IssuedBy.Name,
  100. x => x.IssuedDate,
  101. x => x.ClosedDate,
  102. x => x.PONumber))
  103. .ToObjects<PurchaseOrder>().FirstOrDefault();
  104. if (po is not null)
  105. {
  106. Order = po;
  107. CreatePOEditor(new BaseObject[] { po });
  108. }
  109. }
  110. private void CreatePOEditor(BaseObject[]? items = null)
  111. {
  112. DetailBorder.Child = null;
  113. Editor = new EmbeddedDynamicEditorForm();
  114. Editor.SetLayoutType<VerticalDynamicEditorGridLayout>();
  115. Editor.SetValue(Grid.RowProperty, 1);
  116. Editor.SetValue(Grid.ColumnProperty, 0);
  117. Editor.SetValue(Grid.ColumnSpanProperty, 4);
  118. Editor.HighlightButtons = true;
  119. Editor.HideButtons = true;
  120. EditorChanged = false;
  121. Editor.OnAfterEditorValueChanged += (sender, args) =>
  122. {
  123. EditorChanged = true;
  124. Editor.HideButtons = false;
  125. return null;
  126. };
  127. Editor.OnOK += () =>
  128. {
  129. var cancel = new System.ComponentModel.CancelEventArgs();
  130. Editor.SaveItem(cancel);
  131. Editor.HideButtons = true;
  132. SaveJRIPOIs();
  133. OnPurchaseOrderSaved?.Invoke();
  134. EditorChanged = false;
  135. bLoaded = false;
  136. };
  137. Editor.OnCancel += () =>
  138. {
  139. Editor.HideButtons = true;
  140. bLoaded = false;
  141. var orderID = Order.ID;
  142. Order = new PurchaseOrder();
  143. JobRequiItems.Clear();
  144. LoadFromRequiLine(orderID);
  145. EditorChanged = false;
  146. };
  147. Editor.OnChanged += (sender, args) =>
  148. {
  149. EditorChanged = true;
  150. Editor.HideButtons = false;
  151. };
  152. DetailBorder.Child = Editor;
  153. var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(PurchaseOrder));
  154. grid.InitialiseEditorForm(Editor, items ?? new object[] { new PurchaseOrder() });
  155. var loadPO = new Button
  156. {
  157. Content = "Load PO",
  158. Height = 30,
  159. Margin = new System.Windows.Thickness(2, 0, 0, 0),
  160. Padding = new System.Windows.Thickness(15, 0, 15, 0)
  161. };
  162. loadPO.Click += LoadPO_Click;
  163. Editor.AddButton(loadPO);
  164. }
  165. private void LoadPO_Click(object sender, System.Windows.RoutedEventArgs e)
  166. {
  167. var popup = new PopupList(typeof(PurchaseOrder), Guid.Empty, Array.Empty<string>());
  168. if(popup.ShowDialog() == true)
  169. {
  170. bLoaded = true;
  171. LoadPO(popup.ID);
  172. }
  173. }
  174. private void SaveJRIPOIs()
  175. {
  176. var jriPois = new List<PurchaseOrderItemAllocation>();
  177. var jris = new List<JobRequisitionItem>();
  178. foreach(var item in JobRequiItems)
  179. {
  180. if(item.PurchaseOrderItem is not null)
  181. {
  182. var jriPoi = new PurchaseOrderItemAllocation();
  183. jriPoi.Job.ID = item.JobRequiItem.Job.ID;
  184. jriPoi.JobRequisitionItem.ID = item.JobRequiItem.ID;
  185. jriPoi.Item.ID = item.PurchaseOrderItem.ID;
  186. jriPoi.Quantity = item.PurchaseOrderItem.Qty;
  187. jriPois.Add(jriPoi);
  188. item.POAllocation = jriPoi;
  189. jris.Add(item.JobRequiItem);
  190. }
  191. }
  192. Client.Save(
  193. jriPois,
  194. "Updated from Job Requi Review Create Purchase Order");
  195. Client.Save(
  196. jris,
  197. "Marked as on order");
  198. }
  199. private void ClearEditor()
  200. {
  201. Order = new PurchaseOrder();
  202. CreatePOEditor();
  203. }
  204. public void DropItems(IList<CoreRow> rows)
  205. {
  206. var page = Editor.Pages.OfType<SupplierPurchaseOrderItemOneToMany>().First();
  207. if(CreatePOItemsFromRequiItems(rows.ToArray<JobRequisitionItem>(), page.Items))
  208. {
  209. page.Refresh(false, true);
  210. page.DoChanged();
  211. }
  212. }
  213. public bool CreatePOItemsFromRequiItems(IList<JobRequisitionItem> selected, List<PurchaseOrderItem> items)
  214. {
  215. // These columns probably are already there, but if they aren't, let's load them.
  216. Client.EnsureColumns(selected,
  217. Columns.None<JobRequisitionItem>()
  218. .Add(x => x.Qty)
  219. .Add(x => x.Issued)
  220. .Add(x => x.InStock)
  221. .Add(x => x.ID)
  222. .Add(x => x.Product.Name)
  223. .Add(x => x.Product.ID)
  224. .Add(x => x.Style.ID)
  225. .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Data));
  226. var changed = false;
  227. foreach (var jobRequisitionItem in selected)
  228. {
  229. // We only want stuff which doesn't have enough total stock allocated, which is the InStock and Issued added together.
  230. if(!jobRequisitionItem.Qty.IsEffectivelyGreaterThan(jobRequisitionItem.InStock + jobRequisitionItem.Issued))
  231. continue;
  232. // Filter out ones we've already got.
  233. if(JobRequiItems.Any(x => x.JobRequiItem.ID == jobRequisitionItem.ID))
  234. {
  235. continue;
  236. }
  237. var poItem = new PurchaseOrderItem
  238. {
  239. Description = jobRequisitionItem.Product.Name,
  240. Qty = jobRequisitionItem.Qty
  241. };
  242. poItem.Product.ID = jobRequisitionItem.Product.ID;
  243. poItem.Product.Synchronise(jobRequisitionItem.Product);
  244. poItem.Dimensions.CopyFrom(jobRequisitionItem.Dimensions);
  245. poItem.Style.ID = jobRequisitionItem.Style.ID;
  246. poItem.Style.Synchronise(jobRequisitionItem.Style);
  247. items.Add(poItem);
  248. JobRequiItems.Add(new JobRequiItemLinking(jobRequisitionItem, poItem));
  249. changed = true;
  250. }
  251. return changed;
  252. }
  253. }