JobRequisitionReviewGrid.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. using Comal.Classes;
  2. using InABox.Clients;
  3. using InABox.Configuration;
  4. using InABox.Core;
  5. using InABox.DynamicGrid;
  6. using InABox.WPF;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Drawing;
  10. using System.Linq;
  11. using System.Windows;
  12. using System.Windows.Controls;
  13. namespace PRSDesktop
  14. {
  15. public class JobRequisitionReviewUserSettings : IUserConfigurationSettings
  16. {
  17. public DynamicGridFilter Filter { get; set; }
  18. public JobRequisitionReviewUserSettings()
  19. {
  20. Filter = new DynamicGridFilter();
  21. }
  22. }
  23. public delegate void JobRequiItemSelect(CoreRow[] rows);
  24. public delegate void GridRefresh();
  25. public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
  26. {
  27. public event JobRequiItemSelect OnJobRequiItemSelected;
  28. public event GridRefresh OnGridRefresh;
  29. public Guid empID = new Guid();
  30. string empName = "";
  31. bool bIncludeArchived = false;
  32. bool bViewCancelled = false;
  33. JobRequisitionReviewUserSettings FilterSettings = new JobRequisitionReviewUserSettings();
  34. Dictionary<Guid, double> JobRequisReservedQty = new Dictionary<Guid, double>();
  35. public JobRequisitionReviewGrid()
  36. {
  37. FilterSettings = new UserConfiguration<JobRequisitionReviewUserSettings>().Load();
  38. if (!string.IsNullOrWhiteSpace(FilterSettings.Filter.Name))
  39. {
  40. SelectedFilter = new(FilterSettings.Filter.Name, Serialization.Deserialize<Filter<JobRequisitionItem>>(FilterSettings.Filter.Filter));
  41. UpdateFilterButton(InABox.Wpf.Resources.filter_set);
  42. }
  43. Options.AddRange(
  44. DynamicGridOption.FilterRows,
  45. DynamicGridOption.SelectColumns,
  46. DynamicGridOption.RecordCount
  47. );
  48. Options.Remove(DynamicGridOption.AddRows);
  49. Options.Remove(DynamicGridOption.EditRows);
  50. Options.Remove(DynamicGridOption.ImportData);
  51. Options.Remove(DynamicGridOption.ExportData);
  52. Options.Remove(DynamicGridOption.Print);
  53. Options.Remove(DynamicGridOption.ShowHelp);
  54. HiddenColumns.Add(x => x.ID);
  55. HiddenColumns.Add(x => x.Product.ID);
  56. HiddenColumns.Add(x => x.Product.Code);
  57. HiddenColumns.Add(x => x.Product.Group.ID);
  58. HiddenColumns.Add(x => x.Product.Group.Code);
  59. HiddenColumns.Add(x => x.Product.Group.Description);
  60. HiddenColumns.Add(x => x.Style.ID);
  61. HiddenColumns.Add(x => x.Style.Code);
  62. HiddenColumns.Add(x => x.Style.Description);
  63. HiddenColumns.Add(x => x.Requisition.ID);
  64. HiddenColumns.Add(x => x.Requisition.Job.ID);
  65. HiddenColumns.Add(x => x.Requisition.Job.JobNumber);
  66. HiddenColumns.Add(x => x.Requisition.Job.Name);
  67. HiddenColumns.Add(x => x.Requisition.Number);
  68. HiddenColumns.Add(x => x.PurchaseOrderItem.ID);
  69. HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.ID);
  70. HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber);
  71. HiddenColumns.Add(x => x.PurchaseOrderItem.DueDate);
  72. HiddenColumns.Add(x => x.Job.ID);
  73. HiddenColumns.Add(x => x.Job.Name);
  74. HiddenColumns.Add(x => x.Job.JobNumber);
  75. HiddenColumns.Add(x => x.Dimensions.UnitSize);
  76. HiddenColumns.Add(x => x.Dimensions.Length);
  77. HiddenColumns.Add(x => x.Dimensions.Width);
  78. HiddenColumns.Add(x => x.Dimensions.Height);
  79. HiddenColumns.Add(x => x.Dimensions.Weight);
  80. HiddenColumns.Add(x => x.Dimensions.Quantity);
  81. HiddenColumns.Add(x => x.Dimensions.Value);
  82. HiddenColumns.Add(x => x.Dimensions.Unit.ID);
  83. HiddenColumns.Add(x => x.Dimensions.Unit.HasLength);
  84. HiddenColumns.Add(x => x.Dimensions.Unit.HasHeight);
  85. HiddenColumns.Add(x => x.Dimensions.Unit.HasWidth);
  86. HiddenColumns.Add(x => x.Dimensions.Unit.HasWeight);
  87. HiddenColumns.Add(x => x.Dimensions.Unit.HasQuantity);
  88. HiddenColumns.Add(x => x.Dimensions.Unit.Formula);
  89. HiddenColumns.Add(x => x.Dimensions.Unit.Format);
  90. HiddenColumns.Add(x => x.Dimensions.Unit.Code);
  91. HiddenColumns.Add(x => x.Dimensions.Unit.Description);
  92. LoadStockMovements();
  93. if (Security.CanEdit<JobRequisitionItem>())
  94. ActionColumns.Add(new DynamicMenuColumn(BuildMenu));
  95. //if (Security.CanEdit<PurchaseOrder>())
  96. // AddButton("Create Purchase Order", null, CreatePurchaseOrder);
  97. //if (Security.CanEdit<PurchaseOrder>())
  98. // AddButton("Create Treatment PO", null, CreateTreatmentPO);
  99. AddButton("Include Archived", null, ViewArchived);
  100. AddButton("Include Cancelled", null, ViewCancelled);
  101. OnSelectItem += JobRequisitionReviewGrid_OnSelectItem;
  102. ColumnsTag = "JobRequisitionReview";
  103. CoreTable table = new Client<Employee>().Query(new Filter<Employee>(x => x.UserLink.UserID).IsEqualTo(ClientFactory.UserID), new Columns<Employee>(x => x.ID, x => x.Name));
  104. if (table.Rows.Any())
  105. {
  106. empID = Guid.Parse(table.Rows.FirstOrDefault().Values[0].ToString());
  107. empName = table.Rows.FirstOrDefault().Values[1].ToString();
  108. }
  109. OnFilterSelected += GridOnFilterSelected;
  110. //Migrate();
  111. }
  112. private void GridOnFilterSelected(DynamicGridFilter filter, Bitmap image)
  113. {
  114. new UserConfiguration<JobRequisitionReviewUserSettings>().Save(new JobRequisitionReviewUserSettings { Filter = filter });
  115. OnGridRefresh?.Invoke();
  116. }
  117. private void Migrate()
  118. {
  119. CoreTable table = new Client<JobRequisitionItem>().Query(null, new Columns<JobRequisitionItem>(x => x.ID, x => x.PurchaseOrderItem.PurchaseOrderLink.ID));
  120. Dictionary<Guid, Guid> reqPOids = new Dictionary<Guid, Guid>();
  121. List<JobRequisitionItem> affected = new List<JobRequisitionItem>();
  122. foreach (CoreRow row in table.Rows)
  123. {
  124. var item = row.ToObject<JobRequisitionItem>();
  125. if (item.PurchaseOrderItem.PurchaseOrderLink.ID != Guid.Empty)
  126. {
  127. reqPOids.Add(row.Get<JobRequisitionItem, Guid>(x => x.ID), item.PurchaseOrderItem.PurchaseOrderLink.ID);
  128. affected.Add(row.ToObject<JobRequisitionItem>());
  129. }
  130. }
  131. List<JobRequisitionItem> list = new List<JobRequisitionItem>();
  132. CoreTable POs = new Client<PurchaseOrder>().Query(new Filter<PurchaseOrder>(x => x.ID).InList(reqPOids.Values.ToArray()), new Columns<PurchaseOrder>(x => x.ID, x => x.Created));
  133. foreach (CoreRow row in POs.Rows)
  134. {
  135. var items = affected.Where(x => x.PurchaseOrderItem.PurchaseOrderLink.ID == row.Get<PurchaseOrder, Guid>(x => x.ID));
  136. foreach (var item in items)
  137. {
  138. item.Ordered = row.Get<PurchaseOrder, DateTime>(x => x.Created);
  139. list.Add(item);
  140. }
  141. }
  142. new Client<JobRequisitionItem>().Save(list, "Migrate");
  143. }
  144. private void LoadStockMovements()
  145. {
  146. CoreTable table = new Client<StockMovement>().Query(
  147. new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsNotEqualTo(Guid.Empty),
  148. new Columns<StockMovement>(
  149. x => x.JobRequisitionItem.ID,
  150. x => x.Received
  151. )
  152. );
  153. foreach (CoreRow row in table.Rows)
  154. {
  155. var requiID = row.Get<StockMovement, Guid>(x => x.JobRequisitionItem.ID);
  156. var qty = row.Get<StockMovement, double>(x => x.Received);
  157. if (!JobRequisReservedQty.ContainsKey(requiID))
  158. JobRequisReservedQty.Add(requiID, qty);
  159. else
  160. {
  161. double newQty = JobRequisReservedQty[requiID] + qty;
  162. JobRequisReservedQty.Remove(requiID);
  163. JobRequisReservedQty.Add(requiID, newQty);
  164. }
  165. }
  166. }
  167. public void AddStockMovements(Guid requiItemID)
  168. {
  169. CoreTable table = new Client<StockMovement>().Query(new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsEqualTo(requiItemID),
  170. new Columns<StockMovement>(
  171. x => x.JobRequisitionItem.ID,
  172. x => x.Received
  173. )
  174. );
  175. if (table.Rows.Any())
  176. {
  177. foreach (CoreRow row in table.Rows)
  178. {
  179. var requiID = row.Get<StockMovement, Guid>(x => x.JobRequisitionItem.ID);
  180. var qty = row.Get<StockMovement, double>(x => x.Received);
  181. if (!JobRequisReservedQty.ContainsKey(requiID))
  182. JobRequisReservedQty.Add(requiID, qty);
  183. else if (JobRequisReservedQty.ContainsKey(requiID) && row == table.Rows.First())
  184. {
  185. JobRequisReservedQty.Remove(requiID);
  186. JobRequisReservedQty.Add(requiID, qty);
  187. }
  188. else
  189. {
  190. double newQty = JobRequisReservedQty[requiID] + qty;
  191. JobRequisReservedQty.Remove(requiID);
  192. JobRequisReservedQty.Add(requiID, newQty);
  193. }
  194. }
  195. }
  196. }
  197. private string? CreateStatus(CoreRow? row)
  198. {
  199. Guid id = row.Get<JobRequisitionItem, Guid>(x => x.ID);
  200. string status = "Not Checked";
  201. if (row.Get<JobRequisitionItem, DateTime>(x => x.Cancelled) != DateTime.MinValue)
  202. return "Cancelled";
  203. if (row.Get<JobRequisitionItem, DateTime>(x => x.Archived) != DateTime.MinValue)
  204. return "Archived";
  205. if (row.Get<JobRequisitionItem, DateTime>(x => x.Ordered) != DateTime.MinValue && !JobRequisReservedQty.ContainsKey(id))
  206. return "On Order";
  207. if (row.Get<JobRequisitionItem, JobRequisitionItemStatus>(x => x.Status) == JobRequisitionItemStatus.OrderRequired)
  208. return "Order Required";
  209. if (JobRequisReservedQty.ContainsKey(id))
  210. if (JobRequisReservedQty[id] >= row.Get<JobRequisitionItem, double>(x => x.Qty))
  211. return "Reserved";
  212. return status;
  213. }
  214. protected override DynamicGridStyle GetRowStyle(CoreRow row, DynamicGridStyle style)
  215. {
  216. var result = base.GetRowStyle(row, style);
  217. //var item = row.ToObject<JobRequisitionItem>();
  218. //if (item.Status == JobRequisitionItemStatus.NotChecked)
  219. //{
  220. // var rowstyle = new DynamicGridRowStyle();
  221. // rowstyle.Background = new SolidColorBrush(Colors.LightSalmon);
  222. // return rowstyle;
  223. //}
  224. //if (item.Status == JobRequisitionItemStatus.OrderRequired)
  225. //{
  226. // var rowstyle = new DynamicGridRowStyle();
  227. // rowstyle.Background = new SolidColorBrush(Colors.LightCoral);
  228. // return rowstyle;
  229. //}
  230. return result;
  231. }
  232. private void JobRequisitionReviewGrid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
  233. {
  234. OnJobRequiItemSelected?.Invoke(SelectedRows);
  235. }
  236. private bool ViewCancelled(Button button, CoreRow[] rows)
  237. {
  238. if (bViewCancelled)
  239. {
  240. bViewCancelled = false;
  241. button.Content = "Include Cancelled";
  242. }
  243. else
  244. {
  245. bViewCancelled = true;
  246. button.Content = "Exclude Cancelled";
  247. }
  248. OnGridRefresh?.Invoke();
  249. return true;
  250. }
  251. private bool ViewArchived(Button button, CoreRow[] rows)
  252. {
  253. if (bIncludeArchived)
  254. {
  255. bIncludeArchived = false;
  256. button.Content = "Include Archived";
  257. }
  258. else
  259. {
  260. bIncludeArchived = true;
  261. button.Content = "Exclude Archived";
  262. }
  263. OnGridRefresh?.Invoke();
  264. return true;
  265. }
  266. private bool CreateTreatmentPO(Button button, CoreRow[] rows)
  267. {
  268. return true;
  269. }
  270. protected override void GenerateColumns(DynamicGridColumns columns)
  271. {
  272. columns.Add<JobRequisitionItem, DateTime>(x => x.Created, 80, "Date", "", Alignment.MiddleLeft);
  273. columns.Add<JobRequisitionItem, string>(x => x.Requisition.Job.JobNumber, 70, "Job", "", Alignment.MiddleLeft);
  274. columns.Add<JobRequisitionItem, int>(x => x.Requisition.Number, 50, "NO.", "", Alignment.MiddleLeft);
  275. columns.Add<JobRequisitionItem, string>(x => x.Product.Code, 70, "Code", "", Alignment.MiddleLeft);
  276. columns.Add<JobRequisitionItem, string>(x => x.Product.Name, 200, "Product Name", "", Alignment.MiddleLeft);
  277. columns.Add<JobRequisitionItem, string>(x => x.Style.Description, 150, "Style", "", Alignment.MiddleLeft);
  278. columns.Add<JobRequisitionItem, double>(x => x.Qty, 50, "Qty", "", Alignment.MiddleLeft);
  279. columns.Add<JobRequisitionItem, string>(x => x.Dimensions.UnitSize, 50, "Size", "", Alignment.MiddleLeft);
  280. columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
  281. columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
  282. columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.DueDate, 80, "Due", "", Alignment.MiddleLeft);
  283. columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.ReceivedDate, 80, "Received", "", Alignment.MiddleLeft);
  284. columns.Add<JobRequisitionItem, string>(x => x.Notes, 300, "Notes", "", Alignment.MiddleLeft);
  285. }
  286. private DynamicMenuStatus EmptyReturnFunction(CoreRow row)
  287. {
  288. return DynamicMenuStatus.Enabled;
  289. }
  290. #region Action Column Buttons
  291. private bool CheckValidAction(JobRequisitionItem item, bool bypassReserved)
  292. {
  293. bool valid = true;
  294. if (item.Status == JobRequisitionItemStatus.Reserved && !bypassReserved)
  295. {
  296. MessageBox.Show("Error. Item has already been reserved!");
  297. return false;
  298. }
  299. else if (item.Status == JobRequisitionItemStatus.OnOrder)
  300. {
  301. MessageBox.Show("Error. Item is already on order!");
  302. return false;
  303. }
  304. if (item.Status == JobRequisitionItemStatus.Received)
  305. {
  306. MessageBox.Show("Error. Item has already been recieved!");
  307. return false;
  308. }
  309. return valid;
  310. }
  311. private void MarkReserved_Clicked(CoreRow? row)
  312. {
  313. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  314. if (CheckValidAction(item, false))
  315. {
  316. SaveRow(row, JobRequisitionItemStatus.Reserved, "Line marked as Reserved by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  317. }
  318. }
  319. private void SplitLine(JobRequisitionItem item, double oldItemQty, double newItemQty, string notes)
  320. {
  321. List<JobRequisitionItem> items = new List<JobRequisitionItem>();
  322. JobRequisitionItem newItem = new JobRequisitionItem();
  323. newItem.Requisition.ID = item.Requisition.ID;
  324. newItem.Requisition.Job.ID = item.Requisition.Job.ID;
  325. newItem.Requisition.Job.JobNumber = item.Requisition.Job.JobNumber;
  326. newItem.Requisition.Job.Name = item.Requisition.Job.Name;
  327. newItem.Product.ID = item.Product.ID;
  328. newItem.Product.Name = item.Product.Name;
  329. newItem.Product.Code = item.Product.Code;
  330. newItem.Product.Group.ID = item.Product.Group.ID;
  331. newItem.Product.Group.Description = item.Product.Group.Description;
  332. newItem.Dimensions.CopyFrom(item.Dimensions);
  333. newItem.Style.ID = item.Style.ID;
  334. newItem.Style.Description = item.Style.Description;
  335. newItem.Style.Code = item.Style.Code;
  336. newItem.Notes = item.Notes + Environment.NewLine + notes;
  337. item.Notes = newItem.Notes;
  338. item.Qty = oldItemQty;
  339. newItem.Qty = newItemQty;
  340. items.Add(newItem);
  341. items.Add(item);
  342. new Client<JobRequisitionItem>().Save(items, "Split lines from Job Requi Item Review Dashboard");
  343. MessageBox.Show("Line split - original line Qty is now " + item.Qty + ". New line Qty is " + newItem.Qty, "Success");
  344. OnGridRefresh?.Invoke();
  345. }
  346. private void SplitLine_Clicked(CoreRow row)
  347. {
  348. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  349. if (CheckValidAction(item, false))
  350. {
  351. int units = Convert.ToInt32(item.Qty);
  352. if (NumberEdit.Execute("Enter amount to split", 1, units, ref units))
  353. {
  354. SplitLine(item, item.Qty - units, units, "Line split");
  355. }
  356. }
  357. }
  358. private void Archive_Clicked(CoreRow row)
  359. {
  360. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  361. item.Archived = DateTime.Now;
  362. SaveRow(row, JobRequisitionItemStatus.Archived, "Line marked as Archived by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  363. }
  364. private void OrderRequired_Clicked(CoreRow row)
  365. {
  366. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  367. if (CheckValidAction(item, false))
  368. SaveRow(row, JobRequisitionItemStatus.OrderRequired, "Line marked as Order Required by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  369. }
  370. private void TreatmentRequired_Clicked(CoreRow row)
  371. {
  372. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  373. if (item.Status != JobRequisitionItemStatus.Reserved)
  374. {
  375. MessageBox.Show("Stock must first be reserved for this item");
  376. return;
  377. }
  378. SaveRow(row, JobRequisitionItemStatus.TreatmentRequired, "Line marked as Treatment Required by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  379. }
  380. private void Uncheck_Clicked(CoreRow row)
  381. {
  382. string extraMessage = "";
  383. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  384. if (!CheckValidAction(item, true))
  385. return;
  386. CoreTable table = new Client<StockMovement>().Query
  387. (
  388. new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsEqualTo(item.ID),
  389. new Columns<StockMovement>(x => x.ID)
  390. );
  391. if (table.Rows.Any())
  392. {
  393. var result = MessageBox.Show("This will reverse stock movements already created for this Requisition Item. Proceed?", "Alert", MessageBoxButton.YesNo);
  394. switch (result)
  395. {
  396. case MessageBoxResult.Yes:
  397. break;
  398. case MessageBoxResult.No:
  399. return;
  400. default:
  401. return;
  402. }
  403. List<StockMovement> movements = new List<StockMovement>();
  404. foreach (CoreRow stockmovementRow in table.Rows)
  405. {
  406. StockMovement movement = new StockMovement();
  407. movement.ID = Guid.Parse(stockmovementRow.Values[0].ToString());
  408. movements.Add(movement);
  409. }
  410. new Client<StockMovement>().Delete(movements, "Stock movements reversed from Job Requisition Item Review Dashboard");
  411. extraMessage = " and Stock Movements Reversed ";
  412. }
  413. SaveRow(row, JobRequisitionItemStatus.NotChecked, "Line marked as Not Checked by " + empName + extraMessage + " on " + DateTime.Now.ToString("dd MMM yy"));
  414. }
  415. private bool CreatePurchaseOrder(Button btn, CoreRow[] rows)
  416. {
  417. if (!rows.Any())
  418. {
  419. MessageBox.Show("Please select at least one row to add to Purchase Order!");
  420. return false;
  421. }
  422. PurchaseOrder purchaseOrder = new PurchaseOrder();
  423. purchaseOrder.Notes = "Created from Job Requi Item Review Screen" + System.Environment.NewLine;
  424. purchaseOrder.RaisedBy.ID = empID;
  425. var page = new SupplierPurchaseOrders();
  426. page.OnAfterSave += (form, items) =>
  427. {
  428. PurchaseOrderOnSave(form, items.Cast<PurchaseOrder>().ToArray());
  429. };
  430. return page.EditItems(new[] { purchaseOrder }, LoadPurchaseOrderItems, true);
  431. }
  432. private void PurchaseOrderOnSave(IDynamicEditorForm form, PurchaseOrder[] items)
  433. {
  434. Progress.Show("Working");
  435. Guid POID = items[0].ID;
  436. CoreTable table = new Client<PurchaseOrderItem>().Query(new Filter<PurchaseOrderItem>(x => x.PurchaseOrderLink.ID).IsEqualTo(POID),
  437. new Columns<PurchaseOrderItem>(x => x.ID, x => x.Product.ID, x => x.Qty, x => x.Dimensions.UnitSize, x => x.DueDate, x => x.Job.ID));
  438. if (table.Rows.Any())
  439. {
  440. var poItems = AddPOItems(table, new List<PurchaseOrderItem>());
  441. var requiItems = MatchRequiItems(poItems, new List<JobRequisitionItem>());
  442. if (requiItems.Count > 0)
  443. SaveAndRefreshScreen(requiItems);
  444. }
  445. Progress.Close();
  446. }
  447. private void SaveAndRefreshScreen(List<JobRequisitionItem> requiItems)
  448. {
  449. new Client<JobRequisitionItem>().Save(requiItems, "Updated on Create Purchase Order from Job Requi Dashboard");
  450. OnGridRefresh?.Invoke();
  451. }
  452. private List<PurchaseOrderItem> AddPOItems(CoreTable table, List<PurchaseOrderItem> poItems)
  453. {
  454. foreach (CoreRow row in table.Rows)
  455. {
  456. PurchaseOrderItem poItem = row.ToObject<PurchaseOrderItem>();
  457. poItems.Add(poItem);
  458. }
  459. return poItems;
  460. }
  461. private List<JobRequisitionItem> MatchRequiItems(List<PurchaseOrderItem> poItems, List<JobRequisitionItem> requiItems)
  462. {
  463. foreach (CoreRow row in SelectedRows)
  464. {
  465. JobRequisitionItem JobReqItem = row.ToObject<JobRequisitionItem>();
  466. foreach (var item in poItems)
  467. {
  468. if (string.IsNullOrWhiteSpace(JobReqItem.Dimensions.UnitSize))
  469. JobReqItem.Dimensions.UnitSize = QueryUnitSize(JobReqItem.Product.ID);
  470. if (string.IsNullOrWhiteSpace(item.Dimensions.UnitSize))
  471. item.Dimensions.UnitSize = QueryUnitSize(item.Product.ID);
  472. if (JobReqItem.Job.ID == Guid.Empty)
  473. JobReqItem.Job.ID = QueryJobID(JobReqItem.Requisition.ID);
  474. if (item.Job.ID == Guid.Empty)
  475. item.Job.ID = QueryJobID(JobReqItem.Requisition.ID);
  476. if (MatchReqItemToPOItem(JobReqItem, item))
  477. requiItems.Add(UpdateJobReqItemWithPODetails(JobReqItem, item));
  478. }
  479. }
  480. return requiItems;
  481. }
  482. private JobRequisitionItem UpdateJobReqItemWithPODetails(JobRequisitionItem JobReqItem, PurchaseOrderItem poItem)
  483. {
  484. JobReqItem.PurchaseOrderItem.ID = poItem.ID;
  485. JobReqItem.PurchaseOrderItem.DueDate = poItem.DueDate;
  486. if (JobReqItem.Status != JobRequisitionItemStatus.OnOrder)
  487. {
  488. JobReqItem.Notes = JobReqItem.Notes + Environment.NewLine + "Line marked as On Order by " + empName + " on " + DateTime.Now.ToString("dd MMM yy");
  489. JobReqItem.Ordered = poItem.Created;
  490. }
  491. return JobReqItem;
  492. }
  493. private bool MatchReqItemToPOItem(JobRequisitionItem JobReqItem, PurchaseOrderItem item)
  494. {
  495. if (JobReqItem.Product.ID == item.Product.ID &&
  496. JobReqItem.Dimensions.UnitSize == item.Dimensions.UnitSize &&
  497. JobReqItem.Job.ID == item.Job.ID)
  498. return true;
  499. else
  500. return false;
  501. }
  502. private string QueryUnitSize(Guid productID)
  503. {
  504. CoreTable table = new Client<Product>().Query(new Filter<Product>(x => x.ID).IsEqualTo(productID),
  505. new Columns<Product>(x => x.Dimensions.UnitSize));
  506. return table.Rows.FirstOrDefault().Get<string>("Dimensions.UnitSize");
  507. }
  508. private Guid QueryJobID(Guid iD)
  509. {
  510. CoreTable table = new Client<JobRequisition>().Query(new Filter<JobRequisition>(x => x.ID).IsEqualTo(iD),
  511. new Columns<JobRequisition>(x => x.Job.ID));
  512. return table.Rows.FirstOrDefault().Get<Guid>("Job.ID");
  513. }
  514. private CoreTable LoadPurchaseOrderItems(Type arg)
  515. {
  516. Progress.Show("Working");
  517. var result = new CoreTable();
  518. result.LoadColumns(typeof(PurchaseOrderItem));
  519. List<PurchaseOrderItem> items = new List<PurchaseOrderItem>();
  520. foreach (CoreRow row in SelectedRows)
  521. {
  522. JobRequisitionItem JobReqItem = row.ToObject<JobRequisitionItem>();
  523. PurchaseOrderItem POItem = new PurchaseOrderItem();
  524. POItem.Product.ID = JobReqItem.Product.ID;
  525. POItem.Product.Code = JobReqItem.Product.Code;
  526. POItem.Product.Name = JobReqItem.Product.Name;
  527. POItem.Description = JobReqItem.Product.Name;
  528. POItem.Qty = JobReqItem.Qty;
  529. POItem.Dimensions.CopyFrom(JobReqItem.Dimensions);
  530. POItem.Style.ID = JobReqItem.Style.ID;
  531. POItem.Style.Code = JobReqItem.Style.Code;
  532. POItem.Style.Description = JobReqItem.Style.Description;
  533. POItem.Job.ID = JobReqItem.Requisition.Job.ID;
  534. POItem.Dimensions.UnitSize = JobReqItem.Dimensions.UnitSize;
  535. items.Add(POItem);
  536. }
  537. result.LoadRows(items);
  538. Progress.Close();
  539. return result;
  540. }
  541. #endregion
  542. #region Utils
  543. private void SaveRow(CoreRow row, JobRequisitionItemStatus status, string note)
  544. {
  545. if (row == null)
  546. return;
  547. var id = row.Get<JobRequisitionItem, Guid>(c => c.ID);
  548. JobRequisitionItem item = Data.Rows.Where(r => r.Get<JobRequisitionItem, Guid>(c => c.ID).Equals(id)).FirstOrDefault().ToObject<JobRequisitionItem>();
  549. item.Status = status;
  550. item.Notes = item.Notes + Environment.NewLine + note;
  551. new Client<JobRequisitionItem>().Save(item, "Updated From Job Requisition Review Dashboard");
  552. OnGridRefresh?.Invoke();
  553. }
  554. private void SaveItem(JobRequisitionItem item, JobRequisitionItemStatus status, string note)
  555. {
  556. item.Status = status;
  557. item.Notes = item.Notes + Environment.NewLine + note;
  558. new Client<JobRequisitionItem>().Save(item, "Updated From Job Requisition Review Dashboard");
  559. OnGridRefresh?.Invoke();
  560. }
  561. private void MultiSaveRows(CoreRow[] rows, JobRequisitionItemStatus status, string note)
  562. {
  563. List<JobRequisitionItem> items = new List<JobRequisitionItem>();
  564. foreach (CoreRow row in rows)
  565. {
  566. var id = row.Get<JobRequisitionItem, Guid>(c => c.ID);
  567. JobRequisitionItem item = Data.Rows.Where(r => r.Get<JobRequisitionItem, Guid>(c => c.ID).Equals(id)).FirstOrDefault().ToObject<JobRequisitionItem>();
  568. item.Status = status;
  569. item.Notes = item.Notes + Environment.NewLine + note;
  570. items.Add(item);
  571. }
  572. new Client<JobRequisitionItem>().Save(items, "Updated From Job Requisition Review Dashboard");
  573. OnGridRefresh?.Invoke();
  574. }
  575. protected override void Reload(Filters<JobRequisitionItem> criteria, Columns<JobRequisitionItem> columns, ref SortOrder<JobRequisitionItem> sort,
  576. Action<CoreTable, Exception> action)
  577. {
  578. criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.Approved).IsNotEqualTo(DateTime.MinValue));
  579. if (!bViewCancelled)
  580. criteria.Add(new Filter<JobRequisitionItem>(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Cancelled));
  581. if (!bIncludeArchived)
  582. criteria.Add(new Filter<JobRequisitionItem>(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Archived));
  583. sort = new SortOrder<JobRequisitionItem>(x => x.Requisition.Number, SortDirection.Descending);
  584. base.Reload(criteria, columns, ref sort, action);
  585. }
  586. private void BuildMenu(DynamicMenuColumn column, CoreRow row)
  587. {
  588. // column.AddItem("Treatment Required", PRSDesktop.Resources.palette, TreatmentRequired_Clicked);
  589. column.AddItem("Order Required", PRSDesktop.Resources.purchase, OrderRequired_Clicked);
  590. //column.AddItem("Mark as Not Checked", PRSDesktop.Resources.disabled, Uncheck_Clicked);
  591. column.AddItem("Split Line", PRSDesktop.Resources.split, SplitLine_Clicked);
  592. column.AddItem("Archive", PRSDesktop.Resources.archive, Archive_Clicked);
  593. }
  594. #endregion
  595. }
  596. public class JobRequiReviewDashboardFilterItem
  597. {
  598. public Guid SupplierID { get; set; }
  599. public Guid ProductID { get; set; }
  600. public string Text { get; set; }
  601. public JobRequiReviewDashboardFilterItem()
  602. {
  603. SupplierID = Guid.Empty;
  604. ProductID = Guid.Empty;
  605. Text = "";
  606. }
  607. }
  608. }