TaskPanel.xaml.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Controls.Primitives;
  9. using Comal.Classes;
  10. using InABox.Clients;
  11. using InABox.Configuration;
  12. using InABox.Core;
  13. using InABox.DynamicGrid;
  14. using InABox.WPF;
  15. using Syncfusion.Pdf.Graphics;
  16. using Syncfusion.Pdf;
  17. using System.Windows.Data;
  18. using System.Windows.Media;
  19. using System.Drawing;
  20. using System.Globalization;
  21. namespace PRSDesktop
  22. {
  23. public class TaskPanelProperties : BaseObject, IGlobalConfigurationSettings
  24. {
  25. [CheckBoxEditor(ToolTip = "Require that all tasks are given a task type.")]
  26. public bool RequireTaskTypes { get; set; } = false;
  27. }
  28. /// <summary>
  29. /// Interaction logic for TaskPanel.xaml
  30. /// </summary>
  31. public partial class TaskPanel : UserControl, IPanel<Kanban>, ITaskHost, IJobControl, IPropertiesPanel<TaskPanelProperties>
  32. {
  33. private bool _bTabChanging;
  34. public Guid MyID { get; set; } = CoreUtils.FullGuid;
  35. private KanbanType[] kanbanTypes = null!; // Initialized in Setup()
  36. public IList<KanbanType> KanbanTypes => kanbanTypes;
  37. public TaskPanel()
  38. {
  39. InitializeComponent();
  40. foreach (TabItem tab in TaskPanels.Items)
  41. {
  42. var panel = (tab.Content as ITaskControl)!;
  43. _viewmap[panel.KanbanViewType] = tab;
  44. panel.Host = this;
  45. }
  46. if (MyID == CoreUtils.FullGuid)
  47. {
  48. var row = new Client<Employee>()
  49. .Query(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid), new Columns<Employee>(x => x.ID)).Rows
  50. .FirstOrDefault();
  51. if (row != null)
  52. MyID = row.Get<Employee, Guid>(x => x.ID);
  53. }
  54. }
  55. public Guid ParentID { get; set; }
  56. public JobPanelSettings Settings { get; set; }
  57. private void ChangeStatus(ITaskControl control, object o, RoutedEventArgs e, string status)
  58. {
  59. if (MessageBox.Show($"Are you sure you want to mark the selected tasks as {status}?", "Confirm Change Status",
  60. MessageBoxButton.YesNo) != MessageBoxResult.Yes)
  61. return;
  62. var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
  63. Progress.ShowModal("Changing Status", progress =>
  64. {
  65. var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Completed, x => x.Category));
  66. foreach (var kanban in kanbans)
  67. {
  68. if(status == "Complete")
  69. {
  70. kanban.Completed = DateTime.Now;
  71. }
  72. kanban.Category = status;
  73. }
  74. new Client<Kanban>().Save(kanbans, $"Kanban Marked as {status}");
  75. });
  76. control.Refresh(true);
  77. }
  78. private void CompleteTask(ITaskControl control, RoutedEventArgs e, DateTime completed)
  79. {
  80. if (MessageBox.Show($"Are you sure you want to complete the selected tasks?", "Confirm Completion",
  81. MessageBoxButton.YesNo) != MessageBoxResult.Yes)
  82. return;
  83. var tasks = (((FrameworkElement)e.Source).Tag as IEnumerable<TaskModel>)!;
  84. Progress.ShowModal("Completing Tasks", progress =>
  85. {
  86. var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Completed, x => x.Category));
  87. foreach (var kanban in kanbans)
  88. {
  89. kanban.Completed = completed;
  90. kanban.Category = "Complete";
  91. }
  92. new Client<Kanban>().Save(kanbans, $"Kanban Marked as Complete");
  93. });
  94. control.Refresh(true);
  95. }
  96. private void AddChangeStatusButton(ITaskControl control, TaskModel[] models, MenuItem menu, string header, string status)
  97. {
  98. var item = new MenuItem
  99. {
  100. Tag = models,
  101. Header = header
  102. };
  103. item.Click += (o, e) => ChangeStatus(control, o, e, status);
  104. menu.Items.Add(item);
  105. }
  106. public bool CanChangeTasks(IEnumerable<TaskModel> models)
  107. {
  108. foreach (var task in models)
  109. {
  110. if (!MyID.Equals(task.ManagerID) && !MyID.Equals(task.EmployeeID))
  111. {
  112. // If you can change others tasks, IsFullControl is true - but we don't check at the beginning of the function
  113. // to save checking security tokens every time.
  114. return Security.IsAllowed<CanChangeOthersTasks>();
  115. }
  116. }
  117. return true;
  118. }
  119. /// <summary>
  120. /// <paramref name="menu"/> should have <see cref="FrameworkElement.Tag"/> set to a <see cref="TaskModel"/>.
  121. /// </summary>
  122. /// <param name="control"></param>
  123. /// <param name="menu"></param>
  124. public void PopulateMenu(ITaskControl control, ContextMenu menu)
  125. {
  126. menu.Items.Clear();
  127. var models = control.SelectedModels((menu.Tag as TaskModel)!).ToArray();
  128. var references = GetReferences(models);
  129. var bLinks = references.Any(x => x.ReferenceType() != null);
  130. var referencetypes = references.Select(x => x.ReferenceType()).Distinct().ToArray();
  131. var bSingle = models.Length == 1;
  132. var canChange = CanChangeTasks(models);
  133. var edit = new MenuItem
  134. {
  135. Tag = models,
  136. Header = referencetypes.SingleOrDefault() == typeof(Requisition)
  137. ? "Edit Requisition Details"
  138. : referencetypes.SingleOrDefault() == typeof(Setout)
  139. ? "Edit Setout Details"
  140. : referencetypes.SingleOrDefault() == typeof(Delivery)
  141. ? "Edit Delivery Details"
  142. : referencetypes.SingleOrDefault() == typeof(PurchaseOrder)
  143. ? "Edit Order Details"
  144. : "Edit Task" + (bSingle ? "" : "s")
  145. };
  146. edit.Click += (o, e) =>
  147. {
  148. var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
  149. if (EditReferences(tasks))
  150. control.Refresh(true);
  151. e.Handled = true;
  152. };
  153. edit.IsEnabled = referencetypes.Length == 1;
  154. menu.Items.Add(edit);
  155. if (!bLinks && models.Length == 1)
  156. {
  157. var digitalForms = new MenuItem { Header = "Digital Forms" };
  158. var model = models.First();
  159. Guid kanbanID = Guid.Parse(model.ID);
  160. DynamicGridUtils.PopulateFormMenu<KanbanForm, Kanban, KanbanLink>(
  161. digitalForms,
  162. kanbanID,
  163. () => new Client<Kanban>().Load(new Filter<Kanban>(x => x.ID).IsEqualTo(kanbanID)).First(),
  164. model.EmployeeID == MyID);
  165. menu.Items.Add(digitalForms);
  166. }
  167. if (!models.Any(x => !x.CompletedDate.IsEmpty()) && !bLinks)
  168. {
  169. menu.Items.Add(new Separator());
  170. var job = new MenuItem
  171. {
  172. Tag = models,
  173. Header = "Link to Job"
  174. };
  175. job.SubmenuOpened += (o, e) => CreateJobSubMenu(control, job, models);
  176. menu.Items.Add(job);
  177. if (bSingle)
  178. {
  179. menu.AddItem("Create Setout from Task", null, models.First(), task =>
  180. {
  181. var jobID = task.JobID;
  182. if (task.JobID.Equals(Guid.Empty))
  183. {
  184. jobID = ParentID;
  185. }
  186. if (MessageBox.Show("This will convert this task into a Setout.\n\nDo you wish to continue?", "Confirmation", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
  187. return;
  188. ManufacturingTemplate? template = new Client<ManufacturingTemplate>()
  189. .Load(new Filter<ManufacturingTemplate>(x => x.Code).IsEqualTo("PRS")).FirstOrDefault();
  190. if (template == null)
  191. {
  192. MessageBox.Show("[Pressing] Template does not exist!");
  193. return;
  194. }
  195. string? setoutNumber = null;
  196. Kanban? kanban = null;
  197. ManufacturingTemplateStage[] tstages = Array.Empty<ManufacturingTemplateStage>();
  198. Progress.ShowModal("Creating Setout", (progress) =>
  199. {
  200. var kanbanFilter = new Filter<Kanban>(x => x.ID).IsEqualTo(task.ID);
  201. var tables = Client.QueryMultiple(new Dictionary<string, IQueryDef>
  202. {
  203. { "ManufacturingTemplateStage", new QueryDef<ManufacturingTemplateStage>(
  204. new Filter<ManufacturingTemplateStage>(x => x.Template.ID).IsEqualTo(template.ID),
  205. null,
  206. new SortOrder<ManufacturingTemplateStage>(x => x.Sequence)) },
  207. { "Kanban", new QueryDef<Kanban>(
  208. kanbanFilter,
  209. null,
  210. null) },
  211. { "Setout", new QueryDef<Setout>(
  212. new Filter<Setout>(x => x.JobLink.ID)
  213. .InQuery(new SubQuery<Kanban>(kanbanFilter, new Column<Kanban>(x => x.JobLink.ID))),
  214. new Columns<Setout>(x => x.JobLink.JobNumber, x => x.Number),
  215. null) }
  216. });
  217. tstages = tables["ManufacturingTemplateStage"].Rows
  218. .Select(x => x.ToObject<ManufacturingTemplateStage>()).ToArray();
  219. kanban = tables["Kanban"].Rows.FirstOrDefault()?.ToObject<Kanban>();
  220. if (kanban == null)
  221. {
  222. MessageBox.Show("Task does not exist!");
  223. return;
  224. }
  225. progress.Report("Creating Setouts");
  226. CoreTable setouts = tables["Setout"];
  227. int ireq = 0;
  228. string sreq = "";
  229. while (true)
  230. {
  231. ireq++;
  232. sreq = string.Format("{0}-{1:yyMMdd}-{2}", kanban.JobLink.JobNumber, DateTime.Now, ireq);
  233. if (!setouts.Rows.Any(r => sreq.Equals(r.Get<Setout, String>(c => c.Number))))
  234. break;
  235. }
  236. setoutNumber = sreq;
  237. });
  238. if (setoutNumber == null || kanban == null)
  239. {
  240. return;
  241. }
  242. var result = CreateSetout(
  243. task,
  244. s =>
  245. {
  246. s.Number = setoutNumber;
  247. s.JobLink.ID = jobID;
  248. var notes = kanban.Notes.ToList();
  249. var description = kanban.Summary;
  250. if (string.IsNullOrWhiteSpace(description))
  251. {
  252. description = CoreUtils.StripHTML(kanban.Description);
  253. }
  254. if (!string.IsNullOrWhiteSpace(description))
  255. {
  256. notes.Insert(0, description);
  257. }
  258. s.Description = string.Join("\n==========================================\n", notes);
  259. }
  260. );
  261. if (result != null)
  262. {
  263. Progress.ShowModal("Creating Manufacturing Packet", progress =>
  264. {
  265. ManufacturingPacket packet = new ManufacturingPacket()
  266. {
  267. Serial = template.Code,
  268. Title = kanban.Title,
  269. Quantity = 1,
  270. BarcodeQty = 1,
  271. DueDate = kanban.DueDate
  272. };
  273. packet.ManufacturingTemplateLink.ID = template.ID;
  274. packet.ManufacturingTemplateLink.Code = template.Code;
  275. packet.ManufacturingTemplateLink.Factory.ID = template.Factory.ID;
  276. packet.SetoutLink.ID = result.ID;
  277. new Client<ManufacturingPacket>().Save(packet, "Created from Task");
  278. DoLink<ManufacturingPacketKanban, ManufacturingPacket, ManufacturingPacketLink>(task, packet.ID);
  279. List<ManufacturingPacketStage> pstages = new List<ManufacturingPacketStage>();
  280. foreach (var tstage in tstages)
  281. {
  282. var pstage = new ManufacturingPacketStage()
  283. {
  284. Time = tstage.Time,
  285. Sequence = tstage.Sequence,
  286. SequenceType = tstage.SequenceType,
  287. Started = DateTime.MinValue,
  288. PercentageComplete = 0.0F,
  289. Completed = DateTime.MinValue,
  290. QualityChecks = tstage.QualityChecks,
  291. QualityStatus = QualityStatus.NotChecked,
  292. QualityNotes = "",
  293. };
  294. pstage.Parent.ID = packet.ID;
  295. pstage.ManufacturingSectionLink.ID = tstage.Section.ID;
  296. pstage.ManufacturingSectionLink.Name = tstage.Section.Name;
  297. pstages.Add(pstage);
  298. }
  299. new Client<ManufacturingPacketStage>().Save(pstages, "Created from Task", (_, __) => { });
  300. progress.Report("Processing Documents");
  301. List<SetoutDocument> _setoutdocuments = new List<SetoutDocument>();
  302. List<KanbanDocument> _kanbandocuments = new List<KanbanDocument>();
  303. KanbanDocument[] docrefs = new Client<KanbanDocument>()
  304. .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
  305. foreach (var docref in docrefs)
  306. {
  307. // Convert the document to a PDF
  308. var docid = ProcessKanbanDocument(docref);
  309. var newdoc = new SetoutDocument();
  310. newdoc.EntityLink.ID = result.ID;
  311. newdoc.DocumentLink.ID = docid;
  312. _setoutdocuments.Add(newdoc);
  313. if (docid != docref.DocumentLink.ID)
  314. {
  315. docref.DocumentLink.ID = docid;
  316. _kanbandocuments.Add(docref);
  317. }
  318. }
  319. new Client<SetoutDocument>().Save(_setoutdocuments, "Converted from Task", (_, __) => { });
  320. new Client<KanbanDocument>().Save(_kanbandocuments, "Converted to PDF", (_, __) => { });
  321. progress.Report("Updating Task");
  322. kanban.Title = kanban.Title + " (" + result.Number + ")";
  323. new Client<Kanban>().Save(kanban, "Converting Kanban to Setout");
  324. });
  325. control.Refresh(true);
  326. }
  327. });
  328. menu.AddItem("Create Requisition from Task", null, models, tasks =>
  329. {
  330. var taskModel = tasks.First();
  331. var jobID = taskModel.JobID;
  332. if (taskModel.JobID.Equals(Guid.Empty))
  333. {
  334. jobID = ParentID;
  335. }
  336. var kanbanTable = new Client<Kanban>().Query(new Filter<Kanban>(x => x.ID).IsEqualTo(taskModel.ID));
  337. var kanban = kanbanTable.Rows.First().ToObject<Kanban>();
  338. var result = CreateRequisition(
  339. taskModel,
  340. r =>
  341. {
  342. r.RequestedBy.ID = kanban.ManagerLink.ID;
  343. r.Employee.ID = Guid.Empty;
  344. r.Title = kanban.Title;
  345. r.Request = string.IsNullOrWhiteSpace(kanban.Summary)
  346. ? String.IsNullOrWhiteSpace(kanban.Description)
  347. ? String.Join("\n", kanban.Notes)
  348. : CoreUtils.StripHTML(kanban.Description)
  349. : kanban.Summary;
  350. r.Notes = kanban.Notes;
  351. r.Due = kanban.DueDate;
  352. r.JobLink.ID = jobID;
  353. }
  354. );
  355. if (result != null)
  356. {
  357. Progress.ShowModal("Updating Documents", progress =>
  358. {
  359. progress.Report("Updating Documents");
  360. List<RequisitionDocument> requiDocuments = new();
  361. KanbanDocument[] kanbanDocuments = new Client<KanbanDocument>()
  362. .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
  363. foreach (var document in kanbanDocuments)
  364. {
  365. var newdoc = new RequisitionDocument();
  366. newdoc.EntityLink.ID = result.ID;
  367. newdoc.DocumentLink.ID = document.DocumentLink.ID;
  368. requiDocuments.Add(newdoc);
  369. }
  370. new Client<RequisitionDocument>().Save(requiDocuments, "Converted from Task", (_, __) => { });
  371. /*RequisitionKanban link = new();
  372. link.Entity.ID = result.ID;
  373. link.Kanban.ID = kanban.ID;
  374. new Client<RequisitionKanban>().Save(link, "Converting Task -> Requisition", (_, __) => { });*/
  375. progress.Report("Updating Task");
  376. kanban.Category = "Open";
  377. kanban.Completed = DateTime.MinValue;
  378. kanban.Title += $" (Requi #{result.Number})";
  379. new Client<Kanban>().Save(kanban, "Converted to Requisition", (_, __) => { });
  380. });
  381. MessageBox.Show(String.Format("Created Requisition {0}", result.Number));
  382. control.Refresh(true);
  383. }
  384. });
  385. menu.AddItem("Create Delivery from Task", null, models, tasks =>
  386. {
  387. var result = CreateDelivery(
  388. tasks.First(),
  389. d =>
  390. {
  391. // Post-Process Requi Here
  392. }
  393. );
  394. if (result != null)
  395. control.Refresh(true);
  396. });
  397. menu.AddItem("Create Purchase Order from Task", null, models, tasks =>
  398. {
  399. var result = CreateOrder(
  400. tasks.First(),
  401. p =>
  402. {
  403. // Post-Process Requi Here
  404. }
  405. );
  406. if (result != null)
  407. control.Refresh(true);
  408. });
  409. }
  410. }
  411. if (!bLinks && canChange)
  412. {
  413. menu.Items.Add(new Separator());
  414. var changeStatus = new MenuItem { Header = "Change Status" };
  415. AddChangeStatusButton(control, models, changeStatus, "Open", "Open");
  416. AddChangeStatusButton(control, models, changeStatus, "In Progress", "In Progress");
  417. AddChangeStatusButton(control, models, changeStatus, "Waiting", "Waiting");
  418. if (models.Any(x => x.CompletedDate.IsEmpty()))
  419. {
  420. var complete = new MenuItem
  421. {
  422. Tag = models,
  423. Header = models.Length > 1 ? "Complete Tasks" : "Complete Task"
  424. };
  425. complete.Click += (o, e) =>
  426. {
  427. CompleteTask(control, e, DateTime.Now);
  428. };
  429. menu.Items.Add(complete);
  430. if (Security.IsAllowed<CanSetKanbanCompletedDate>())
  431. {
  432. var completeDate = new MenuItem
  433. {
  434. Tag = models,
  435. Header = "Set Completed Date"
  436. };
  437. var dateItem = new MenuItem();
  438. var dateCalendar = new System.Windows.Controls.Calendar { SelectedDate = DateTime.MinValue };
  439. dateCalendar.Tag = models;
  440. dateCalendar.SelectedDatesChanged += (o, e) =>
  441. {
  442. if (e.Source is not System.Windows.Controls.Calendar calendar) return;
  443. menu.IsOpen = false;
  444. var selectedDate = calendar.SelectedDate ?? DateTime.Now;
  445. CompleteTask(control, e, selectedDate);
  446. };
  447. dateItem.Header = dateCalendar;
  448. dateItem.Style = Resources["calendarItem"] as Style;
  449. completeDate.Items.Add(dateItem);
  450. menu.Items.Add(completeDate);
  451. }
  452. }
  453. else
  454. {
  455. menu.AddItem(models.Length > 1 ? "Archive Tasks" : "Archive Task", null, models, tasks =>
  456. {
  457. if (MessageBox.Show("Are you sure you want to remove the selected tasks from the list?", "Confirm removal",
  458. MessageBoxButton.YesNo) != MessageBoxResult.Yes)
  459. return;
  460. Progress.ShowModal("Closing Kanbans", progress =>
  461. {
  462. var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Closed));
  463. foreach (var kanban in kanbans)
  464. kanban.Closed = DateTime.Now;
  465. new Client<Kanban>().Save(kanbans, "Kanban Marked as Closed");
  466. });
  467. control.Refresh(true);
  468. });
  469. }
  470. menu.Items.Add(changeStatus);
  471. var changeType = new MenuItem { Header = "Change Task Type", Tag = models };
  472. foreach(var type in KanbanTypes)
  473. {
  474. changeType.AddItem($"{type.Code}: {type.Description}", null, type, type =>
  475. {
  476. Progress.ShowModal("Changing Task Type", progress =>
  477. {
  478. var kanbans = LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.Type.ID));
  479. foreach (var kanban in kanbans)
  480. {
  481. kanban.Type.ID = type.ID;
  482. }
  483. new Client<Kanban>().Save(kanbans, $"Kanban Task Type changed to {type}");
  484. });
  485. control.Refresh(true);
  486. });
  487. }
  488. menu.Items.Add(changeType);
  489. var changeDueDate = new MenuItem { Header = "Change Due Date" };
  490. var calendarItem = new MenuItem();
  491. var calendar = new System.Windows.Controls.Calendar { SelectedDate = models.Length == 1 ? models[0].DueDate : DateTime.Today };
  492. calendar.Tag = models;
  493. calendar.SelectedDatesChanged += (o, e) =>
  494. {
  495. if (e.Source is not System.Windows.Controls.Calendar calendar) return;
  496. var selectedDate = calendar.SelectedDate ?? DateTime.Now;
  497. var models = (calendar.Tag as IList<TaskModel>)!;
  498. Progress.ShowModal("Changing Due Date", progress =>
  499. {
  500. var kanbans = LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.DueDate));
  501. foreach (var kanban in kanbans)
  502. {
  503. kanban.DueDate = selectedDate;
  504. }
  505. new Client<Kanban>().Save(kanbans, $"Kanban Due Date changed to {selectedDate:dd MMM yyyy}");
  506. });
  507. control.Refresh(true);
  508. menu.IsOpen = false;
  509. };
  510. calendarItem.Header = calendar;
  511. calendarItem.Style = Resources["calendarItem"] as Style;
  512. changeDueDate.Items.Add(calendarItem);
  513. menu.Items.Add(changeDueDate);
  514. }
  515. }
  516. /// <summary>
  517. /// Takes a <see cref="KanbanDocument"/>, and if it is a .txt or an image (".png", ".jpg", ".jpeg" or ".bmp"), converts to a PDF
  518. /// with the content of the document, saving a new document with extension changed to ".pdf".
  519. /// </summary>
  520. /// <param name="docref">The original document.</param>
  521. /// <returns>
  522. /// The ID of the new <see cref="Document"/> or,
  523. /// if not one of the given types, the original document ID.
  524. /// </returns>
  525. private static Guid ProcessKanbanDocument(KanbanDocument docref)
  526. {
  527. var result = docref.DocumentLink.ID;
  528. var ext = System.IO.Path.GetExtension(docref.DocumentLink.FileName).ToLower();
  529. if (ext.EndsWith("txt"))
  530. {
  531. var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
  532. if (doc is null)
  533. {
  534. Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
  535. return docref.DocumentLink.ID;
  536. }
  537. PdfDocument pdf = new PdfDocument();
  538. PdfPage page = pdf.Pages.Add();
  539. PdfGraphics graphics = page.Graphics;
  540. PdfFont font = new PdfStandardFont(PdfFontFamily.Courier, 12);
  541. String text = System.Text.Encoding.UTF8.GetString(doc.Data);
  542. graphics.DrawString(text, font, PdfBrushes.Black, new PointF(0, 0));
  543. MemoryStream ms = new MemoryStream();
  544. pdf.Save(ms);
  545. pdf.Close(true);
  546. byte[] data = ms.ToArray();
  547. var newdoc = new Document()
  548. {
  549. Data = data,
  550. FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
  551. CRC = CoreUtils.CalculateCRC(data),
  552. TimeStamp = DateTime.Now,
  553. };
  554. new Client<Document>().Save(newdoc, "Converted from Text");
  555. return newdoc.ID;
  556. }
  557. else if (ext.EndsWith("png") || ext.EndsWith("bmp") || ext.EndsWith("jpg") || ext.EndsWith("jpeg"))
  558. {
  559. var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
  560. if (doc is null)
  561. {
  562. Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
  563. return docref.DocumentLink.ID;
  564. }
  565. PdfBitmap image = new PdfBitmap(new MemoryStream(doc.Data));
  566. PdfDocument pdf = new PdfDocument();
  567. pdf.PageSettings.Orientation = image.Height > image.Width ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
  568. pdf.PageSettings.Size = new SizeF(image.Width, image.Height);
  569. PdfPage page = pdf.Pages.Add();
  570. PdfGraphics graphics = page.Graphics;
  571. graphics.DrawImage(image, 0.0F, 0.0F);
  572. MemoryStream ms = new MemoryStream();
  573. pdf.Save(ms);
  574. pdf.Close(true);
  575. byte[] data = ms.ToArray();
  576. var newdoc = new Document()
  577. {
  578. Data = data,
  579. FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
  580. CRC = CoreUtils.CalculateCRC(data),
  581. TimeStamp = DateTime.Now,
  582. };
  583. new Client<Document>().Save(newdoc, "Converted from Image");
  584. return newdoc.ID;
  585. }
  586. return result;
  587. }
  588. private void TaskPanels_SelectionChanged(object sender, SelectionChangedEventArgs e)
  589. {
  590. if (!IsReady)
  591. return;
  592. if (e.Source is not TabControl)
  593. return;
  594. if (_bTabChanging)
  595. return;
  596. try
  597. {
  598. _bTabChanging = true;
  599. var panel = GetCurrentPanel();
  600. if(panel is not null)
  601. {
  602. KanbanSettings.ViewType = panel.KanbanViewType;
  603. new UserConfiguration<KanbanSettings>().Save(KanbanSettings);
  604. panel.Refresh(false);
  605. }
  606. }
  607. finally
  608. {
  609. _bTabChanging = false;
  610. }
  611. }
  612. private void CreateJobSubMenu(ITaskControl control, MenuItem job, IEnumerable<TaskModel> tasks)
  613. {
  614. job.Items.Clear();
  615. job.Items.Add(new MenuItem { Header = "Loading...", IsEnabled = false });
  616. using (new WaitCursor())
  617. {
  618. job.Items.Clear();
  619. var jobs = new Client<Job>().Query(
  620. LookupFactory.DefineFilter<Job>(),
  621. LookupFactory.DefineColumns<Job>(),
  622. LookupFactory.DefineSort<Job>()
  623. );
  624. foreach (var row in jobs.Rows)
  625. {
  626. var jobNumber = row.Get<Job, string>(x => x.JobNumber);
  627. var jobName = row.Get<Job, string>(x => x.Name);
  628. job.AddItem($"{jobNumber}: {jobName}", null, tasks, tasks =>
  629. {
  630. using (new WaitCursor())
  631. {
  632. var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.JobLink.ID));
  633. foreach (var kanban in kanbans)
  634. kanban.JobLink.ID = row.Get<Job, Guid>(x => x.ID);
  635. new Client<Kanban>().Save(kanbans, "Updated Job Number");
  636. control.Refresh(false);
  637. }
  638. });
  639. }
  640. }
  641. }
  642. #region Get/Save Settings
  643. private KanbanSettings? _settings;
  644. public KanbanSettings KanbanSettings
  645. {
  646. get
  647. {
  648. _settings ??= new UserConfiguration<KanbanSettings>().Load();
  649. return _settings;
  650. }
  651. }
  652. public void SaveSettings()
  653. {
  654. if(_settings != null)
  655. new UserConfiguration<KanbanSettings>().Save(_settings);
  656. }
  657. #endregion
  658. #region IPanel Stuff
  659. public event DataModelUpdateEvent? OnUpdateDataModel;
  660. public bool IsReady { get; set; }
  661. public void CreateToolbarButtons(IPanelHost host)
  662. {
  663. host.CreatePanelAction(
  664. new PanelAction
  665. {
  666. Caption = "New Task",
  667. OnExecute = a => {
  668. if(CreateKanban(k => { }) != null)
  669. {
  670. Refresh();
  671. }
  672. },
  673. Image = PRSDesktop.Resources.add
  674. }
  675. );
  676. }
  677. public Dictionary<string, object[]> Selected()
  678. {
  679. return new Dictionary<string, object[]>();
  680. }
  681. public void Heartbeat(TimeSpan time)
  682. {
  683. }
  684. private readonly Dictionary<KanbanViewType, TabItem> _viewmap = new();
  685. private readonly List<ITaskControl> _initialized = new();
  686. private ITaskControl
  687. GetCurrentPanel()
  688. {
  689. var result = (TaskPanels.SelectedContent as ITaskControl)!;
  690. if (result == null)
  691. result = (TaskPanels.Items[0] as DynamicTabItem)?.Content as ITaskControl;
  692. try
  693. {
  694. //if (result != null)
  695. if (!_initialized.Contains(result))
  696. {
  697. result.Setup();
  698. result.IsReady = true;
  699. _initialized.Add(result);
  700. }
  701. }
  702. catch (Exception e)
  703. {
  704. Logger.Send(LogType.Error, "", $"Error in TaskPanel.GetCurrentPanel: {CoreUtils.FormatException(e)}");
  705. }
  706. return result;
  707. }
  708. public void Setup()
  709. {
  710. _settings = new UserConfiguration<KanbanSettings>().Load();
  711. TaskPanels.SelectedItem = _viewmap[_settings.ViewType];
  712. kanbanTypes = new Client<KanbanType>()
  713. .Query(new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false), new Columns<KanbanType>(x => x.ID, x => x.Code, x => x.Description))
  714. .Rows.Select(x => x.ToObject<KanbanType>()).ToArray();
  715. }
  716. public void Shutdown()
  717. {
  718. }
  719. public void Refresh()
  720. {
  721. if (ParentID == Guid.Empty)
  722. {
  723. if (TaskPanels.SelectedItem == TasksPlannerTabItem)
  724. TaskPanels.SelectedItem = _viewmap[KanbanViewType.Status];
  725. if (TasksPlannerTabItem.Visibility == Visibility.Visible)
  726. TasksPlannerTabItem.Visibility = Visibility.Collapsed;
  727. }
  728. else
  729. {
  730. if (TasksPlannerTabItem.Visibility == Visibility.Collapsed)
  731. TasksPlannerTabItem.Visibility = Visibility.Visible;
  732. }
  733. TasksPlannerTabItem.Visibility = ParentID != Guid.Empty ? Visibility.Visible : Visibility.Collapsed;
  734. GetCurrentPanel()?.Refresh(false);
  735. }
  736. public string SectionName => GetCurrentPanel().SectionName;
  737. public TaskPanelProperties Properties { get; set; }
  738. public DataModel DataModel(Selection selection)
  739. {
  740. return GetCurrentPanel().DataModel(selection);
  741. //return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));
  742. }
  743. #endregion
  744. #region CRUD Functionality
  745. private TEntity? DoCreate<TEntity>(Action<TEntity> customise)
  746. where TEntity : Entity, IRemotable, IPersistent, new()
  747. {
  748. var result = new TEntity();
  749. customise?.Invoke(result);
  750. if (DoEdit(new[] { result }, null))
  751. return result;
  752. return null;
  753. }
  754. private readonly Dictionary<Type, IDynamicGrid> _grids = new();
  755. private readonly List<Tuple<Guid, Entity>> _entitycache = new();
  756. private DynamicDataGrid<TEntity> GetGrid<TEntity>() where TEntity : Entity, IRemotable, IPersistent, new()
  757. {
  758. if(!_grids.TryGetValue(typeof(TEntity), out var grid))
  759. {
  760. grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(TEntity)) as DynamicDataGrid<TEntity>)!;
  761. _grids[typeof(TEntity)] = grid;
  762. if (typeof(TEntity) == typeof(Kanban))
  763. {
  764. CustomiseKanbanGrid((grid as DynamicDataGrid<Kanban>)!);
  765. }
  766. }
  767. return (grid as DynamicDataGrid<TEntity>)!;
  768. }
  769. private IEnumerable<TEntity> DoLoad<TEntity>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
  770. where TEntity : Entity, IRemotable, IPersistent, new()
  771. {
  772. var result = new List<TEntity>();
  773. var load = new List<Guid>();
  774. foreach (var model in models)
  775. {
  776. var id = Guid.Parse(model.ID);
  777. var entity = _entitycache.FirstOrDefault(x => Equals(x.Item1, id) && x.Item2 is TEntity) as TEntity;
  778. if (entity is not null)
  779. result.Add(entity);
  780. else
  781. load.Add(id);
  782. }
  783. if (load.Any())
  784. {
  785. var entities = new Client<TEntity>()
  786. .Query(new Filter<TEntity>(x => x.ID).InList(load.ToArray()), columns)
  787. .Rows.Select(x => x.ToObject<TEntity>()).ToList();
  788. foreach (var entity in entities)
  789. _entitycache.Add(new Tuple<Guid, Entity>(entity.ID, entity));
  790. result.AddRange(entities);
  791. }
  792. return result;
  793. }
  794. private IEnumerable<TEntity> DoLoad<TEntityKanban, TEntity, TLink>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
  795. where TEntityKanban : EntityKanban<TEntity, TLink>, new()
  796. where TEntity : Entity, IRemotable, IPersistent, new()
  797. where TLink : IEntityLink<TEntity>, new()
  798. {
  799. var result = DoLoad(models, columns);
  800. if (!result.Any())
  801. foreach (var model in models)
  802. {
  803. var id = Guid.Parse(model.ID);
  804. result = new Client<TEntity>().Load(
  805. new Filter<TEntity>(x => x.ID).InQuery(new Filter<TEntityKanban>(x => x.Kanban.ID).IsEqualTo(id),
  806. x => x.Entity.ID));
  807. foreach (var r in result)
  808. _entitycache.Add(new Tuple<Guid, Entity>(id, r));
  809. }
  810. return result;
  811. }
  812. private void DoCache<TEntity>(Guid kanbanid, TEntity entity) where TEntity : Entity
  813. {
  814. if (!_entitycache.Any(x => Equals(x.Item1, kanbanid) && x.Item2 is TEntity && Equals(x.Item2.ID, entity.ID)))
  815. _entitycache.Add(new Tuple<Guid, Entity>(kanbanid, entity));
  816. }
  817. private bool DoEdit<TEntity>(IEnumerable<TEntity> entities, Action<TEntity>? action = null)
  818. where TEntity : Entity, IRemotable, IPersistent, new()
  819. {
  820. if (entities == null || !entities.Any())
  821. return false;
  822. foreach (var entity in entities)
  823. action?.Invoke(entity);
  824. return GetGrid<TEntity>().EditItems(entities.ToArray());
  825. }
  826. private void DoLink<TEntityKanban, TEntity, TLink>(TaskModel model, Guid entityid)
  827. where TEntityKanban : EntityKanban<TEntity, TLink>, new()
  828. where TEntity : Entity, IRemotable, IPersistent, new()
  829. where TLink : IEntityLink<TEntity>, new()
  830. {
  831. var linktask = Task.Run(() =>
  832. {
  833. var link = new TEntityKanban();
  834. link.Kanban.ID = Guid.Parse(model.ID);
  835. link.Entity.ID = entityid;
  836. new Client<TEntityKanban>().Save(link, "");
  837. });
  838. var kanbantask = Task.Run(() =>
  839. {
  840. var kanban = LoadKanbans(new[] { model }, new Columns<Kanban>(x => x.ID, x => x.Locked)).FirstOrDefault();
  841. if (kanban is not null)
  842. {
  843. kanban.Locked = true;
  844. new Client<Kanban>().Save(kanban, "Locked because of linked " + typeof(TEntity).EntityName().Split('.').Last());
  845. }
  846. });
  847. Task.WaitAll(linktask, kanbantask);
  848. }
  849. private static void DoDelete<TEntity>(IList<TEntity> entities, string auditnote)
  850. where TEntity : Entity, IRemotable, IPersistent, new()
  851. {
  852. new Client<TEntity>().Delete(entities, auditnote);
  853. }
  854. public Kanban? CreateKanban(Action<Kanban> customise)
  855. {
  856. var result = DoCreate<Kanban>(
  857. kanban =>
  858. {
  859. kanban.Title = "New Task";
  860. kanban.Description = "";
  861. kanban.Category = "Open";
  862. kanban.DueDate = DateTime.Today;
  863. kanban.Private = false;
  864. kanban.JobLink.ID = ParentID;
  865. kanban.EmployeeLink.ID = MyID;
  866. kanban.ManagerLink.ID = MyID;
  867. customise?.Invoke(kanban);
  868. });
  869. if (result != null)
  870. DoCache(result.ID, result);
  871. return result;
  872. }
  873. public IEnumerable<Kanban> LoadKanbans(IEnumerable<TaskModel> models, Columns<Kanban> columns)
  874. {
  875. columns.Add(x => x.ID);
  876. columns.Add(x => x.Number);
  877. columns.Add(x => x.Title);
  878. columns.Add(x => x.Notes);
  879. columns.Add(x => x.Summary);
  880. columns.Add(x => x.Completed);
  881. columns.Add(x => x.DueDate);
  882. columns.Add(x => x.ManagerLink.ID);
  883. columns.Add(x => x.EmployeeLink.ID);
  884. return DoLoad(models, columns);
  885. }
  886. public void OnValidateKanban(object sender, Kanban[] items, List<string> errors)
  887. {
  888. if (Properties.RequireTaskTypes && items.Any(x => x.Type.ID == Guid.Empty))
  889. {
  890. errors.Add("[Task Type] may not be blank!");
  891. }
  892. }
  893. public void CustomiseKanbanGrid(DynamicDataGrid<Kanban> grid)
  894. {
  895. grid.OnValidate += OnValidateKanban;
  896. }
  897. public bool EditKanbans(IEnumerable<TaskModel> models, Action<Kanban>? customise = null)
  898. {
  899. var entities = LoadKanbans(models, GetGrid<Kanban>().LoadEditorColumns());
  900. return DoEdit(entities, customise);
  901. }
  902. public void DeleteKanbans(IEnumerable<TaskModel> models, string auditnote)
  903. {
  904. var kanbans = models.Select(x => new Kanban { ID = Guid.Parse(x.ID) }).ToList();
  905. DoDelete(kanbans, auditnote);
  906. }
  907. public Requisition? CreateRequisition(TaskModel model, Action<Requisition>? customise)
  908. {
  909. var result = DoCreate<Requisition>(
  910. requi =>
  911. {
  912. requi.JobLink.ID = ParentID;
  913. customise?.Invoke(requi);
  914. });
  915. if (result != null)
  916. {
  917. var id = Guid.Parse(model.ID);
  918. DoCache(id, result);
  919. DoLink<RequisitionKanban, Requisition, RequisitionLink>(model, result.ID);
  920. }
  921. return result;
  922. }
  923. public bool EditRequisitions(IEnumerable<TaskModel> models, Action<Requisition>? customise = null)
  924. {
  925. var requis = DoLoad<RequisitionKanban, Requisition, RequisitionLink>(models, GetGrid<Requisition>().LoadEditorColumns());
  926. if (requis.Any())
  927. return DoEdit(requis, customise);
  928. return false;
  929. }
  930. public Setout? CreateSetout(TaskModel model, Action<Setout> customise)
  931. {
  932. var result = DoCreate<Setout>(
  933. setout =>
  934. {
  935. setout.JobLink.ID = ParentID;
  936. customise?.Invoke(setout);
  937. });
  938. if (result != null)
  939. {
  940. var id = Guid.Parse(model.ID);
  941. DoCache(id, result);
  942. //DoLink<SetoutKanban, Setout, SetoutLink>(model, result.ID);
  943. }
  944. return result;
  945. }
  946. public bool EditSetouts(IEnumerable<TaskModel> models, Action<Setout>? customise = null)
  947. {
  948. var setouts = DoLoad<SetoutKanban, Setout, SetoutLink>(models, GetGrid<Setout>().LoadEditorColumns());
  949. if (setouts.Any())
  950. return DoEdit(setouts, customise);
  951. return false;
  952. }
  953. public Delivery? CreateDelivery(TaskModel model, Action<Delivery> customise)
  954. {
  955. var result = DoCreate<Delivery>(
  956. delivery =>
  957. {
  958. delivery.Job.ID = ParentID;
  959. customise?.Invoke(delivery);
  960. });
  961. if (result != null)
  962. {
  963. var id = Guid.Parse(model.ID);
  964. DoCache(id, result);
  965. DoLink<DeliveryKanban, Delivery, DeliveryLink>(model, result.ID);
  966. }
  967. return result;
  968. }
  969. public bool EditDeliveries(IEnumerable<TaskModel> models, Action<Delivery>? customise = null)
  970. {
  971. var deliveries = DoLoad<DeliveryKanban, Delivery, DeliveryLink>(models, GetGrid<Delivery>().LoadEditorColumns());
  972. if (deliveries.Any())
  973. return DoEdit(deliveries, customise);
  974. return false;
  975. }
  976. public PurchaseOrder? CreateOrder(TaskModel model, Action<PurchaseOrder> customise)
  977. {
  978. var result = DoCreate<PurchaseOrder>(
  979. order => { customise?.Invoke(order); });
  980. if (result != null)
  981. {
  982. var id = Guid.Parse(model.ID);
  983. DoCache(id, result);
  984. DoLink<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(model, result.ID);
  985. }
  986. return result;
  987. }
  988. public bool EditPurchaseOrders(IEnumerable<TaskModel> models, Action<PurchaseOrder>? customise = null)
  989. {
  990. var orders = DoLoad<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(models, GetGrid<PurchaseOrder>().LoadEditorColumns());
  991. if (orders.Any())
  992. return DoEdit(orders, customise);
  993. return false;
  994. }
  995. #endregion
  996. #region EntityReferences
  997. private static void AddQuery<TEntityKanban, TEntity, TLink>(MultiQuery query, Guid[] taskids)
  998. where TEntityKanban : EntityKanban<TEntity, TLink>, new()
  999. where TEntity : Entity
  1000. where TLink : IEntityLink<TEntity>, new()
  1001. {
  1002. query.Add(
  1003. new Filter<TEntityKanban>(x => x.Kanban.ID).InList(taskids),
  1004. new Columns<TEntityKanban>(x => x.Entity.ID).Add(x => x.Kanban.ID)
  1005. );
  1006. }
  1007. private static Guid[] ExtractIDs<TEntityKanban, TEntity, TLink>(MultiQuery query)
  1008. where TEntityKanban : EntityKanban<TEntity, TLink>, new()
  1009. where TEntity : Entity
  1010. where TLink : IEntityLink<TEntity>, new()
  1011. {
  1012. var lookup = query.Get<TEntityKanban>().ToLookup<TEntityKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
  1013. return query.Get<TEntityKanban>().ExtractValues<TEntityKanban, Guid>(x => x.Entity.ID).ToArray();
  1014. }
  1015. public KanbanReferences[] GetReferences(IEnumerable<TaskModel> models)
  1016. {
  1017. var result = new List<KanbanReferences>();
  1018. var ids = models.Select(x => Guid.Parse(x.ID)).ToArray();
  1019. var query = new MultiQuery();
  1020. AddQuery<RequisitionKanban, Requisition, RequisitionLink>(query, ids);
  1021. AddQuery<SetoutKanban, Setout, SetoutLink>(query, ids);
  1022. AddQuery<DeliveryKanban, Delivery, DeliveryLink>(query, ids);
  1023. AddQuery<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(query, ids);
  1024. query.Query();
  1025. var requis = query.Get<RequisitionKanban>().ToLookup<RequisitionKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
  1026. var setouts = query.Get<SetoutKanban>().ToLookup<SetoutKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
  1027. var deliveries = query.Get<DeliveryKanban>().ToLookup<DeliveryKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
  1028. var orders = query.Get<PurchaseOrderKanban>().ToLookup<PurchaseOrderKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
  1029. foreach (var id in ids)
  1030. {
  1031. var references = new KanbanReferences
  1032. {
  1033. Kanban = id,
  1034. Requisitions = requis.Contains(id) ? requis[id].ToArray() : Array.Empty<Guid>(),
  1035. Setouts = setouts.Contains(id) ? setouts[id].ToArray() : Array.Empty<Guid>(),
  1036. Deliveries = deliveries.Contains(id) ? deliveries[id].ToArray() : Array.Empty<Guid>(),
  1037. Orders = orders.Contains(id) ? orders[id].ToArray() : Array.Empty<Guid>()
  1038. };
  1039. result.Add(references);
  1040. }
  1041. return result.ToArray();
  1042. }
  1043. public bool EditReferences(IEnumerable<TaskModel> models)
  1044. {
  1045. var result = false;
  1046. var refs = GetReferences(models).First();
  1047. if (refs.ReferenceType() == typeof(Requisition))
  1048. result = EditRequisitions(
  1049. models,
  1050. requi =>
  1051. {
  1052. requi.Notes = Utility.ProcessNotes(requi.Notes, requi.Request);
  1053. requi.Request = "";
  1054. }
  1055. );
  1056. else if (refs.ReferenceType() == typeof(Setout))
  1057. result = EditSetouts(models);
  1058. else if (refs.ReferenceType() == typeof(Delivery))
  1059. result = EditDeliveries(models);
  1060. else if (refs.ReferenceType() == typeof(PurchaseOrder))
  1061. result = EditPurchaseOrders(models);
  1062. else
  1063. result = EditKanbans(models);
  1064. return result;
  1065. }
  1066. #endregion
  1067. }
  1068. }