JobSummaryGrid.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Media;
  9. using Comal.Classes;
  10. using InABox.Clients;
  11. using InABox.Core;
  12. using InABox.DynamicGrid;
  13. using InABox.WPF;
  14. namespace PRSDesktop
  15. {
  16. internal class JobSummaryGrid : DynamicDataGrid<JobMaterial>, IJobControl, IDataModelSource
  17. {
  18. Guid empID = Guid.Empty;
  19. string empName = "";
  20. private bool _stylecolumnVisible;
  21. public bool IncludeReserves { get; set; }
  22. public Job Job { get; set; }
  23. public JobPanelSettings Settings { get; set; }
  24. public JobSummaryGrid() : base()
  25. {
  26. ColumnsTag = nameof(JobSummaryGrid);
  27. OnCellDoubleClick += JobSummaryGrid_OnCellDoubleClick;
  28. }
  29. protected override void Init()
  30. {
  31. base.Init();
  32. HiddenColumns.Add(x => x.Product.ID);
  33. HiddenColumns.Add(x => x.Style.ID);
  34. HiddenColumns.Add(x => x.Dimensions.UnitSize);
  35. HiddenColumns.Add(x => x.BillOfMaterials);
  36. HiddenColumns.Add(x => x.Requisitions);
  37. HiddenColumns.Add(x => x.PickingLists);
  38. HiddenColumns.Add(x => x.Issued);
  39. HiddenColumns.Add(x => x.ReservedStock);
  40. HiddenColumns.Add(x => x.OnOrder);
  41. HiddenColumns.Add(x => x.JobShortage);
  42. HiddenColumns.Add(x => x.FreeOnHand);
  43. HiddenColumns.Add(x => x.FreeOnOrder);
  44. HiddenColumns.Add(x => x.FreeStockTotal);
  45. HiddenColumns.Add(x => x.FreeStockShortage);
  46. HiddenColumns.Add(x => x.Product.Image.ID);
  47. HiddenColumns.Add(x => x.Product.Image.FileName);
  48. ActionColumns.Add(new DynamicImageManagerColumn<JobMaterial>(this, x => x.Product.Image, false)
  49. { Position = DynamicActionColumnPosition.Start });
  50. AddButton("Create PO", null, CreatePO);
  51. }
  52. protected override void DoReconfigure(FluentList<DynamicGridOption> options)
  53. {
  54. base.DoReconfigure(options);
  55. options.AddRange(
  56. DynamicGridOption.RecordCount,
  57. DynamicGridOption.SelectColumns,
  58. DynamicGridOption.FilterRows,
  59. DynamicGridOption.ExportData,
  60. DynamicGridOption.MultiSelect
  61. );
  62. }
  63. protected override void GenerateColumns(DynamicGridColumns columns)
  64. {
  65. columns.Add<JobMaterial, string>(x => x.Product.Group.Code, 120, "Group Code", "", Alignment.MiddleCenter);
  66. columns.Add<JobMaterial, string>(x => x.Product.Code, 200, "Product Code", "", Alignment.MiddleCenter);
  67. columns.Add<JobMaterial, string>(x => x.Product.Name, 0, "Product Name", "", Alignment.MiddleCenter);
  68. columns.Add<JobMaterial, string>(x => x.Dimensions.UnitSize, 120, "UOM", "", Alignment.MiddleCenter);
  69. columns.Add<JobMaterial, double>(x => x.BillOfMaterials, 80, "BOM", "", Alignment.MiddleCenter);
  70. columns.Add<JobMaterial, double>(x => x.Requisitions, 80, "Req.", "", Alignment.MiddleCenter);
  71. columns.Add<JobMaterial, double>(x => x.PickingLists, 80, "P/L", "", Alignment.MiddleCenter);
  72. columns.Add<JobMaterial, double>(x => x.Issued, 80, "Issued", "", Alignment.MiddleCenter);
  73. columns.Add<JobMaterial, double>(x => x.ReservedStock, 80, "Reserved", "", Alignment.MiddleCenter);
  74. columns.Add<JobMaterial, double>(x => x.OnOrder, 80, "Ordered", "", Alignment.MiddleCenter);
  75. columns.Add<JobMaterial, double>(x => x.JobShortage, 80, "Job Short", "", Alignment.MiddleCenter);
  76. columns.Add<JobMaterial, double>(x => x.FreeStockTotal, 80, "Free Stock", "", Alignment.MiddleCenter);
  77. columns.Add<JobMaterial, double>(x => x.FreeStockShortage, 80, "Stk Short", "", Alignment.MiddleCenter);
  78. }
  79. private void ShowDetailGrid<TEntity>(
  80. String columnname,
  81. Expression<Func<TEntity,object?>> productcol,
  82. Guid productid,
  83. Expression<Func<TEntity,object?>> stylecol,
  84. Guid? styleid,
  85. Expression<Func<TEntity,object?>> unitcol,
  86. String unitsize,
  87. Expression<Func<TEntity,object?>>? jobcol,
  88. Filter<TEntity>? extrafilter,
  89. Func<CoreRow,bool>? rowfilter
  90. )
  91. {
  92. var grid = (Activator.CreateInstance(typeof(DynamicDataGrid<>).MakeGenericType(typeof(TEntity))) as IDynamicDataGrid);
  93. if (grid == null)
  94. {
  95. MessageBox.Show($"Cannot create Grid for [{typeof(TEntity).Name}]");
  96. return;
  97. }
  98. grid.ColumnsTag = $"{ColumnsTag}.{columnname}";
  99. grid.Reconfigure(options =>
  100. {
  101. options.BeginUpdate().Clear().AddRange(DynamicGridOption.FilterRows, DynamicGridOption.SelectColumns).EndUpdate();
  102. });
  103. grid.OnDefineFilter += t =>
  104. {
  105. var filter = new Filter<TEntity>(productcol).IsEqualTo(productid)
  106. .And(unitcol).IsEqualTo(unitsize);
  107. if (styleid.HasValue)
  108. filter = filter.And(stylecol).IsEqualTo(styleid);
  109. if (jobcol != null)
  110. filter = filter.And(jobcol).IsEqualTo(Job.ID);
  111. if (extrafilter != null)
  112. filter = filter.And(extrafilter);
  113. return filter;
  114. };
  115. grid.OnFilterRecord += row => rowfilter?.Invoke(row) ?? true;
  116. var window = DynamicGridUtils.CreateGridWindow($"Viewing {CoreUtils.Neatify(columnname)} Calculation", (grid as BaseDynamicGrid)!);
  117. window.ShowDialog();
  118. }
  119. private void JobSummaryGrid_OnCellDoubleClick(object sender, DynamicGridCellClickEventArgs args)
  120. {
  121. Guid productid = args.Row.Get<StockSummary, Guid>(c => c.Product.ID);
  122. Guid? styleid = _stylecolumnVisible ? args.Row.Get<StockSummary, Guid>(c => c.Style.ID) : null;
  123. String unitsize = args.Row.Get<StockSummary, String>(c => c.Dimensions.UnitSize);
  124. if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.BillOfMaterials, ".")))
  125. {
  126. ShowDetailGrid<JobBillOfMaterialsItem>(
  127. args.Column.ColumnName,
  128. x => x.Product.ID,
  129. productid,
  130. x => x.Style.ID,
  131. styleid,
  132. x=>x.Dimensions.UnitSize,
  133. unitsize,
  134. x => x.Job.ID,
  135. new Filter<JobBillOfMaterialsItem>(x=>x.BillOfMaterials.Approved).IsNotEqualTo(DateTime.MinValue),
  136. null
  137. );
  138. }
  139. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.Requisitions, ".")))
  140. {
  141. ShowDetailGrid<JobRequisitionItem>(
  142. args.Column.ColumnName,
  143. x => x.Product.ID,
  144. productid,
  145. x => x.Style.ID,
  146. styleid,
  147. x=>x.Dimensions.UnitSize,
  148. unitsize,
  149. x => x.Job.ID,
  150. new Filter<JobRequisitionItem>(x=>x.Requisition.Approved).IsNotEqualTo(DateTime.MinValue),
  151. null
  152. );
  153. }
  154. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.PickingLists, ".")))
  155. {
  156. ShowDetailGrid<RequisitionItem>(
  157. args.Column.ColumnName,
  158. x => x.Product.ID,
  159. productid,
  160. x => x.Style.ID,
  161. styleid,
  162. x=>x.Dimensions.UnitSize,
  163. unitsize,
  164. x => x.Job.ID,
  165. new Filter<RequisitionItem>(x=>x.RequisitionLink.Filled).IsEqualTo(DateTime.MinValue),
  166. null
  167. );
  168. }
  169. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.Issued, ".")))
  170. {
  171. ShowDetailGrid<StockMovement>(
  172. args.Column.ColumnName,
  173. x => x.Product.ID,
  174. productid,
  175. x => x.Style.ID,
  176. styleid,
  177. x=>x.Dimensions.UnitSize,
  178. unitsize,
  179. x => x.Job.ID,
  180. new Filter<StockMovement>(x=>x.IsTransfer).IsEqualTo(false).And(x=>x.Issued).IsNotEqualTo(0.0F),
  181. null
  182. );
  183. }
  184. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.ReservedStock, ".")))
  185. {
  186. ShowDetailGrid<StockHolding>(
  187. args.Column.ColumnName,
  188. x => x.Product.ID,
  189. productid,
  190. x => x.Style.ID,
  191. styleid,
  192. x=>x.Dimensions.UnitSize,
  193. unitsize,
  194. x=>x.Job.ID,
  195. new Filter<StockHolding>(x => x.Units).IsGreaterThan(0.1),
  196. null
  197. );
  198. }
  199. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.OnOrder, ".")))
  200. {
  201. ShowDetailGrid<PurchaseOrderItem>(
  202. args.Column.ColumnName,
  203. x => x.Product.ID,
  204. productid,
  205. x => x.Style.ID,
  206. styleid,
  207. x=>x.Dimensions.UnitSize,
  208. unitsize,
  209. x=>x.Job.ID,
  210. null,
  211. null
  212. );
  213. }
  214. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.FreeOnHand, ".")))
  215. {
  216. ShowDetailGrid<StockHolding>(
  217. args.Column.ColumnName,
  218. x => x.Product.ID,
  219. productid,
  220. x => x.Style.ID,
  221. styleid,
  222. x=>x.Dimensions.UnitSize,
  223. unitsize,
  224. null,
  225. new Filter<StockHolding>(x=>x.Units).IsNotEqualTo(0.0F)
  226. .And(
  227. IncludeReserves
  228. ? new Filter<StockHolding>(x=>x.Job.ID).IsNotEqualTo(Job.ID)
  229. : new Filter<StockHolding>(x=>x.Job.JobStatus.Active).IsEqualTo(false)
  230. ),
  231. null
  232. );
  233. }
  234. else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.FreeOnOrder, ".")))
  235. {
  236. ShowDetailGrid<PurchaseOrderItem>(
  237. args.Column.ColumnName,
  238. x => x.Product.ID,
  239. productid,
  240. x => x.Style.ID,
  241. styleid,
  242. x=>x.Dimensions.UnitSize,
  243. unitsize,
  244. null,
  245. IncludeReserves
  246. ? new Filter<PurchaseOrderItem>(x=>x.Job.ID).IsNotEqualTo(Job.ID)
  247. : new Filter<PurchaseOrderItem>(x=>x.Job.JobStatus.Active).IsEqualTo(false),
  248. null
  249. );
  250. }
  251. }
  252. public event DataModelUpdateEvent OnUpdateDataModel;
  253. public string SectionName => "Job Summary";
  254. public DataModel DataModel(Selection selection)
  255. {
  256. return new AutoDataModel<JobMaterial>(new Filter<JobMaterial>(x => x.Job.ID).IsEqualTo(Job.ID));
  257. }
  258. protected override JobMaterial CreateItem()
  259. {
  260. var result = base.CreateItem();
  261. result.Job.ID = Job.ID;
  262. result.Job.Synchronise(Job);
  263. return result;
  264. }
  265. private Tuple<Guid,Guid,Guid?,String>[] GetKeys(IEnumerable<CoreRow> rows, Columns<JobMaterial> columns, bool hasstyle)
  266. {
  267. int jobcol = columns.IndexOf(x => x.Job.ID);
  268. int productcol = columns.IndexOf(x => x.Product.ID);
  269. int stylecol = hasstyle ? columns.IndexOf(x => x.Style.ID) : -1;
  270. int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
  271. var result = rows.Select(r => new Tuple<Guid, Guid, Guid?, String>(
  272. (Guid)(r.Values[jobcol] ?? Guid.Empty),
  273. (Guid)(r.Values[productcol] ?? Guid.Empty),
  274. (stylecol != -1) ? (Guid)(r.Values[stylecol] ?? Guid.Empty) : null,
  275. (String)(r.Values[unitcol] ?? ""))
  276. ).Distinct().ToArray();
  277. return result;
  278. }
  279. private CoreRow[] GetRows<TSource>(IEnumerable<CoreRow> rows, Columns<TSource> columns, Guid? jobid, Guid productid, Guid? styleid, String unitsize, Func<CoreRow,bool>? extrafilter = null) where TSource : IJobMaterial
  280. {
  281. int jobcol = columns.IndexOf(x => x.Job.ID);
  282. int productcol = columns.IndexOf(x => x.Product.ID);
  283. int stylecol = styleid.HasValue ? columns.IndexOf(x => x.Style.ID) : -1;
  284. int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
  285. var subset = rows
  286. .Where(r=>
  287. (!jobid.HasValue || Guid.Equals(r.Values[jobcol], jobid))
  288. && Guid.Equals(r.Values[productcol], productid)
  289. && (!styleid.HasValue || Guid.Equals(r.Values[stylecol], styleid))
  290. && String.Equals(r.Values[unitcol], unitsize)
  291. && ((extrafilter == null) || extrafilter(r) )
  292. );
  293. return subset.ToArray();
  294. }
  295. private double Aggregate<TSource>(IEnumerable<CoreRow> rows, Columns<TSource> columns, bool hasstyle, bool hasjob, Expression<Func<TSource, object>> source, CoreRow target, Expression<Func<JobMaterial, object>> aggregate )
  296. {
  297. int srcol = columns.IndexOf(source);
  298. if (srcol == -1)
  299. return 0.00;
  300. var total = rows.Aggregate(0d, (value, row) => value + (double)(row.Values[srcol] ?? 0.0d));
  301. target.Set(aggregate, total);
  302. return total;
  303. }
  304. protected override void Reload(Filters<JobMaterial> criteria, Columns<JobMaterial> columns, ref SortOrder<JobMaterial>? sort,
  305. Action<CoreTable?, Exception?> action)
  306. {
  307. Filter<JobMaterial>? filter = Job.ID == Guid.Empty
  308. ? new Filter<JobMaterial>().None()
  309. : new Filter<JobMaterial>(x => x.Job.ID).IsEqualTo(Job.ID)
  310. .And(x => x.Product.ID).IsNotEqualTo(Guid.Empty);
  311. var orderby = sort;
  312. Progress.ShowModal("Loading Data",
  313. (progress) =>
  314. {
  315. CoreTable table = new CoreTable();
  316. table.LoadColumns(columns);
  317. var data = new Client<JobMaterial>().Query(filter, columns, orderby);
  318. var pids = data.ExtractValues<JobMaterial, Guid>(x => x.Product.ID).ToArray();
  319. if (pids.Any())
  320. {
  321. MultiQuery query = new MultiQuery();
  322. query.Add<StockHolding>(
  323. new Filter<StockHolding>(x => x.Product.ID).InList(pids)
  324. .And(x => x.Units).IsNotEqualTo(0.0F)
  325. .And(new Filter<StockHolding>(x => x.Job.ID).IsEqualTo(Guid.Empty).Or(x=>x.Job.ID).IsNotEqualTo(Job.ID)),
  326. new Columns<StockHolding>(x => x.Product.ID)
  327. .Add(x => x.Style.ID)
  328. .Add(x => x.Dimensions.UnitSize)
  329. .Add(x => x.Units)
  330. .Add(x => x.Job.ID)
  331. .Add(x => x.Job.JobStatus.Active)
  332. );
  333. query.Add<PurchaseOrderItem>(
  334. new Filter<PurchaseOrderItem>(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue)
  335. .And(x => x.Product.ID).InList(pids)
  336. .And(new Filter<PurchaseOrderItem>(x => x.Job.ID).IsEqualTo(Guid.Empty).Or(x=>x.Job.ID).IsNotEqualTo(Job.ID)),
  337. new Columns<PurchaseOrderItem>(x => x.Product.ID)
  338. .Add(x => x.Style.ID)
  339. .Add(x => x.Dimensions.UnitSize)
  340. .Add(x => x.Qty)
  341. .Add(x => x.Job.ID)
  342. .Add(x => x.Job.JobStatus.Active)
  343. );
  344. query.Query();
  345. var freestock = query.Get<StockHolding>();
  346. Columns<StockHolding> freestockcolumns = new Columns<StockHolding>(freestock.Columns.Select(x => x.ColumnName));
  347. var freeorders = query.Get<PurchaseOrderItem>();
  348. Columns<PurchaseOrderItem> freeordercolumns = new Columns<PurchaseOrderItem>(freeorders.Columns.Select(x => x.ColumnName));
  349. var keys = GetKeys(data.Rows, columns, _stylecolumnVisible);
  350. foreach (var key in keys)
  351. {
  352. var rows = GetRows(data.Rows, columns, key.Item1, key.Item2, key.Item3, key.Item4);
  353. if (rows.Any())
  354. {
  355. CoreRow newrow = table.NewRow();
  356. newrow.LoadValues(rows.First().Values);
  357. var bom = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.BillOfMaterials, newrow,
  358. x => x.BillOfMaterials);
  359. var requi = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.Requisitions, newrow, x => x.Requisitions);
  360. var picklist = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.PickingLists, newrow,
  361. x => x.PickingLists);
  362. var issued = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.Issued, newrow, x => x.Issued);
  363. var reserved = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.ReservedStock, newrow,
  364. x => x.ReservedStock);
  365. var ordered = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.OnOrder, newrow, x => x.OnOrder);
  366. var shortage = Math.Max(0, Math.Max(0, (requi - issued)) - (reserved + ordered));
  367. newrow.Set<JobMaterial, double>(x => x.JobShortage, shortage);
  368. var freestockrows = GetRows(freestock.Rows, freestockcolumns, null, key.Item2, key.Item3, key.Item4,
  369. IncludeReserves ? null : (r) => !r.Get<StockHolding,bool>(x=>x.Job.JobStatus.Active));
  370. var freeonhand = Aggregate(freestockrows, freestockcolumns, _stylecolumnVisible, false, x => x.Units, newrow,
  371. x => x.FreeOnHand);
  372. newrow.Set<JobMaterial, double>(x => x.FreeOnHand, freeonhand);
  373. var freeorderrows = GetRows(freeorders.Rows, freeordercolumns, null, key.Item2, key.Item3, key.Item4,
  374. IncludeReserves ? null : (r) => !r.Get<PurchaseOrderItem,bool>(x=>x.Job.JobStatus.Active));
  375. var freeonorder = Aggregate(freeorderrows, freeordercolumns, _stylecolumnVisible, false, x => x.Qty, newrow,
  376. x => x.FreeOnOrder);
  377. newrow.Set<JobMaterial, double>(x => x.FreeOnOrder, freeonorder);
  378. newrow.Set<JobMaterial, double>(x => x.FreeStockTotal, freeonhand + freeonorder);
  379. newrow.Set<JobMaterial, double>(x => x.FreeStockShortage, Math.Max(0, shortage - (freeonhand + freeonorder)));
  380. table.Rows.Add(newrow);
  381. }
  382. }
  383. }
  384. action?.Invoke(table, null);
  385. }
  386. );
  387. }
  388. protected override bool FilterRecord(CoreRow row)
  389. {
  390. var result = base.FilterRecord(row)
  391. && (
  392. row.Get<JobMaterial, double>(x => x.BillOfMaterials) != 0.0F ||
  393. row.Get<JobMaterial, double>(x => x.Requisitions) != 0.0F ||
  394. row.Get<JobMaterial, double>(x => x.PickingLists) != 0.0F ||
  395. row.Get<JobMaterial, double>(x => x.Issued) != 0.0F ||
  396. row.Get<JobMaterial, double>(x => x.ReservedStock) != 0.0F ||
  397. row.Get<JobMaterial, double>(x => x.OnOrder) != 0.0F
  398. );
  399. return result;
  400. }
  401. private String _jobshortage = CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.JobShortage, ".");
  402. private String _stockshortage = CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.FreeStockShortage, ".");
  403. protected override Brush? GetCellBackground(CoreRow row, string columnname)
  404. {
  405. if (String.Equals(columnname, _jobshortage))
  406. return row.Get<JobMaterial, double>(x => x.JobShortage) > 0.0F ? new SolidColorBrush(Colors.LightSalmon) { Opacity = 0.5 } : null;
  407. if (String.Equals(columnname, _stockshortage))
  408. return row.Get<JobMaterial, double>(x => x.FreeStockShortage) > 0.0F ? new SolidColorBrush(Colors.LightSalmon) { Opacity = 0.5 } : null;
  409. return null;
  410. }
  411. #region Create PO
  412. private void GetEmpID()
  413. {
  414. 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));
  415. if (table.Rows.Any())
  416. {
  417. empID = Guid.Parse(table.Rows.FirstOrDefault().Values[0].ToString());
  418. empName = table.Rows.FirstOrDefault().Values[1].ToString();
  419. }
  420. }
  421. private bool CreatePO(System.Windows.Controls.Button btn, CoreRow[] rows)
  422. {
  423. if (!rows.Any())
  424. {
  425. MessageBox.Show("Please select at least one row to add to PO");
  426. return false;
  427. }
  428. PurchaseOrder purchaseOrder = new PurchaseOrder();
  429. purchaseOrder.Description = "Created from Job Summary Screen" + System.Environment.NewLine;
  430. purchaseOrder.RaisedBy.ID = empID;
  431. var page = new SupplierPurchaseOrders();
  432. page.OnAfterSave += (form, items) =>
  433. {
  434. MessageBox.Show("Success - New Purchase Order Created (" + purchaseOrder.PONumber + ")");
  435. };
  436. return page.EditItems(new[] { purchaseOrder }, LoadPurchaseOrderItems, true);
  437. }
  438. private CoreTable LoadPurchaseOrderItems(Type arg)
  439. {
  440. Progress.Show("Working");
  441. var result = new CoreTable();
  442. result.LoadColumns(typeof(PurchaseOrderItem));
  443. List<PurchaseOrderItem> items = new List<PurchaseOrderItem>();
  444. foreach (CoreRow row in SelectedRows)
  445. {
  446. JobMaterial material = row.ToObject<JobMaterial>();
  447. PurchaseOrderItem POItem = new PurchaseOrderItem();
  448. POItem.Product.ID = material.Product.ID;
  449. POItem.Product.Code = material.Product.Code;
  450. POItem.Product.Name = material.Product.Name;
  451. POItem.Description = material.Product.Name;
  452. POItem.Qty = 0;
  453. POItem.Dimensions.CopyFrom(material.Dimensions);
  454. POItem.Style.ID = material.Style.ID;
  455. POItem.Style.Code = material.Style.Code;
  456. POItem.Style.Description = material.Style.Description;
  457. POItem.Job.ID = material.Job.ID;
  458. POItem.Dimensions.UnitSize = material.Dimensions.UnitSize;
  459. items.Add(POItem);
  460. }
  461. result.LoadRows(items);
  462. Progress.Close();
  463. return result;
  464. }
  465. #endregion
  466. }
  467. }