TaskPanel.xaml.cs 51 KB

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