TaskPanel.xaml.cs 51 KB

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