JobRequisitionItemGrid.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Immutable;
  4. using System.Linq;
  5. using System.Reactive.Linq;
  6. using System.Threading;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using Comal.Classes;
  10. using InABox.Clients;
  11. using InABox.Core;
  12. using InABox.DynamicGrid;
  13. using InABox.Wpf;
  14. using InABox.WPF;
  15. using Syncfusion.Windows.Controls.RichTextBoxAdv;
  16. namespace PRSDesktop;
  17. internal class JobRequisitionItemGrid : DynamicDataGrid<JobRequisitionItem>, IMasterDetailControl<JobRequisition, JobRequisitionItem>, ISpecificGrid
  18. {
  19. public Job? Job { get; set; }
  20. private JobRequisition? _master;
  21. public JobRequisition? Master
  22. {
  23. get => _master;
  24. set
  25. {
  26. _master = value;
  27. // CheckVisibility();
  28. Reconfigure();
  29. }
  30. }
  31. public Filter<JobRequisitionItem> MasterDetailFilter => Master != null
  32. ? Master.ID != Guid.Empty
  33. ? new Filter<JobRequisitionItem>(x => x.Requisition.ID).IsEqualTo(Master.ID)
  34. : new Filter<JobRequisitionItem>().None()
  35. : Job is not null && Job.ID != Guid.Empty
  36. ? new Filter<JobRequisitionItem>(x => x.Requisition.Job.ID).IsEqualTo(Job.ID)
  37. : new Filter<JobRequisitionItem>().None();
  38. private Button CreatePickingList;
  39. private Button CreateOrder;
  40. public JobRequisitionItemGrid()
  41. {
  42. HiddenColumns.Add(x=>x.Product.ID);
  43. HiddenColumns.Add(x=>x.Style.ID);
  44. HiddenColumns.Add(x=>x.Dimensions.Unit.ID);
  45. HiddenColumns.Add(x=>x.Dimensions.Unit.HasHeight);
  46. HiddenColumns.Add(x=>x.Dimensions.Unit.HasLength);
  47. HiddenColumns.Add(x=>x.Dimensions.Unit.HasWidth);
  48. HiddenColumns.Add(x=>x.Dimensions.Unit.HasQuantity);
  49. HiddenColumns.Add(x=>x.Dimensions.Unit.HasWeight);
  50. HiddenColumns.Add(x=>x.Dimensions.Unit.Formula);
  51. HiddenColumns.Add(x=>x.Dimensions.Unit.Format);
  52. HiddenColumns.Add(x=>x.Dimensions.Height);
  53. HiddenColumns.Add(x=>x.Dimensions.Length);
  54. HiddenColumns.Add(x=>x.Dimensions.Width);
  55. HiddenColumns.Add(x=>x.Dimensions.Quantity);
  56. HiddenColumns.Add(x=>x.Dimensions.Weight);
  57. HiddenColumns.Add(x=>x.Dimensions.Value);
  58. HiddenColumns.Add(x=>x.Dimensions.UnitSize);
  59. HiddenColumns.Add(x=>x.PickRequested);
  60. CreateOrder = AddButton("Create Order", PRSDesktop.Resources.purchase.AsBitmapImage(), DoCreatePurchaseOrder);
  61. CreatePickingList = AddButton("Create Picking List", PRSDesktop.Resources.trolley.AsBitmapImage(), DoCreatePickingList);
  62. }
  63. protected override void SelectItems(CoreRow[]? rows)
  64. {
  65. base.SelectItems(rows);
  66. CreatePickingList.IsEnabled = rows?.Any() == true;
  67. }
  68. #region CreatePurchaseOrder
  69. private bool DoCreatePurchaseOrder(Button button, CoreRow[]? rows)
  70. {
  71. if (rows?.Any() != true)
  72. return false;
  73. MultiSelectDialog<Supplier> dlg = new MultiSelectDialog<Supplier>(
  74. LookupFactory.DefineFilter<Supplier>(),
  75. Columns.None<Supplier>()
  76. .Add(x => x.ID)
  77. .Add(x => x.Code)
  78. .Add(x => x.Name),
  79. false
  80. );
  81. var _po = new PurchaseOrder();
  82. if (dlg.ShowDialog())
  83. {
  84. Progress.ShowModal("Creating Purchase Order", progress =>
  85. {
  86. _po.Description = "Created from Job Requisition Screen" + System.Environment.NewLine;
  87. _po.RaisedBy.ID = App.EmployeeID;
  88. _po.SupplierLink.ID = dlg.IDs().First();
  89. Client.Save(_po, "Created From Requisition Screen");
  90. progress.Report("Creating Order Items");
  91. Dictionary<Guid,PurchaseOrderItem> _pois = new Dictionary<Guid,PurchaseOrderItem>();
  92. foreach (CoreRow row in SelectedRows)
  93. {
  94. JobRequisitionItem _jri = row.ToObject<JobRequisitionItem>();
  95. PurchaseOrderItem _poi = new PurchaseOrderItem();
  96. _poi.PurchaseOrderLink.ID = _po.ID;
  97. _poi.Product.ID = _jri.Product.ID;
  98. _poi.Product.Code = _jri.Product.Code;
  99. _poi.Product.Name = _jri.Product.Name;
  100. _poi.Qty = _jri.Qty;
  101. _poi.Dimensions.CopyFrom(_jri.Dimensions);
  102. _poi.Dimensions.Value = _jri.Dimensions.Value;
  103. _poi.Style.ID = _jri.Style.ID;
  104. _poi.Style.Code = _jri.Style.Code;
  105. _poi.Style.Description = _jri.Style.Description;
  106. _poi.Job.ID = _jri.Job.ID;
  107. _poi.Dimensions.UnitSize = _jri.Dimensions.UnitSize;
  108. _poi.Description = _jri.Product.Name + " (" + _jri.Dimensions.ToString() + ")";
  109. _pois[_jri.ID] = _poi;
  110. }
  111. Client.Save(_pois.Values, "Created From Requisition Screen");
  112. List<JobRequisitionItemPurchaseOrderItem> _jripois = new();
  113. foreach (var _poi in _pois)
  114. {
  115. var _jripoi = new JobRequisitionItemPurchaseOrderItem();
  116. _jripoi.JobRequisitionItem.ID = _poi.Key;
  117. _jripoi.PurchaseOrderItem.ID = _poi.Value.ID;
  118. _jripois.Add(_jripoi);
  119. }
  120. Client.Save(_jripois, "Created From Requisition Screen");
  121. });
  122. }
  123. new SupplierPurchaseOrders().EditItems(new[] { _po });
  124. return true;
  125. }
  126. #endregion
  127. #region CreatePickingList
  128. private bool DoCreatePickingList(Button button, CoreRow[]? rows)
  129. {
  130. if (rows?.Any() != true)
  131. return false;
  132. if (rows.All(r =>
  133. r.Get<JobRequisitionItem, double>(x => x.PickRequested)
  134. .IsEffectivelyEqual(r.Get<JobRequisitionItem, double>(x => x.Qty))))
  135. {
  136. MessageWindow.ShowMessage("All Items have been picked!","Error");
  137. return false;
  138. }
  139. var picklist = new Requisition();
  140. if (Job != null)
  141. picklist.JobLink.CopyFrom(Job);
  142. else
  143. picklist.JobLink.CopyFrom(Master?.Job ?? new JobLink());
  144. if (new RequisitionGrid().EditItems(new Requisition[] { picklist }))
  145. {
  146. Progress.ShowModal("Creating Picking List", (progress) =>
  147. {
  148. List<RequisitionItem> pickitems = new();
  149. foreach (var item in rows.Select(x => x.ToObject<JobRequisitionItem>()))
  150. {
  151. if (!item.PickRequested.IsEffectivelyEqual(item.Qty))
  152. {
  153. var pickitem = new RequisitionItem();
  154. pickitem.RequisitionLink.ID = picklist.ID;
  155. pickitem.RequisitionLink.Synchronise(picklist);
  156. pickitem.SourceJRI.ID = item.ID;
  157. pickitem.SourceJRI.Synchronise(item);
  158. pickitem.Product.ID = item.Product.ID;
  159. pickitem.Product.Synchronise(item.Product);
  160. pickitem.Style.ID = item.Style.ID;
  161. pickitem.Style.Synchronise(item.Style);
  162. pickitem.Dimensions.CopyFrom(item.Dimensions);
  163. pickitem.Quantity = item.Qty - item.PickRequested;
  164. pickitems.Add(pickitem);
  165. }
  166. }
  167. Client.Save(pickitems, "Created from Job Requisition");
  168. });
  169. }
  170. return true;
  171. }
  172. #endregion
  173. // private void CheckVisibility()
  174. // {
  175. // CancelItemsButton.Visibility = Master is not null && Security.CanEdit<JobRequisition>() && Security.CanEdit<JobRequisitionItem>()
  176. // ? System.Windows.Visibility.Visible
  177. // : System.Windows.Visibility.Hidden;
  178. // }
  179. // protected override void SelectItems(CoreRow[]? rows)
  180. // {
  181. // base.SelectItems(rows);
  182. // CancelItemsButton.IsEnabled = rows is not null && rows.Length > 0;
  183. // }
  184. //private bool CancelItems(Button button, CoreRow[] rows)
  185. //{
  186. // if (Master is null) return false;
  187. // if(rows.Length == 0)
  188. // {
  189. // MessageWindow.ShowMessage("Please select at least one item to cancel.", "Select items");
  190. // return false;
  191. // }
  192. // // Reloading so I can ensure the correct columns without having to add hidden columns to JobRequisitionGrid.
  193. // var oldRequi = Client.Query(
  194. // new Filter<JobRequisition>(x => x.ID).IsEqualTo(Master?.ID ?? Guid.Empty),
  195. // Columns.None<JobRequisition>().Add(x => x.Description)
  196. // .Add(x => x.Number)
  197. // .Add(x => x.DueDate))
  198. // .ToObjects<JobRequisition>()
  199. // .First();
  200. // var oldRequiItems = Client.Query(
  201. // new Filter<JobRequisitionItem>(x => x.ID).InList(rows.Select(x => x.Get<JobRequisitionItem, Guid>(x => x.ID)).ToArray()),
  202. // Columns.None<JobRequisitionItem>().Add(x => x.Qty)
  203. // .Add(x => x.Sequence)
  204. // .Add(x => x.Job.ID)
  205. // .Add(x => x.Product.ID)
  206. // .Add(x => x.Product.Code)
  207. // .Add(x => x.Style.ID)
  208. // .Add(x => x.Style.Code)
  209. // .Add(x => x.Style.Description)
  210. // .Add(x => x.Dimensions.Unit.ID)
  211. // .Add(x => x.Dimensions.Quantity)
  212. // .Add(x => x.Dimensions.Length)
  213. // .Add(x => x.Dimensions.Width)
  214. // .Add(x => x.Dimensions.Height)
  215. // .Add(x => x.Dimensions.Weight)
  216. // .Add(x => x.Dimensions.UnitSize)
  217. // .Add(x => x.Supplier.ID));
  218. // var requisition = new JobRequisition
  219. // {
  220. // Description = $"Adjustment Requisition for Requisition {oldRequi.Number}",
  221. // DueDate = oldRequi.DueDate
  222. // };
  223. // requisition.Job.ID = Master.Job.ID;
  224. // requisition.Job.Synchronise(Master.Job);
  225. // var requiItems = new List<JobRequisitionItem>();
  226. // foreach(var oldItem in oldRequiItems.ToObjects<JobRequisitionItem>())
  227. // {
  228. // var newItem = new JobRequisitionItem
  229. // {
  230. // Notes = "Adjustment Requisition item",
  231. // Qty = -oldItem.Qty,
  232. // Sequence = oldItem.Sequence
  233. // };
  234. // newItem.Job.ID = requisition.Job.ID;
  235. // newItem.Product.ID = oldItem.Product.ID;
  236. // newItem.Style.ID = oldItem.Style.ID;
  237. // newItem.Supplier.ID = oldItem.Supplier.ID;
  238. // requiItems.Add(newItem);
  239. // }
  240. // var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicGrid<>), typeof(JobRequisition));
  241. // if (grid.EditItems(new JobRequisition[] { requisition }, t =>
  242. // {
  243. // if (t == typeof(JobRequisitionItem))
  244. // {
  245. // var table = new CoreTable();
  246. // table.LoadColumns(new Columns<JobRequisitionItem>(ColumnTypeFlags.Local | ColumnTypeFlags.IncludeAggregates | ColumnTypeFlags.IncludeFormulae | ColumnTypeFlags.Required));
  247. // table.LoadRows(requiItems);
  248. // return table;
  249. // }
  250. // return null;
  251. // }))
  252. // {
  253. // MessageWindow.ShowMessage($"Created requisition {requisition.Number}", "Created Requisition");
  254. // return true;
  255. // }
  256. // else
  257. // {
  258. // return false;
  259. // }
  260. //}
  261. protected override void DoReconfigure(DynamicGridOptions options)
  262. {
  263. base.DoReconfigure(options);
  264. options.RecordCount = true;
  265. options.SelectColumns = true;
  266. options.FilterRows = true;
  267. options.MultiSelect = true;
  268. if(Master is not null)
  269. {
  270. options.AddRows = true;
  271. }
  272. else
  273. {
  274. options.AddRows = false;
  275. }
  276. }
  277. protected override void Reload(
  278. Filters<JobRequisitionItem> criteria, Columns<JobRequisitionItem> columns, ref SortOrder<JobRequisitionItem>? sort,
  279. CancellationToken token, Action<CoreTable?, Exception?> action)
  280. {
  281. criteria.Add(MasterDetailFilter);
  282. base.Reload(criteria, columns, ref sort, token, action);
  283. }
  284. protected override bool CanCreateItems()
  285. {
  286. return base.CanCreateItems() && (Master?.ID ?? Guid.Empty) != Guid.Empty;
  287. }
  288. public override JobRequisitionItem CreateItem()
  289. {
  290. var result = base.CreateItem();
  291. if(Master is not null)
  292. {
  293. result.Requisition.ID = Master.ID;
  294. result.Requisition.Synchronise(Master);
  295. result.Job.ID = Master.Job.ID;
  296. result.Job.Synchronise(Master.Job);
  297. }
  298. result.Qty = 1;
  299. return result;
  300. }
  301. protected override void OnAfterEditorValueChanged(DynamicEditorGrid? grid, JobRequisitionItem[] items, AfterEditorValueChangedArgs args, Dictionary<string, object?> changes)
  302. {
  303. base.OnAfterEditorValueChanged(grid, items, args, changes);
  304. if (args.ColumnName.Equals("Product.ID") || args.ColumnName.Equals("Dimensions") || args.ColumnName.StartsWith("Dimensions.") || args.ColumnName.Equals("Style.ID") || args.ColumnName.Equals("Supplier.ID"))
  305. {
  306. JobRequisitionItem.UpdateCosts(
  307. items,
  308. changes
  309. );
  310. }
  311. }
  312. public override DynamicGridColumns GenerateColumns()
  313. {
  314. var columns = new DynamicGridColumns();
  315. columns.Add<JobRequisitionItem, DateTime>(x => x.Created, 80, "Date", "", Alignment.MiddleLeft);
  316. columns.Add<JobRequisitionItem, string>(x => x.Requisition.Job.JobNumber, 70, "Job", "", Alignment.MiddleLeft);
  317. columns.Add<JobRequisitionItem, int>(x => x.Requisition.Number, 50, "NO.", "", Alignment.MiddleLeft);
  318. columns.Add<JobRequisitionItem, string>(x => x.Product.Code, 70, "Code", "", Alignment.MiddleLeft);
  319. columns.Add<JobRequisitionItem, string>(x => x.Product.Name, 200, "Product Name", "", Alignment.MiddleLeft);
  320. columns.Add<JobRequisitionItem, string>(x => x.Style.Description, 150, "Style", "", Alignment.MiddleLeft);
  321. columns.Add<JobRequisitionItem, double>(x => x.Qty, 50, "Qty", "", Alignment.MiddleLeft);
  322. columns.Add<JobRequisitionItem, string>(x => x.Dimensions.UnitSize, 50, "Size", "", Alignment.MiddleLeft);
  323. columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderNumbers, 80, "PO Numbers", "", Alignment.MiddleLeft);
  324. columns.Add<JobRequisitionItem, string>(x => x.Notes, 300, "Notes", "", Alignment.MiddleLeft);
  325. columns.AddRange(base.GenerateColumns());
  326. return columns;
  327. }
  328. }