JobRequisitionReviewDashboard.xaml.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. using Comal.Classes;
  2. using InABox.Core;
  3. using InABox.DynamicGrid;
  4. using InABox.WPF;
  5. using PRSDesktop.WidgetGroups;
  6. using InABox.Clients;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Windows;
  11. using System.Windows.Controls;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Media;
  14. using InABox.Configuration;
  15. namespace PRSDesktop
  16. {
  17. public class JobRequisitionReviewDashboardProperties : IUserConfigurationSettings, IDashboardProperties { }
  18. public class JobRequisitionReviewDashboardElement : DashboardElement<JobRequisitionReviewDashboard, Projects, JobRequisitionReviewDashboardProperties> { }
  19. /// <summary>
  20. /// Interaction logic for JobRequisitionReviewDashboard.xaml
  21. /// </summary>
  22. ///
  23. //Job Requi Review Dashboard works with JobRequisitionReviewGrid (for viewing data), and also allows:
  24. // 1. Changing the status of a Job Requi Item line via an action column with context menu.
  25. // Of note is "Reserving" stock - using the JobRequisitionReserveWindow, which works with the JobRequisitionItemStockHoldingReserverGrid
  26. // 2. Create a purchase order from a selection of one or more lines using the added button. If the PO process is cancelled, the PO and items created are cleaned up
  27. // 3. Splitting Job Requi Item lines
  28. public partial class JobRequisitionReviewDashboard : UserControl, IDashboardWidget<Projects, JobRequisitionReviewDashboardProperties>
  29. {
  30. public List<JobRequiReviewDashboardFilterItem> filterItems = new List<JobRequiReviewDashboardFilterItem>();
  31. public JobRequisitionReviewDashboardProperties Properties { get; set; }
  32. public event LoadSettings<JobRequisitionReviewDashboardProperties>? LoadSettings;
  33. public event SaveSettings<JobRequisitionReviewDashboardProperties>? SaveSettings;
  34. public JobRequisitionReviewDashboard()
  35. {
  36. InitializeComponent();
  37. Grid.Refresh(true, true);
  38. LoadFilters();
  39. }
  40. public void Refresh()
  41. {
  42. }
  43. public void Setup()
  44. {
  45. }
  46. public void Shutdown()
  47. {
  48. }
  49. private void Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
  50. {
  51. var item = filterComboBox.SelectedItem as JobRequiReviewDashboardFilterItem;
  52. Grid.RefreshOnFilterChanged(item.SupplierID);
  53. }
  54. private void LoadFilters()
  55. {
  56. List<Guid> productIDs = new List<Guid>();
  57. CoreTable productsTable = new Client<JobRequisitionItem>().Query(new Filter<JobRequisitionItem>(x => x.Product).LinkValid(),
  58. new Columns<JobRequisitionItem>(x => x.Product.ID));
  59. foreach (CoreRow row1 in productsTable.Rows)
  60. {
  61. productIDs.Add(Guid.Parse(row1.Values[0].ToString()));
  62. }
  63. CoreTable table = new Client<SupplierProduct>().Query(
  64. new Filter<SupplierProduct>(x => x.Product).LinkValid()
  65. .And(x => x.SupplierLink).LinkValid(),
  66. new Columns<SupplierProduct>(x => x.SupplierLink.ID, x => x.Product.ID, x => x.SupplierLink.Name, x => x.SupplierLink.Code));
  67. if (table.Rows.Any())
  68. {
  69. JobRequiReviewDashboardFilterItem firstItem = new JobRequiReviewDashboardFilterItem
  70. {
  71. Text = "No Filter"
  72. };
  73. filterItems.Add(firstItem);
  74. foreach (CoreRow row in table.Rows)
  75. {
  76. JobRequiReviewDashboardFilterItem filterItem = new JobRequiReviewDashboardFilterItem
  77. {
  78. SupplierID = Guid.Parse(row.Values[0].ToString()),
  79. ProductID = Guid.Parse(row.Values[1].ToString()),
  80. };
  81. if (row.Values[3] != null)
  82. {
  83. filterItem.Text = row.Values[3].ToString();
  84. if (row.Values[2] != null)
  85. {
  86. filterItem.Text = filterItem.Text + " " + row.Values[2].ToString();
  87. }
  88. }
  89. var founditem = filterItems.Find(x => x.SupplierID == filterItem.SupplierID);
  90. if (founditem == null)
  91. {
  92. if (productIDs.Contains(filterItem.ProductID))
  93. filterItems.Add(filterItem);
  94. }
  95. }
  96. }
  97. filterComboBox.ItemsSource = filterItems;
  98. }
  99. }
  100. public class JobRequisitionReviewGrid : DynamicDataGrid<JobRequisitionItem>
  101. {
  102. List<Guid> filterProductIDs = new List<Guid>();
  103. Guid empID = new Guid();
  104. string empName = "";
  105. bool bIncludeArchived = false;
  106. bool bViewCancelled = false;
  107. public JobRequisitionReviewGrid()
  108. {
  109. Options.AddRange(
  110. DynamicGridOption.FilterRows,
  111. DynamicGridOption.SelectColumns,
  112. DynamicGridOption.RecordCount,
  113. DynamicGridOption.MultiSelect
  114. );
  115. HiddenColumns.Add(x => x.ID);
  116. HiddenColumns.Add(x => x.Product.ID);
  117. HiddenColumns.Add(x => x.Product.Code);
  118. HiddenColumns.Add(x => x.Product.Group.ID);
  119. HiddenColumns.Add(x => x.Product.Group.Code);
  120. HiddenColumns.Add(x => x.Product.Group.Description);
  121. HiddenColumns.Add(x => x.Style.ID);
  122. HiddenColumns.Add(x => x.Style.Code);
  123. HiddenColumns.Add(x => x.Style.Description);
  124. HiddenColumns.Add(x => x.Requisition.ID);
  125. HiddenColumns.Add(x => x.Requisition.Job.ID);
  126. HiddenColumns.Add(x => x.Requisition.Job.JobNumber);
  127. HiddenColumns.Add(x => x.Requisition.Job.Name);
  128. HiddenColumns.Add(x => x.Requisition.Number);
  129. HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.ID);
  130. HiddenColumns.Add(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber);
  131. HiddenColumns.Add(x => x.PurchaseOrderItem.DueDate);
  132. HiddenColumns.Add(x => x.Job.ID);
  133. HiddenColumns.Add(x => x.Dimensions.UnitSize);
  134. HiddenColumns.Add(x => x.Dimensions.Length);
  135. HiddenColumns.Add(x => x.Dimensions.Width);
  136. HiddenColumns.Add(x => x.Dimensions.Height);
  137. HiddenColumns.Add(x => x.Dimensions.Weight);
  138. HiddenColumns.Add(x => x.Dimensions.Quantity);
  139. HiddenColumns.Add(x => x.Dimensions.Value);
  140. HiddenColumns.Add(x => x.Dimensions.Unit.ID);
  141. HiddenColumns.Add(x => x.Dimensions.Unit.HasLength);
  142. HiddenColumns.Add(x => x.Dimensions.Unit.HasHeight);
  143. HiddenColumns.Add(x => x.Dimensions.Unit.HasWidth);
  144. HiddenColumns.Add(x => x.Dimensions.Unit.HasWeight);
  145. HiddenColumns.Add(x => x.Dimensions.Unit.HasQuantity);
  146. HiddenColumns.Add(x => x.Dimensions.Unit.Formula);
  147. HiddenColumns.Add(x => x.Dimensions.Unit.Format);
  148. HiddenColumns.Add(x => x.Dimensions.Unit.Code);
  149. HiddenColumns.Add(x => x.Dimensions.Unit.Description);
  150. if (Security.CanEdit<JobRequisitionItem>())
  151. ActionColumns.Add(new DynamicMenuColumn(BuildMenu, EmptyReturnFunction));
  152. if (Security.CanEdit<PurchaseOrder>())
  153. AddButton("Create Purchase Order", null, CreatePurchaseOrder);
  154. if (Security.CanEdit<PurchaseOrder>())
  155. AddButton("Create Treatment PO", null, CreateTreatmentPO);
  156. AddButton("Include Archived", null, ViewArchived);
  157. AddButton("Include Cancelled", null, ViewCancelled);
  158. ActionColumns.Add(new DynamicImageColumn(PRSDesktop.Resources.rack.AsBitmapImage(), null) { ToolTip = ShowStockToolTip });
  159. ColumnsTag = "JobRequisitionReview";
  160. 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));
  161. if (table.Rows.Any())
  162. {
  163. empID = Guid.Parse(table.Rows.FirstOrDefault().Values[0].ToString());
  164. empName = table.Rows.FirstOrDefault().Values[1].ToString();
  165. }
  166. }
  167. private bool ViewCancelled(Button button, CoreRow[] rows)
  168. {
  169. if (bViewCancelled)
  170. {
  171. bViewCancelled = false;
  172. button.Content = "Includ Cancelled";
  173. }
  174. else
  175. {
  176. bViewCancelled = true;
  177. button.Content = "Exclude Cancelled";
  178. }
  179. Dispatcher.BeginInvoke(() =>
  180. {
  181. Refresh(true, true);
  182. });
  183. return true;
  184. }
  185. private bool ViewArchived(Button button, CoreRow[] rows)
  186. {
  187. if (bIncludeArchived)
  188. {
  189. bIncludeArchived = false;
  190. button.Content = "Include Archived";
  191. }
  192. else
  193. {
  194. bIncludeArchived = true;
  195. button.Content = "Exclude Archived";
  196. }
  197. Dispatcher.BeginInvoke(() =>
  198. {
  199. Refresh(true, true);
  200. });
  201. return true;
  202. }
  203. private FrameworkElement ShowStockToolTip(DynamicActionColumn arg1, CoreRow row)
  204. {
  205. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  206. var holdings = new StockHoldingToolTipGrid(item.Product.ID, item.Job.ID, item.ID, item.Requisition.Number.ToString());
  207. holdings.Refresh(true, true);
  208. Frame frame = new Frame();
  209. frame.Background = new SolidColorBrush(Colors.LightYellow);
  210. frame.Padding = new Thickness(10);
  211. frame.BorderBrush = new SolidColorBrush(Colors.DarkGray);
  212. frame.BorderThickness = new Thickness(1);
  213. frame.Content = holdings;
  214. return frame;
  215. }
  216. private bool CreateTreatmentPO(Button button, CoreRow[] rows)
  217. {
  218. return true;
  219. }
  220. protected override void GenerateColumns(DynamicGridColumns columns)
  221. {
  222. columns.Add<JobRequisitionItem, DateTime>(x => x.Created, 80, "Date", "", Alignment.MiddleLeft);
  223. columns.Add<JobRequisitionItem, string>(x => x.Requisition.Job.JobNumber, 70, "Job", "", Alignment.MiddleLeft);
  224. columns.Add<JobRequisitionItem, int>(x => x.Requisition.Number, 50, "NO.", "", Alignment.MiddleLeft);
  225. columns.Add<JobRequisitionItem, string>(x => x.Product.Code, 70, "Code", "", Alignment.MiddleLeft);
  226. columns.Add<JobRequisitionItem, string>(x => x.Product.Name, 200, "Product Name", "", Alignment.MiddleLeft);
  227. columns.Add<JobRequisitionItem, string>(x => x.Style.Description, 150, "Style", "", Alignment.MiddleLeft);
  228. columns.Add<JobRequisitionItem, double>(x => x.Qty, 50, "Qty", "", Alignment.MiddleLeft);
  229. columns.Add<JobRequisitionItem, string>(x => x.Dimensions.UnitSize, 50, "Size", "", Alignment.MiddleLeft);
  230. columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PurchaseOrderLink.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
  231. columns.Add<JobRequisitionItem, string>(x => x.PurchaseOrderItem.PONumber, 80, "PO Number", "", Alignment.MiddleLeft);
  232. columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.DueDate, 80, "Due", "", Alignment.MiddleLeft);
  233. columns.Add<JobRequisitionItem, DateTime>(x => x.PurchaseOrderItem.ReceivedDate, 80, "Received", "", Alignment.MiddleLeft);
  234. columns.Add<JobRequisitionItem, JobRequisitionItemStatus>(x => x.Status, 80, "Status", "", Alignment.MiddleLeft);
  235. columns.Add<JobRequisitionItem, string>(x => x.Notes, 300, "Notes", "", Alignment.MiddleLeft);
  236. }
  237. private DynamicMenuStatus EmptyReturnFunction(CoreRow row)
  238. {
  239. return DynamicMenuStatus.Enabled;
  240. }
  241. #region Action Column Buttons
  242. private bool CheckValidAction(JobRequisitionItem item, bool bypassReserved)
  243. {
  244. bool valid = true;
  245. if (item.Status == JobRequisitionItemStatus.Reserved && !bypassReserved)
  246. {
  247. MessageBox.Show("Error. Item has already been reserved!");
  248. return false;
  249. }
  250. else if (item.Status == JobRequisitionItemStatus.OnOrder)
  251. {
  252. MessageBox.Show("Error. Item is already on order!");
  253. return false;
  254. }
  255. if (item.Status == JobRequisitionItemStatus.Received)
  256. {
  257. MessageBox.Show("Error. Item has already been recieved!");
  258. return false;
  259. }
  260. return valid;
  261. }
  262. private void Reserve_Clicked(CoreRow row)
  263. {
  264. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  265. CoreTable table = new Client<StockHolding>().Query
  266. (
  267. new Filter<StockHolding>(x => x.Product.ID).IsEqualTo(item.Product.ID)
  268. .And(x => x.Job).NotLinkValid(),
  269. new Columns<StockHolding>(x => x.Units)
  270. );
  271. if (table.Rows.Count == 0)
  272. {
  273. MessageBox.Show("No free stock found for this product.");
  274. return;
  275. }
  276. double units = 0.0;
  277. foreach (CoreRow corerow in table.Rows)
  278. {
  279. List<Object> list = corerow.Values;
  280. if (list[0] == null) list[0] = 0;
  281. double holdingUnits = double.Parse(list[0].ToString());
  282. units = units + holdingUnits;
  283. }
  284. if (item.Qty > units)
  285. {
  286. var result = MessageBox.Show("Current free stock for this product is " + units + ". Amount required for this requisition line is " + item.Qty +
  287. ". Do you want to split this requisition line?", "Alert", MessageBoxButton.YesNo);
  288. switch (result)
  289. {
  290. case MessageBoxResult.Yes:
  291. SplitLine(item, units, item.Qty - units, "line split due to insufficient stock holdings");
  292. return;
  293. case MessageBoxResult.No:
  294. break;
  295. default:
  296. return;
  297. }
  298. }
  299. Dispatcher.BeginInvoke(() =>
  300. {
  301. JobRequisitionReserveWindow window = new JobRequisitionReserveWindow();
  302. JobRequisitionItemStockHoldingReserverGrid holdings = new JobRequisitionItemStockHoldingReserverGrid
  303. (
  304. item.Product.ID, item.Requisition.Job.ID, item.ID, item.Requisition.Job.JobNumber + " (" + item.Requisition.Number + ")"
  305. );
  306. holdings.Refresh(true, true);
  307. window.grid.Children.Add(holdings);
  308. window.SizeToContent = SizeToContent.WidthAndHeight;
  309. window.ShowDialog();
  310. if (holdings.StockReserved || window.StockReserved)
  311. SaveRow(row, JobRequisitionItemStatus.Reserved, "Line marked reserved by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  312. });
  313. }
  314. private void SplitLine(JobRequisitionItem item, double oldItemQty, double newItemQty, string notes)
  315. {
  316. List<JobRequisitionItem> items = new List<JobRequisitionItem>();
  317. JobRequisitionItem newItem = new JobRequisitionItem();
  318. newItem.Requisition.ID = item.Requisition.ID;
  319. newItem.Requisition.Job.ID = item.Requisition.Job.ID;
  320. newItem.Requisition.Job.JobNumber = item.Requisition.Job.JobNumber;
  321. newItem.Requisition.Job.Name = item.Requisition.Job.Name;
  322. newItem.Product.ID = item.Product.ID;
  323. newItem.Product.Name = item.Product.Name;
  324. newItem.Product.Code = item.Product.Code;
  325. newItem.Product.Group.ID = item.Product.Group.ID;
  326. newItem.Product.Group.Description = item.Product.Group.Description;
  327. newItem.Dimensions.CopyFrom(item.Dimensions);
  328. newItem.Style.ID = item.Style.ID;
  329. newItem.Style.Description = item.Style.Description;
  330. newItem.Style.Code = item.Style.Code;
  331. newItem.Notes = item.Notes + Environment.NewLine + notes;
  332. item.Notes = newItem.Notes;
  333. item.Qty = oldItemQty;
  334. newItem.Qty = newItemQty;
  335. items.Add(newItem);
  336. items.Add(item);
  337. new Client<JobRequisitionItem>().Save(items, "Split lines from Job Requi Item Review Dashboard");
  338. MessageBox.Show("Line split - original line Qty is now " + item.Qty + ". New line Qty is " + newItem.Qty, "Success");
  339. Dispatcher.BeginInvoke(() =>
  340. {
  341. Refresh(true, true);
  342. });
  343. }
  344. private void SplitLine_Clicked(CoreRow row)
  345. {
  346. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  347. if (CheckValidAction(item, false))
  348. {
  349. int units = Convert.ToInt32(item.Qty);
  350. if (NumberEdit.Execute("Enter amount to split", 1, units, ref units))
  351. {
  352. SplitLine(item, item.Qty - units, units, "Line split");
  353. }
  354. }
  355. }
  356. private void Archive_Clicked(CoreRow row)
  357. {
  358. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  359. SaveRow(row, JobRequisitionItemStatus.Archived, "Line marked as Archived by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  360. }
  361. private void OrderRequired_Clicked(CoreRow row)
  362. {
  363. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  364. if (CheckValidAction(item, false))
  365. SaveRow(row, JobRequisitionItemStatus.OrderRequired, "Line marked as Order Required by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  366. }
  367. private void TreatmentRequired_Clicked(CoreRow row)
  368. {
  369. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  370. if (item.Status != JobRequisitionItemStatus.Reserved)
  371. {
  372. MessageBox.Show("Stock must first be reserved for this item");
  373. return;
  374. }
  375. SaveRow(row, JobRequisitionItemStatus.TreatmentRequired, "Line marked as Treatment Required by " + empName + " on " + DateTime.Now.ToString("dd MMM yy"));
  376. }
  377. private void Uncheck_Clicked(CoreRow row)
  378. {
  379. string extraMessage = "";
  380. JobRequisitionItem item = row.ToObject<JobRequisitionItem>();
  381. if (!CheckValidAction(item, true))
  382. return;
  383. CoreTable table = new Client<StockMovement>().Query
  384. (
  385. new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsEqualTo(item.ID),
  386. new Columns<StockMovement>(x => x.ID)
  387. );
  388. if (table.Rows.Any())
  389. {
  390. var result = MessageBox.Show("This will reverse stock movements already created for this Requisition Item. Proceed?", "Alert", MessageBoxButton.YesNo);
  391. switch (result)
  392. {
  393. case MessageBoxResult.Yes:
  394. break;
  395. case MessageBoxResult.No:
  396. return;
  397. default:
  398. return;
  399. }
  400. List<StockMovement> movements = new List<StockMovement>();
  401. foreach (CoreRow stockmovementRow in table.Rows)
  402. {
  403. StockMovement movement = new StockMovement();
  404. movement.ID = Guid.Parse(stockmovementRow.Values[0].ToString());
  405. movements.Add(movement);
  406. }
  407. new Client<StockMovement>().Delete(movements, "Stock movements reversed from Job Requisition Item Review Dashboard");
  408. extraMessage = " and Stock Movements Reversed ";
  409. }
  410. SaveRow(row, JobRequisitionItemStatus.NotChecked, "Line marked as Not Checked by " + empName + extraMessage + " on " + DateTime.Now.ToString("dd MMM yy"));
  411. }
  412. private bool CreatePurchaseOrder(Button btn, CoreRow[] rows)
  413. {
  414. if (!rows.Any())
  415. {
  416. MessageBox.Show("Please select at least one row to add to Purchase Order!");
  417. return false;
  418. }
  419. PurchaseOrder purchaseOrder = new PurchaseOrder();
  420. purchaseOrder.Notes = "Created from Job Requi Item Review Screen" + System.Environment.NewLine;
  421. purchaseOrder.RaisedBy.ID = empID;
  422. var page = new SupplierPurchaseOrders();
  423. page.OnAfterSave += (form, items) =>
  424. {
  425. PurchaseOrderOnSave(form, items.Cast<PurchaseOrder>().ToArray());
  426. };
  427. return page.EditItems(new[] { purchaseOrder }, LoadPurchaseOrderItems, true);
  428. }
  429. private void PurchaseOrderOnSave(IDynamicEditorForm form, PurchaseOrder[] items)
  430. {
  431. Progress.Show("Working");
  432. Guid POID = items[0].ID;
  433. CoreTable table = new Client<PurchaseOrderItem>().Query(new Filter<PurchaseOrderItem>(x => x.PurchaseOrderLink.ID).IsEqualTo(POID),
  434. new Columns<PurchaseOrderItem>(x => x.ID, x => x.Product.ID, x => x.Qty, x => x.Dimensions.UnitSize, x => x.DueDate, x => x.Job.ID));
  435. if (table.Rows.Any())
  436. {
  437. var poItems = AddPOItems(table, new List<PurchaseOrderItem>());
  438. var requiItems = MatchRequiItems(poItems, new List<JobRequisitionItem>());
  439. if (requiItems.Count > 0)
  440. SaveAndRefreshScreen(requiItems);
  441. }
  442. Progress.Close();
  443. }
  444. private void SaveAndRefreshScreen(List<JobRequisitionItem> requiItems)
  445. {
  446. new Client<JobRequisitionItem>().Save(requiItems, "Updated on Create Purchase Order from Job Requi Dashboard");
  447. Dispatcher.BeginInvoke(() =>
  448. {
  449. Refresh(false, true);
  450. });
  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 item)
  483. {
  484. JobReqItem.PurchaseOrderItem.ID = item.ID;
  485. JobReqItem.PurchaseOrderItem.DueDate = item.DueDate;
  486. JobReqItem.Status = JobRequisitionItemStatus.OnOrder;
  487. JobReqItem.Notes = JobReqItem.Notes + Environment.NewLine + "Line marked as On Order by " + empName + " on " + DateTime.Now.ToString("dd MMM yy");
  488. return JobReqItem;
  489. }
  490. private bool MatchReqItemToPOItem(JobRequisitionItem JobReqItem, PurchaseOrderItem item)
  491. {
  492. if (JobReqItem.Product.ID == item.Product.ID &&
  493. JobReqItem.Dimensions.UnitSize == item.Dimensions.UnitSize &&
  494. JobReqItem.Job.ID == item.Job.ID)
  495. return true;
  496. else
  497. return false;
  498. }
  499. private string QueryUnitSize(Guid productID)
  500. {
  501. CoreTable table = new Client<Product>().Query(new Filter<Product>(x => x.ID).IsEqualTo(productID),
  502. new Columns<Product>(x => x.Dimensions.UnitSize));
  503. return table.Rows.FirstOrDefault().Get<string>("Dimensions.UnitSize");
  504. }
  505. private Guid QueryJobID(Guid iD)
  506. {
  507. CoreTable table = new Client<JobRequisition>().Query(new Filter<JobRequisition>(x => x.ID).IsEqualTo(iD),
  508. new Columns<JobRequisition>(x => x.Job.ID));
  509. return table.Rows.FirstOrDefault().Get<Guid>("Job.ID");
  510. }
  511. private CoreTable LoadPurchaseOrderItems(Type arg)
  512. {
  513. Progress.Show("Working");
  514. var result = new CoreTable();
  515. result.LoadColumns(typeof(PurchaseOrderItem));
  516. List<PurchaseOrderItem> items = new List<PurchaseOrderItem>();
  517. foreach (CoreRow row in SelectedRows)
  518. {
  519. JobRequisitionItem JobReqItem = row.ToObject<JobRequisitionItem>();
  520. PurchaseOrderItem POItem = new PurchaseOrderItem();
  521. POItem.Product.ID = JobReqItem.Product.ID;
  522. POItem.Product.Code = JobReqItem.Product.Code;
  523. POItem.Product.Name = JobReqItem.Product.Name;
  524. POItem.Description = JobReqItem.Product.Name;
  525. POItem.Qty = JobReqItem.Qty;
  526. POItem.Dimensions.CopyFrom(JobReqItem.Dimensions);
  527. POItem.Style.ID = JobReqItem.Style.ID;
  528. POItem.Style.Code = JobReqItem.Style.Code;
  529. POItem.Style.Description = JobReqItem.Style.Description;
  530. POItem.Job.ID = JobReqItem.Requisition.Job.ID;
  531. POItem.Dimensions.UnitSize = JobReqItem.Dimensions.UnitSize;
  532. items.Add(POItem);
  533. }
  534. result.LoadRows(items);
  535. Progress.Close();
  536. return result;
  537. }
  538. #endregion
  539. #region Utils
  540. private void SaveRow(CoreRow row, JobRequisitionItemStatus status, string note)
  541. {
  542. if (row == null)
  543. return;
  544. var id = row.Get<JobRequisitionItem, Guid>(c => c.ID);
  545. JobRequisitionItem item = Data.Rows.Where(r => r.Get<JobRequisitionItem, Guid>(c => c.ID).Equals(id)).FirstOrDefault().ToObject<JobRequisitionItem>();
  546. item.Status = status;
  547. item.Notes = item.Notes + Environment.NewLine + note;
  548. new Client<JobRequisitionItem>().Save(item, "Updated From Job Requisition Review Dashboard");
  549. Dispatcher.BeginInvoke(() =>
  550. {
  551. Refresh(true, true);
  552. });
  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. Dispatcher.BeginInvoke(() =>
  560. {
  561. Refresh(true, true);
  562. });
  563. }
  564. private void MultiSaveRows(CoreRow[] rows, JobRequisitionItemStatus status, string note)
  565. {
  566. List<JobRequisitionItem> items = new List<JobRequisitionItem>();
  567. foreach (CoreRow row in rows)
  568. {
  569. var id = row.Get<JobRequisitionItem, Guid>(c => c.ID);
  570. JobRequisitionItem item = Data.Rows.Where(r => r.Get<JobRequisitionItem, Guid>(c => c.ID).Equals(id)).FirstOrDefault().ToObject<JobRequisitionItem>();
  571. item.Status = status;
  572. item.Notes = item.Notes + Environment.NewLine + note;
  573. items.Add(item);
  574. }
  575. new Client<JobRequisitionItem>().Save(items, "Updated From Job Requisition Review Dashboard");
  576. Dispatcher.BeginInvoke(() =>
  577. {
  578. Refresh(true, true);
  579. });
  580. }
  581. protected override void Reload(Filters<JobRequisitionItem> criteria, Columns<JobRequisitionItem> columns, ref SortOrder<JobRequisitionItem> sort,
  582. Action<CoreTable, Exception> action)
  583. {
  584. criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.Approved).IsNotEqualTo(DateTime.MinValue));
  585. if (!bViewCancelled)
  586. criteria.Add(new Filter<JobRequisitionItem>(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Cancelled));
  587. if (!bIncludeArchived)
  588. criteria.Add(new Filter<JobRequisitionItem>(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Archived));
  589. if (filterProductIDs.Count > 0)
  590. {
  591. Filter<JobRequisitionItem> filter = new Filter<JobRequisitionItem>(x => x.Product.ID).IsEqualTo(filterProductIDs.FirstOrDefault());
  592. foreach (Guid id in filterProductIDs)
  593. {
  594. if (id != filterProductIDs[0])
  595. filter = filter.Or(x => x.Product.ID).IsEqualTo(id);
  596. }
  597. criteria.Add(filter);
  598. }
  599. sort = new SortOrder<JobRequisitionItem>(x => x.Requisition.Number, SortDirection.Descending);
  600. base.Reload(criteria, columns, ref sort, action);
  601. }
  602. public void RefreshOnFilterChanged(Guid id)
  603. {
  604. filterProductIDs.Clear();
  605. if (id != Guid.Empty)
  606. {
  607. CoreTable table = new Client<SupplierProduct>().Query(
  608. new Filter<SupplierProduct>(x => x.SupplierLink.ID).IsEqualTo(id)
  609. .And(x => x.Product).LinkValid(),
  610. new Columns<SupplierProduct>(x => x.Product.ID));
  611. if (table.Rows.Any())
  612. {
  613. foreach (CoreRow row in table.Rows)
  614. {
  615. filterProductIDs.Add(Guid.Parse(row.Values[0].ToString()));
  616. }
  617. }
  618. }
  619. Dispatcher.BeginInvoke(() =>
  620. {
  621. Refresh(true, true);
  622. });
  623. }
  624. private void BuildMenu(DynamicMenuColumn column, CoreRow row)
  625. {
  626. column.AddItem("Reserve", PRSDesktop.Resources.project, Reserve_Clicked);
  627. column.AddItem("Treatment Required", PRSDesktop.Resources.palette, TreatmentRequired_Clicked);
  628. column.AddItem("Order Required", PRSDesktop.Resources.purchase, OrderRequired_Clicked);
  629. column.AddItem("Mark as Not Checked", PRSDesktop.Resources.disabled, Uncheck_Clicked);
  630. column.AddItem("Split Line", PRSDesktop.Resources.split, SplitLine_Clicked);
  631. column.AddItem("Archive", PRSDesktop.Resources.archive, Archive_Clicked);
  632. }
  633. #endregion
  634. }
  635. public class JobRequiReviewDashboardFilterItem
  636. {
  637. public Guid SupplierID { get; set; }
  638. public Guid ProductID { get; set; }
  639. public string Text { get; set; }
  640. public JobRequiReviewDashboardFilterItem()
  641. {
  642. SupplierID = Guid.Empty;
  643. ProductID = Guid.Empty;
  644. Text = "";
  645. }
  646. }
  647. }