ConsignmentItemGrid.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Media.Imaging;
  8. using Comal.Classes;
  9. using InABox.Clients;
  10. using InABox.Core;
  11. using InABox.DynamicGrid;
  12. using InABox.Wpf;
  13. using InABox.WPF;
  14. using Microsoft.Xaml.Behaviors.Core;
  15. using PRSDesktop.Panels.PurchaseOrders;
  16. using PurchaseOrder = MYOB.AccountRight.SDK.Contracts.Version2.Purchase.PurchaseOrder;
  17. using PurchaseOrderItemAllocation = Comal.Classes.PurchaseOrderItemAllocation;
  18. namespace PRSDesktop;
  19. public class ConsignmentItemGrid : DynamicDataGrid<PurchaseOrderItem>
  20. {
  21. private Button receiveall;
  22. private Button receiveselected;
  23. private Button allocateparcels;
  24. public Guid ConsignmentID { get; set; } = CoreUtils.FullGuid;
  25. public Guid ParcelID { get; set; } = Guid.Empty;
  26. public bool Completed { get; set; }
  27. public Func<CoreTable>? GetParcels { get; set; }
  28. protected override void Init()
  29. {
  30. base.Init();
  31. HiddenColumns.Add(x=>x.ConsignmentParcel.ID);
  32. HiddenColumns.Add(x=>x.ConsignmentParcel.Description);
  33. allocateparcels = AddButton("Parcels", null, ShowParcelMenu);
  34. allocateparcels.IsEnabled = false;
  35. receiveall = AddButton("Receive All", null, ReceiveAll);
  36. receiveall.IsEnabled = false;
  37. receiveselected = AddButton("Receive Selected", null, ReceiveSelected);
  38. receiveselected.IsEnabled = false;
  39. AddButton("Assign Location", null, SupplierPurchaseOrderItemOneToMany.AssignLocation);
  40. ActionColumns.Add(
  41. new DynamicMenuColumn(
  42. DoBuildMenu,
  43. row => row.Get<PurchaseOrderItem,DateTime>(x=>x.ReceivedDate).IsEmpty()
  44. ? DynamicMenuStatus.Enabled
  45. : DynamicMenuStatus.Disabled
  46. )
  47. );
  48. }
  49. private void DoBuildMenu(DynamicMenuColumn column, CoreRow? row)
  50. {
  51. if (row is null)
  52. return;
  53. column.AddItem("Split Line", PRSDesktop.Resources.split, SplitLine);
  54. var parcels = GetParcels?.Invoke().ToArray<ConsignmentParcel>() ?? [];
  55. if (parcels.Any())
  56. {
  57. column.AddSeparator();
  58. foreach (var parcel in parcels.Where(x=>x.ID != Guid.Empty && x.ID != CoreUtils.FullGuid))
  59. column.AddItem(parcel.Description, null, r => AllocateParcels([r], parcel));
  60. if (row.Get<PurchaseOrderItem, Guid>(x => x.ConsignmentParcel.ID) != Guid.Empty)
  61. {
  62. column.AddSeparator();
  63. column.AddItem("Clear Parcel", null, r => AllocateParcels([r], new ConsignmentParcel()));
  64. }
  65. }
  66. }
  67. private void SplitLine(CoreRow? row)
  68. {
  69. if (row is null || !row.Get<PurchaseOrderItem, DateTime>(x => x.ReceivedDate).IsEmpty())
  70. return;
  71. Guid itemid = row.Get<PurchaseOrderItem, Guid>(x => x.ID);
  72. var query = new MultiQuery();
  73. query.Add(
  74. new Filter<PurchaseOrderItem>(x => x.ID).IsEqualTo(itemid),
  75. Columns.Local<PurchaseOrderItem>()
  76. );
  77. query.Add(
  78. new Filter<PurchaseOrderItemAllocation>(x => x.Item.ID),
  79. Columns.Local<PurchaseOrderItemAllocation>()
  80. );
  81. query.Query();
  82. var item = query.Get<PurchaseOrderItem>().ToObjects<PurchaseOrderItem>().FirstOrDefault() ?? new PurchaseOrderItem();
  83. var allocations = query.Get<PurchaseOrderItemAllocation>().ToList<PurchaseOrderItemAllocation>();
  84. var splits = allocations.ToList(SupplierPurchaseOrderItemSplit.FromAllocation);
  85. if (SupplierPurchaseOrderItemSplitWindow.Execute(item.Qty, splits, out var value))
  86. {
  87. var newItem = item.Clone();
  88. newItem.ID = Guid.Empty;
  89. newItem.CommitChanges();
  90. newItem.Qty = item.Qty - value;
  91. item.Qty = value;
  92. foreach(var split in splits)
  93. {
  94. var allocation = allocations.FirstOrDefault(x => x.ID == split.AllocationID);
  95. if (allocation is null)
  96. continue;
  97. var newAllocation = new PurchaseOrderItemAllocation();
  98. newAllocation.Job.CopyFrom(allocation.Job);
  99. newAllocation.JobRequisitionItem.CopyFrom(allocation.JobRequisitionItem);
  100. newAllocation.Quantity = allocation.Quantity - split.SplitQuantity;
  101. allocations.Add(newAllocation);
  102. allocation.Quantity = split.SplitQuantity;
  103. }
  104. Progress.ShowModal("Saving items", progress =>
  105. {
  106. Client.Save([item,newItem],"Split Consignment Line");
  107. Client.Save(allocations,"Split Consignment Line");
  108. });
  109. Refresh(false,true);
  110. }
  111. }
  112. private bool ShowParcelMenu(Button button, CoreRow[] rows)
  113. {
  114. var parcels = GetParcels?.Invoke()?.ToArray<ConsignmentParcel>() ?? [];
  115. if (!parcels.Any())
  116. return false;
  117. ContextMenu menu = new ContextMenu();
  118. if (rows.Any(r => r.Get<PurchaseOrderItem,Guid>(c => c.ConsignmentParcel.ID) != Guid.Empty))
  119. {
  120. menu.Items.Add(
  121. new MenuItem()
  122. {
  123. Header = "Clear Allocation",
  124. Command = new ActionCommand(() => AllocateParcels(rows, new ConsignmentParcel()))
  125. });
  126. menu.Items.Add(new Separator());
  127. }
  128. foreach (var parcel in parcels.Where(p => p.ID != Guid.Empty && p.ID != CoreUtils.FullGuid))
  129. menu.Items.Add(
  130. new MenuItem()
  131. {
  132. Header = parcel.Description,
  133. Command = new ActionCommand(() => AllocateParcels(rows, parcel))
  134. }
  135. );
  136. menu.IsOpen = true;
  137. return false;
  138. }
  139. private void AllocateParcels(CoreRow[] rows, ConsignmentParcel parcel)
  140. {
  141. List<PurchaseOrderItem> updates = new();
  142. foreach (var row in rows)
  143. {
  144. var update = row.ToObject<PurchaseOrderItem>();
  145. update.ConsignmentParcel.CopyFrom(parcel);
  146. updates.Add(update);
  147. row.Set<PurchaseOrderItem,Guid>(x=>x.ConsignmentParcel.ID, parcel.ID);
  148. row.Set<PurchaseOrderItem,string>(x=>x.ConsignmentParcel.Description, parcel.Description);
  149. InvalidateRow(row);
  150. }
  151. Client.Save(updates,"Updated from Consignment Screen", (o,e) => { });
  152. }
  153. protected override void DoReconfigure(DynamicGridOptions options)
  154. {
  155. base.DoReconfigure(options);
  156. options.RecordCount = true;
  157. options.SelectColumns = true;
  158. options.AddRows = true;
  159. options.DeleteRows = true;
  160. options.MultiSelect = true;
  161. options.FilterRows = true;
  162. options.HideDatabaseFilters = true;
  163. }
  164. protected override void SelectItems(CoreRow[]? rows)
  165. {
  166. var parcels = GetParcels?.Invoke()?.ToArray<ConsignmentParcel>() ?? [];
  167. allocateparcels.IsEnabled = parcels.Any() && rows != null && rows.Any(r => r.Get<PurchaseOrderItem, DateTime>(c => c.ReceivedDate).IsEmpty());
  168. receiveselected.IsEnabled = rows != null && rows.Any(r => r.Get<PurchaseOrderItem, DateTime>(c => c.ReceivedDate).IsEmpty());
  169. receiveall.IsEnabled = Data.Rows.Any(r => r.Get<PurchaseOrderItem, DateTime>(c => c.ReceivedDate).IsEmpty());
  170. base.SelectItems(rows);
  171. }
  172. private bool ReceiveAll(Button sender, CoreRow[] rows)
  173. {
  174. var unreceived = Data.Rows.Where(r => r.Get<PurchaseOrderItem, DateTime>(c => c.ReceivedDate).IsEmpty());
  175. if (!unreceived.Any())
  176. {
  177. MessageBox.Show("No Items to Receive");
  178. return false;
  179. }
  180. var now = DateTime.Now;
  181. using (new WaitCursor())
  182. {
  183. var items = unreceived.Select(x => x.ToObject<PurchaseOrderItem>());
  184. foreach (var item in items)
  185. item.ReceivedDate = now;
  186. new Client<PurchaseOrderItem>().Save(items, "Consignment Items Received");
  187. }
  188. return true;
  189. }
  190. private bool ReceiveSelected(Button sender, CoreRow[] rows)
  191. {
  192. if (!rows.Any())
  193. {
  194. MessageBox.Show("Please select a row first");
  195. return false;
  196. }
  197. var now = DateTime.Now;
  198. using (new WaitCursor())
  199. {
  200. var items = LoadItems(rows);
  201. foreach (var item in items)
  202. item.ReceivedDate = now;
  203. new Client<PurchaseOrderItem>().Save(items, "Consignment Items Received");
  204. }
  205. return true;
  206. }
  207. protected override void Reload(
  208. Filters<PurchaseOrderItem> criteria, Columns<PurchaseOrderItem> columns, ref SortOrder<PurchaseOrderItem>? sort,
  209. CancellationToken token, Action<CoreTable?, Exception?> action)
  210. {
  211. criteria.Add(new Filter<PurchaseOrderItem>(x => x.Consignment.ID).IsEqualTo(
  212. ConsignmentID == Guid.Empty ? CoreUtils.FullGuid : ConsignmentID));
  213. if (ParcelID != CoreUtils.FullGuid)
  214. criteria.Add(new Filter<PurchaseOrderItem>(x=>x.ConsignmentParcel.ID).IsEqualTo(ParcelID));
  215. base.Reload(criteria, columns, ref sort, token, action);
  216. }
  217. protected override void DoAdd(bool openEditorOnDirectEdit = false)
  218. {
  219. if (ConsignmentID.Equals(Guid.Empty))
  220. {
  221. MessageBox.Show("Please select a Requisition first!");
  222. return;
  223. }
  224. if (Completed)
  225. {
  226. MessageBox.Show("Cannot Modify a Completed Requisition");
  227. return;
  228. }
  229. var dialog = new MultiSelectDialog<PurchaseOrderItem>(
  230. new Filter<PurchaseOrderItem>(x => x.Consignment.ID).IsEqualTo(Guid.Empty).And(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue),
  231. Columns.None<PurchaseOrderItem>().Add(x => x.PurchaseOrderLink.PONumber, x => x.Product.Code, x => x.Product.Name, x => x.Description,
  232. x => x.Qty)
  233. //new System.Linq.Expressions.Expression<Func<PurchaseOrderItem, object>>[] { x => x.PurchaseOrderLink.PONumber, x => x.ProductLink.Code, x=>x.ProductLink.Name, x=>x.Description, x=>x.Qty}
  234. );
  235. if (dialog.ShowDialog())
  236. {
  237. Progress.Show("Adding Order Items");
  238. var items = dialog.Items(Columns.Required<PurchaseOrderItem>().Add(x => x.ID).Add(x => x.Consignment.ID));
  239. foreach (var item in items)
  240. item.Consignment.ID = ConsignmentID;
  241. Progress.SetMessage("Updating Items");
  242. new Client<PurchaseOrderItem>().Save(items, "Added to Consignment");
  243. Refresh(false, true);
  244. Progress.Close();
  245. MessageBox.Show(string.Format("{0} order items added", items.Length));
  246. }
  247. }
  248. public override bool EditItems(PurchaseOrderItem[] items, Func<Type, CoreTable?>? PageDataHandler, bool PreloadPages = false)
  249. {
  250. if (ConsignmentID.Equals(Guid.Empty))
  251. {
  252. MessageWindow.ShowMessage("Please select a Requisition first!", "Invalid Action");
  253. return false;
  254. }
  255. if (Completed)
  256. {
  257. MessageWindow.ShowMessage("Cannot Modify a Completed Requisition", "Invalid Action");
  258. return false;
  259. }
  260. return base.EditItems(items, PageDataHandler, PreloadPages);
  261. }
  262. protected override bool CanDeleteItems(CoreRow[] rows)
  263. {
  264. if (ConsignmentID.Equals(Guid.Empty))
  265. {
  266. MessageBox.Show("Please select a Requisition first!");
  267. return false;
  268. }
  269. if (Completed)
  270. {
  271. MessageBox.Show("Cannot Modify a Closed Requisition");
  272. return false;
  273. }
  274. return base.CanDeleteItems(rows);
  275. }
  276. public override void DeleteItems(params CoreRow[] rows)
  277. {
  278. using (new WaitCursor())
  279. {
  280. var items = LoadItems(rows);
  281. foreach (var item in items)
  282. item.Consignment.ID = Guid.Empty;
  283. new Client<PurchaseOrderItem>().Save(items, "Removed from Consignment");
  284. }
  285. }
  286. }