| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.IO;
 
- using System.Linq;
 
- using System.Threading.Tasks;
 
- using System.Windows;
 
- using System.Windows.Controls;
 
- using System.Windows.Controls.Primitives;
 
- using Comal.Classes;
 
- using InABox.Clients;
 
- using InABox.Configuration;
 
- using InABox.Core;
 
- using InABox.DynamicGrid;
 
- using InABox.WPF;
 
- using Syncfusion.Pdf.Graphics;
 
- using Syncfusion.Pdf;
 
- using System.Windows.Data;
 
- using System.Windows.Media;
 
- using System.Drawing;
 
- using System.Globalization;
 
- namespace PRSDesktop
 
- {
 
-     public class TaskPanelProperties : BaseObject, IGlobalConfigurationSettings
 
-     {
 
-         [CheckBoxEditor(ToolTip = "Require that all tasks are given a task type.")]
 
-         public bool RequireTaskTypes { get; set; } = false;
 
-     }
 
-     /// <summary>
 
-     ///     Interaction logic for TaskPanel.xaml
 
-     /// </summary>
 
-     public partial class TaskPanel : UserControl, IPanel<Kanban>, ITaskHost, IJobControl, IPropertiesPanel<TaskPanelProperties>
 
-     {
 
-         private bool _bTabChanging;
 
-         public Guid MyID { get; set; } = CoreUtils.FullGuid;
 
-         private KanbanType[] kanbanTypes = null!; // Initialized in Setup()
 
-         public IList<KanbanType> KanbanTypes => kanbanTypes;
 
-         public TaskPanel()
 
-         {
 
-             InitializeComponent();
 
-             
 
-             foreach (TabItem tab in TaskPanels.Items)
 
-             {
 
-                 var panel = (tab.Content as ITaskControl)!;
 
-                 _viewmap[panel.KanbanView] = tab;
 
-                 panel.Host = this;
 
-             }
 
-             if (MyID == CoreUtils.FullGuid)
 
-             {
 
-                 var row = new Client<Employee>()
 
-                     .Query(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid), new Columns<Employee>(x => x.ID)).Rows
 
-                     .FirstOrDefault();
 
-                 if (row != null)
 
-                     MyID = row.Get<Employee, Guid>(x => x.ID);
 
-             }
 
-         }
 
-         public Guid ParentID { get; set; }
 
-         private void ChangeStatus(ITaskControl control, object o, RoutedEventArgs e, string status)
 
-         {
 
-             if (MessageBox.Show($"Are you sure you want to mark the selected tasks as {status}?", "Confirm Change Status",
 
-                     MessageBoxButton.YesNo) != MessageBoxResult.Yes)
 
-                 return;
 
-             var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
 
-             Progress.ShowModal("Changing Status", progress =>
 
-             {
 
-                 var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Completed, x => x.Category));
 
-                 foreach (var kanban in kanbans)
 
-                 {
 
-                     if(status == "Complete")
 
-                     {
 
-                         kanban.Completed = DateTime.Now;
 
-                     }
 
-                     kanban.Category = status;
 
-                 }
 
-                 new Client<Kanban>().Save(kanbans, $"Kanban Marked as {status}");
 
-             });
 
-             control.Refresh(true);
 
-         }
 
-         private void CompleteTask(ITaskControl control, RoutedEventArgs e, DateTime completed)
 
-         {
 
-             if (MessageBox.Show($"Are you sure you want to complete the selected tasks?", "Confirm Completion",
 
-                     MessageBoxButton.YesNo) != MessageBoxResult.Yes)
 
-                 return;
 
-             var tasks = (((FrameworkElement)e.Source).Tag as IEnumerable<TaskModel>)!;
 
-             Progress.ShowModal("Completing Tasks", progress =>
 
-             {
 
-                 var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Completed, x => x.Category));
 
-                 foreach (var kanban in kanbans)
 
-                 {
 
-                     kanban.Completed = completed;
 
-                     kanban.Category = "Complete";
 
-                 }
 
-                 new Client<Kanban>().Save(kanbans, $"Kanban Marked as Complete");
 
-             });
 
-             control.Refresh(true);
 
-         }
 
-         private void AddChangeStatusButton(ITaskControl control, TaskModel[] models, MenuItem menu, string header, string status)
 
-         {
 
-             var item = new MenuItem
 
-             {
 
-                 Tag = models,
 
-                 Header = header
 
-             };
 
-             item.Click += (o, e) => ChangeStatus(control, o, e, status);
 
-             menu.Items.Add(item);
 
-         }
 
-         public bool CanChangeTasks(IEnumerable<TaskModel> models)
 
-         {
 
-             foreach (var task in models)
 
-             {
 
-                 if (!MyID.Equals(task.ManagerID) && !MyID.Equals(task.EmployeeID))
 
-                 {
 
-                     // If you can change others tasks, IsFullControl is true - but we don't check at the beginning of the function
 
-                     // to save checking security tokens every time.
 
-                     return Security.IsAllowed<CanChangeOthersTasks>();
 
-                 }
 
-             }
 
-             return true;
 
-         }
 
-         /// <summary>
 
-         /// <paramref name="menu"/> should have <see cref="FrameworkElement.Tag"/> set to a <see cref="TaskModel"/>.
 
-         /// </summary>
 
-         /// <param name="control"></param>
 
-         /// <param name="menu"></param>
 
-         public void PopulateMenu(ITaskControl control, ContextMenu menu)
 
-         {
 
-            menu.Items.Clear();
 
-             
 
-             var models = control.SelectedModels((menu.Tag as TaskModel)!).ToArray();
 
-             var references = GetReferences(models);
 
-             var bLinks = references.Any(x => x.ReferenceType() != null);
 
-             var referencetypes = references.Select(x => x.ReferenceType()).Distinct().ToArray();
 
-             var bSingle = models.Length == 1;
 
-             var canChange = CanChangeTasks(models);
 
-             var edit = new MenuItem
 
-             {
 
-                 Tag = models,
 
-                 Header = referencetypes.SingleOrDefault() == typeof(Requisition)
 
-                     ? "Edit Requisition Details"
 
-                     : referencetypes.SingleOrDefault() == typeof(Setout)
 
-                         ? "Edit Setout Details"
 
-                         : referencetypes.SingleOrDefault() == typeof(Delivery)
 
-                             ? "Edit Delivery Details"
 
-                             : referencetypes.SingleOrDefault() == typeof(PurchaseOrder)
 
-                                 ? "Edit Order Details"
 
-                                 : "Edit Task" + (bSingle ? "" : "s")
 
-             };
 
-             edit.Click += (o, e) =>
 
-             {
 
-                 var tasks = (((MenuItem)e.Source).Tag as IEnumerable<TaskModel>)!;
 
-                 if (EditReferences(tasks))
 
-                     control.Refresh(true);
 
-                 e.Handled = true;
 
-             };
 
-             edit.IsEnabled = referencetypes.Length == 1;
 
-             menu.Items.Add(edit);
 
-             if (!bLinks && models.Length == 1)
 
-             {
 
-                 var digitalForms = new MenuItem { Header = "Digital Forms" };
 
-                 var model = models.First();
 
-                 Guid kanbanID = Guid.Parse(model.ID);
 
-                 DynamicGridUtils.PopulateFormMenu<KanbanForm, Kanban, KanbanLink>(
 
-                     digitalForms,
 
-                     kanbanID,
 
-                     () => new Client<Kanban>().Load(new Filter<Kanban>(x => x.ID).IsEqualTo(kanbanID)).First(),
 
-                     model.EmployeeID == MyID);
 
-                 menu.Items.Add(digitalForms);
 
-             }
 
-             if (!models.Any(x => !x.CompletedDate.IsEmpty()) && !bLinks)
 
-             {
 
-                 menu.Items.Add(new Separator());
 
-                 var job = new MenuItem
 
-                 {
 
-                     Tag = models,
 
-                     Header = "Link to Job"
 
-                 };
 
-                 job.SubmenuOpened += (o, e) => CreateJobSubMenu(control, job, models);
 
-                 menu.Items.Add(job);
 
-                 if (bSingle)
 
-                 {
 
-                     menu.AddItem("Create Setout from Task", null, models.First(), task =>
 
-                     {
 
-                         var jobID = task.JobID;
 
-                         if (task.JobID.Equals(Guid.Empty))
 
-                         {
 
-                             jobID = ParentID;
 
-                         }
 
-                         if (MessageBox.Show("This will convert this task into a Setout.\n\nDo you wish to continue?", "Confirmation", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
 
-                             return;
 
-                         ManufacturingTemplate? template = new Client<ManufacturingTemplate>()
 
-                             .Load(new Filter<ManufacturingTemplate>(x => x.Code).IsEqualTo("PRS")).FirstOrDefault();
 
-                         if (template == null)
 
-                         {
 
-                             MessageBox.Show("[Pressing] Template does not exist!");
 
-                             return;
 
-                         }
 
-                         string? setoutNumber = null;
 
-                         Kanban? kanban = null;
 
-                         ManufacturingTemplateStage[] tstages = Array.Empty<ManufacturingTemplateStage>();
 
-                         Progress.ShowModal("Creating Setout", (progress) =>
 
-                         {
 
-                             var kanbanFilter = new Filter<Kanban>(x => x.ID).IsEqualTo(task.ID);
 
-                             var tables = Client.QueryMultiple(new Dictionary<string, IQueryDef>
 
-                             {
 
-                                 { "ManufacturingTemplateStage", new QueryDef<ManufacturingTemplateStage>(
 
-                                     new Filter<ManufacturingTemplateStage>(x => x.Template.ID).IsEqualTo(template.ID),
 
-                                     null,
 
-                                     new SortOrder<ManufacturingTemplateStage>(x => x.Sequence)) },
 
-                                 { "Kanban", new QueryDef<Kanban>(
 
-                                     kanbanFilter,
 
-                                     null,
 
-                                     null) },
 
-                                 { "Setout", new QueryDef<Setout>(
 
-                                     new Filter<Setout>(x => x.JobLink.ID)
 
-                                         .InQuery(new SubQuery<Kanban>(kanbanFilter, new Column<Kanban>(x => x.JobLink.ID))),
 
-                                     new Columns<Setout>(x => x.JobLink.JobNumber, x => x.Number),
 
-                                     null) }
 
-                             });
 
-                             tstages = tables["ManufacturingTemplateStage"].Rows
 
-                                .Select(x => x.ToObject<ManufacturingTemplateStage>()).ToArray();
 
-                             kanban = tables["Kanban"].Rows.FirstOrDefault()?.ToObject<Kanban>();
 
-                             if (kanban == null)
 
-                             {
 
-                                 MessageBox.Show("Task does not exist!");
 
-                                 return;
 
-                             }
 
-                             progress.Report("Creating Setouts");
 
-                             CoreTable setouts = tables["Setout"];
 
-                             int ireq = 0;
 
-                             string sreq = "";
 
-                             while (true)
 
-                             {
 
-                                 ireq++;
 
-                                 sreq = string.Format("{0}-{1:yyMMdd}-{2}", kanban.JobLink.JobNumber, DateTime.Now, ireq);
 
-                                 if (!setouts.Rows.Any(r => sreq.Equals(r.Get<Setout, String>(c => c.Number))))
 
-                                     break;
 
-                             }
 
-                             setoutNumber = sreq;
 
-                         });
 
-                         if (setoutNumber == null || kanban == null)
 
-                         {
 
-                             return;
 
-                         }
 
-                         var result = CreateSetout(
 
-                             task,
 
-                             s =>
 
-                             {
 
-                                 s.Number = setoutNumber;
 
-                                 s.JobLink.ID = jobID;
 
-                                 var notes = kanban.Notes.ToList();
 
-                                 var description = kanban.Summary;
 
-                                 if (string.IsNullOrWhiteSpace(description))
 
-                                 {
 
-                                     description = CoreUtils.StripHTML(kanban.Description);
 
-                                 }
 
-                                 if (!string.IsNullOrWhiteSpace(description))
 
-                                 {
 
-                                     notes.Insert(0, description);
 
-                                 }
 
-                                 s.Description = string.Join("\n==========================================\n", notes);
 
-                             }
 
-                         );
 
-                         if (result != null)
 
-                         {
 
-                             Progress.ShowModal("Creating Manufacturing Packet", progress =>
 
-                             {
 
-                                 ManufacturingPacket packet = new ManufacturingPacket()
 
-                                 {
 
-                                     Serial = template.Code,
 
-                                     Title = kanban.Title,
 
-                                     Quantity = 1,
 
-                                     BarcodeQty = 1,
 
-                                     DueDate = kanban.DueDate
 
-                                 };
 
-                                 packet.ManufacturingTemplateLink.ID = template.ID;
 
-                                 packet.ManufacturingTemplateLink.Code = template.Code;
 
-                                 packet.ManufacturingTemplateLink.Factory.ID = template.Factory.ID;
 
-                                 packet.SetoutLink.ID = result.ID;
 
-                                 new Client<ManufacturingPacket>().Save(packet, "Created from Task");
 
-                                 DoLink<ManufacturingPacketKanban, ManufacturingPacket, ManufacturingPacketLink>(task, packet.ID);
 
-                                 List<ManufacturingPacketStage> pstages = new List<ManufacturingPacketStage>();
 
-                                 foreach (var tstage in tstages)
 
-                                 {
 
-                                     var pstage = new ManufacturingPacketStage()
 
-                                     {
 
-                                         Time = tstage.Time,
 
-                                         Sequence = tstage.Sequence,
 
-                                         SequenceType = tstage.SequenceType,
 
-                                         Started = DateTime.MinValue,
 
-                                         PercentageComplete = 0.0F,
 
-                                         Completed = DateTime.MinValue,
 
-                                         QualityChecks = tstage.QualityChecks,
 
-                                         QualityStatus = QualityStatus.NotChecked,
 
-                                         QualityNotes = "",
 
-                                     };
 
-                                     pstage.Parent.ID = packet.ID;
 
-                                     pstage.ManufacturingSectionLink.ID = tstage.Section.ID;
 
-                                     pstage.ManufacturingSectionLink.Name = tstage.Section.Name;
 
-                                     pstages.Add(pstage);
 
-                                 }
 
-                                 new Client<ManufacturingPacketStage>().Save(pstages, "Created from Task", (_, __) => { });
 
-                                 progress.Report("Processing Documents");
 
-                                 List<SetoutDocument> _setoutdocuments = new List<SetoutDocument>();
 
-                                 List<KanbanDocument> _kanbandocuments = new List<KanbanDocument>();
 
-                                 KanbanDocument[] docrefs = new Client<KanbanDocument>()
 
-                                     .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 
-                                 foreach (var docref in docrefs)
 
-                                 {
 
-                                     // Convert the document to a PDF
 
-                                     var docid = ProcessKanbanDocument(docref);
 
-                                     var newdoc = new SetoutDocument();
 
-                                     newdoc.EntityLink.ID = result.ID;
 
-                                     newdoc.DocumentLink.ID = docid;
 
-                                     _setoutdocuments.Add(newdoc);
 
-                                     if (docid != docref.DocumentLink.ID)
 
-                                     {
 
-                                         docref.DocumentLink.ID = docid;
 
-                                         _kanbandocuments.Add(docref);
 
-                                     }
 
-                                 }
 
-                                 new Client<SetoutDocument>().Save(_setoutdocuments, "Converted from Task", (_, __) => { });
 
-                                 new Client<KanbanDocument>().Save(_kanbandocuments, "Converted to PDF", (_, __) => { });
 
-                                 progress.Report("Updating Task");
 
-                                 kanban.Title = kanban.Title + " (" + result.Number + ")";
 
-                                 new Client<Kanban>().Save(kanban, "Converting Kanban to Setout");
 
-                             });
 
-                             control.Refresh(true);
 
-                         }
 
-                     });
 
-                     menu.AddItem("Create Requisition from Task", null, models, tasks =>
 
-                     {
 
-                         var taskModel = tasks.First();
 
-                         var jobID = taskModel.JobID;
 
-                         if (taskModel.JobID.Equals(Guid.Empty))
 
-                         {
 
-                             jobID = ParentID;
 
-                         }
 
-                         var kanbanTable = new Client<Kanban>().Query(new Filter<Kanban>(x => x.ID).IsEqualTo(taskModel.ID));
 
-                         var kanban = kanbanTable.Rows.First().ToObject<Kanban>();
 
-                         var result = CreateRequisition(
 
-                             taskModel,
 
-                             r =>
 
-                             {
 
-                                 r.RequestedBy.ID = kanban.ManagerLink.ID;
 
-                                 r.Employee.ID = Guid.Empty;
 
-                                 r.Title = kanban.Title;
 
-                                 r.Request = string.IsNullOrWhiteSpace(kanban.Summary)
 
-                                     ? String.IsNullOrWhiteSpace(kanban.Description)
 
-                                         ? String.Join("\n", kanban.Notes)
 
-                                         : CoreUtils.StripHTML(kanban.Description)
 
-                                     : kanban.Summary;
 
-                                 r.Notes = kanban.Notes;
 
-                                 r.Due = kanban.DueDate;
 
-                                 r.JobLink.ID = jobID;
 
-                             }
 
-                         );
 
-                         if (result != null)
 
-                         {
 
-                             Progress.ShowModal("Updating Documents", progress =>
 
-                             {
 
-                                 progress.Report("Updating Documents");
 
-                                 List<RequisitionDocument> requiDocuments = new();
 
-                                 KanbanDocument[] kanbanDocuments = new Client<KanbanDocument>()
 
-                                     .Load(new Filter<KanbanDocument>(x => x.EntityLink.ID).IsEqualTo(kanban.ID));
 
-                                 foreach (var document in kanbanDocuments)
 
-                                 {
 
-                                     var newdoc = new RequisitionDocument();
 
-                                     newdoc.EntityLink.ID = result.ID;
 
-                                     newdoc.DocumentLink.ID = document.DocumentLink.ID;
 
-                                     requiDocuments.Add(newdoc);
 
-                                 }
 
-                                 new Client<RequisitionDocument>().Save(requiDocuments, "Converted from Task", (_, __) => { });
 
-                                 /*RequisitionKanban link = new();
 
-                                 link.Entity.ID = result.ID;
 
-                                 link.Kanban.ID = kanban.ID;
 
-                                 new Client<RequisitionKanban>().Save(link, "Converting Task -> Requisition", (_, __) => { });*/
 
-                                 progress.Report("Updating Task");
 
-                                 kanban.Category = "Open";
 
-                                 kanban.Completed = DateTime.MinValue;
 
-                                 kanban.Title += $" (Requi #{result.Number})";
 
-                                 new Client<Kanban>().Save(kanban, "Converted to Requisition", (_, __) => { });
 
-                             });
 
-                             MessageBox.Show(String.Format("Created Requisition {0}", result.Number));
 
-                             control.Refresh(true);
 
-                         }
 
-                     });
 
-                     menu.AddItem("Create Delivery from Task", null, models, tasks =>
 
-                     {
 
-                         var result = CreateDelivery(
 
-                             tasks.First(),
 
-                             d =>
 
-                             {
 
-                                 // Post-Process Requi Here
 
-                             }
 
-                         );
 
-                         if (result != null)
 
-                             control.Refresh(true);
 
-                     });
 
-                     menu.AddItem("Create Purchase Order from Task", null, models, tasks =>
 
-                     {
 
-                         var result = CreateOrder(
 
-                             tasks.First(),
 
-                             p =>
 
-                             {
 
-                                 // Post-Process Requi Here
 
-                             }
 
-                         );
 
-                         if (result != null)
 
-                             control.Refresh(true);
 
-                     });
 
-                 }
 
-             }
 
-             if (!bLinks && canChange)
 
-             {
 
-                 menu.Items.Add(new Separator());
 
-                 var changeStatus = new MenuItem { Header = "Change Status" };
 
-                 AddChangeStatusButton(control, models, changeStatus, "Open", "Open");
 
-                 AddChangeStatusButton(control, models, changeStatus, "In Progress", "In Progress");
 
-                 AddChangeStatusButton(control, models, changeStatus, "Waiting", "Waiting");
 
-                 if (models.Any(x => x.CompletedDate.IsEmpty()))
 
-                 {
 
-                     var complete = new MenuItem
 
-                     {
 
-                         Tag = models,
 
-                         Header = models.Length > 1 ? "Complete Tasks" : "Complete Task"
 
-                     };
 
-                     complete.Click += (o, e) =>
 
-                     {
 
-                         CompleteTask(control, e, DateTime.Now);
 
-                     };
 
-                     menu.Items.Add(complete);
 
-                     if (Security.IsAllowed<CanSetKanbanCompletedDate>())
 
-                     {
 
-                         var completeDate = new MenuItem
 
-                         {
 
-                             Tag = models,
 
-                             Header = "Set Completed Date"
 
-                         };
 
-                         var dateItem = new MenuItem();
 
-                         var dateCalendar = new System.Windows.Controls.Calendar { SelectedDate = DateTime.MinValue };
 
-                         dateCalendar.Tag = models;
 
-                         dateCalendar.SelectedDatesChanged += (o, e) =>
 
-                         {
 
-                             if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 
-                             menu.IsOpen = false;
 
-                             var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 
-                             CompleteTask(control, e, selectedDate);
 
-                         };
 
-                         dateItem.Header = dateCalendar;
 
-                         dateItem.Style = Resources["calendarItem"] as Style;
 
-                         completeDate.Items.Add(dateItem);
 
-                         menu.Items.Add(completeDate);
 
-                     }
 
-                 }
 
-                 else
 
-                 {
 
-                     menu.AddItem(models.Length > 1 ? "Archive Tasks" : "Archive Task", null, models, tasks =>
 
-                     {
 
-                         if (MessageBox.Show("Are you sure you want to remove the selected tasks from the list?", "Confirm removal",
 
-                                 MessageBoxButton.YesNo) != MessageBoxResult.Yes)
 
-                             return;
 
-                         Progress.ShowModal("Closing Kanbans", progress =>
 
-                         {
 
-                             var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.Closed));
 
-                             foreach (var kanban in kanbans)
 
-                                 kanban.Closed = DateTime.Now;
 
-                             new Client<Kanban>().Save(kanbans, "Kanban Marked as Closed");
 
-                         });
 
-                         control.Refresh(true);
 
-                     });
 
-                 }
 
-                 menu.Items.Add(changeStatus);
 
-                 var changeType = new MenuItem { Header = "Change Task Type", Tag = models };
 
-                 foreach(var type in KanbanTypes)
 
-                 {
 
-                     changeType.AddItem($"{type.Code}: {type.Description}", null, type, type =>
 
-                     {
 
-                         Progress.ShowModal("Changing Task Type", progress =>
 
-                         {
 
-                             var kanbans = LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.Type.ID));
 
-                             foreach (var kanban in kanbans)
 
-                             {
 
-                                 kanban.Type.ID = type.ID;
 
-                             }
 
-                             new Client<Kanban>().Save(kanbans, $"Kanban Task Type changed to {type}");
 
-                         });
 
-                         control.Refresh(true);
 
-                     });
 
-                 }
 
-                 menu.Items.Add(changeType);
 
-                 var changeDueDate = new MenuItem { Header = "Change Due Date" };
 
-                 var calendarItem = new MenuItem();
 
-                 var calendar = new System.Windows.Controls.Calendar { SelectedDate = models.Length == 1 ? models[0].DueDate : DateTime.Today };
 
-                 calendar.Tag = models;
 
-                 calendar.SelectedDatesChanged += (o, e) =>
 
-                 {
 
-                     if (e.Source is not System.Windows.Controls.Calendar calendar) return;
 
-                     var selectedDate = calendar.SelectedDate ?? DateTime.Now;
 
-                     var models = (calendar.Tag as IList<TaskModel>)!;
 
-                     Progress.ShowModal("Changing Due Date", progress =>
 
-                     {
 
-                         var kanbans = LoadKanbans(models, new Columns<Kanban>(x => x.ID, x => x.DueDate));
 
-                         foreach (var kanban in kanbans)
 
-                         {
 
-                             kanban.DueDate = selectedDate;
 
-                         }
 
-                         new Client<Kanban>().Save(kanbans, $"Kanban Due Date changed to {selectedDate:dd MMM yyyy}");
 
-                     });
 
-                     control.Refresh(true);
 
-                     menu.IsOpen = false;
 
-                 };
 
-                 calendarItem.Header = calendar;
 
-                 calendarItem.Style = Resources["calendarItem"] as Style;
 
-                 changeDueDate.Items.Add(calendarItem);
 
-                 menu.Items.Add(changeDueDate);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Takes a <see cref="KanbanDocument"/>, and if it is a .txt or an image (".png", ".jpg", ".jpeg" or ".bmp"), converts to a PDF
 
-         /// with the content of the document, saving a new document with extension changed to ".pdf".
 
-         /// </summary>
 
-         /// <param name="docref">The original document.</param>
 
-         /// <returns>
 
-         /// The ID of the new <see cref="Document"/> or,
 
-         /// if not one of the given types, the original document ID.
 
-         /// </returns>
 
-         private static Guid ProcessKanbanDocument(KanbanDocument docref)
 
-         {
 
-             var result = docref.DocumentLink.ID;
 
-             var ext = System.IO.Path.GetExtension(docref.DocumentLink.FileName).ToLower();
 
-             if (ext.EndsWith("txt"))
 
-             {
 
-                 var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 
-                 if (doc is null)
 
-                 {
 
-                     Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 
-                     return docref.DocumentLink.ID;
 
-                 }
 
-                 PdfDocument pdf = new PdfDocument();
 
-                 PdfPage page = pdf.Pages.Add();
 
-                 PdfGraphics graphics = page.Graphics;
 
-                 PdfFont font = new PdfStandardFont(PdfFontFamily.Courier, 12);
 
-                 String text = System.Text.Encoding.UTF8.GetString(doc.Data);
 
-                 graphics.DrawString(text, font, PdfBrushes.Black, new PointF(0, 0));
 
-                 MemoryStream ms = new MemoryStream();
 
-                 pdf.Save(ms);
 
-                 pdf.Close(true);
 
-                 byte[] data = ms.ToArray();
 
-                 var newdoc = new Document()
 
-                 {
 
-                     Data = data,
 
-                     FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 
-                     CRC = CoreUtils.CalculateCRC(data),
 
-                     TimeStamp = DateTime.Now,
 
-                 };
 
-                 new Client<Document>().Save(newdoc, "Converted from Text");
 
-                 return newdoc.ID;
 
-             }
 
-             else if (ext.EndsWith("png") || ext.EndsWith("bmp") || ext.EndsWith("jpg") || ext.EndsWith("jpeg"))
 
-             {
 
-                 var doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(docref.DocumentLink.ID)).FirstOrDefault();
 
-                 if (doc is null)
 
-                 {
 
-                     Logger.Send(LogType.Error, "", $"Document {docref.DocumentLink.ID} does not exist!");
 
-                     return docref.DocumentLink.ID;
 
-                 }
 
-                 PdfBitmap image = new PdfBitmap(new MemoryStream(doc.Data));
 
-                 PdfDocument pdf = new PdfDocument();
 
-                 pdf.PageSettings.Orientation = image.Height > image.Width ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
 
-                 pdf.PageSettings.Size = new SizeF(image.Width, image.Height);
 
-                 PdfPage page = pdf.Pages.Add();
 
-                 PdfGraphics graphics = page.Graphics;
 
-                 graphics.DrawImage(image, 0.0F, 0.0F);
 
-                 MemoryStream ms = new MemoryStream();
 
-                 pdf.Save(ms);
 
-                 pdf.Close(true);
 
-                 byte[] data = ms.ToArray();
 
-                 var newdoc = new Document()
 
-                 {
 
-                     Data = data,
 
-                     FileName = System.IO.Path.ChangeExtension(docref.DocumentLink.FileName, "pdf"),
 
-                     CRC = CoreUtils.CalculateCRC(data),
 
-                     TimeStamp = DateTime.Now,
 
-                 };
 
-                 new Client<Document>().Save(newdoc, "Converted from Image");
 
-                 return newdoc.ID;
 
-             }
 
-             return result;
 
-         }
 
-         private void TaskPanels_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
-         {
 
-             if (!IsReady)
 
-                 return;
 
-             if (e.Source is not TabControl)
 
-                 return;
 
-             if (_bTabChanging)
 
-                 return;
 
-             try
 
-             {
 
-                 _bTabChanging = true;
 
-                 var panel = GetCurrentPanel();
 
-                 if(panel is not null)
 
-                 {
 
-                     Settings.ViewType = panel.KanbanView;
 
-                     new UserConfiguration<KanbanSettings>().Save(Settings);
 
-                     panel.Refresh(false);
 
-                 }
 
-             }
 
-             finally
 
-             {
 
-                 _bTabChanging = false;
 
-             }
 
-         }
 
-         private void CreateJobSubMenu(ITaskControl control, MenuItem job, IEnumerable<TaskModel> tasks)
 
-         {
 
-             job.Items.Clear();
 
-             job.Items.Add(new MenuItem { Header = "Loading...", IsEnabled = false });
 
-             using (new WaitCursor())
 
-             {
 
-                 job.Items.Clear();
 
-                 var jobs = new Client<Job>().Query(
 
-                     LookupFactory.DefineFilter<Job>(),
 
-                     LookupFactory.DefineColumns<Job>(),
 
-                     LookupFactory.DefineSort<Job>()
 
-                 );
 
-                 foreach (var row in jobs.Rows)
 
-                 {
 
-                     var jobNumber = row.Get<Job, string>(x => x.JobNumber);
 
-                     var jobName = row.Get<Job, string>(x => x.Name);
 
-                     job.AddItem($"{jobNumber}: {jobName}", null, tasks, tasks =>
 
-                     {
 
-                         using (new WaitCursor())
 
-                         {
 
-                             var kanbans = LoadKanbans(tasks, new Columns<Kanban>(x => x.ID, x => x.JobLink.ID));
 
-                             foreach (var kanban in kanbans)
 
-                                 kanban.JobLink.ID = row.Get<Job, Guid>(x => x.ID);
 
-                             new Client<Kanban>().Save(kanbans, "Updated Job Number");
 
-                             control.Refresh(false);
 
-                         }
 
-                     });
 
-                 }
 
-             }
 
-         }
 
-         #region Get/Save Settings
 
-         private KanbanSettings? _settings;
 
-         public KanbanSettings Settings
 
-         {
 
-             get
 
-             {
 
-                 _settings ??= new UserConfiguration<KanbanSettings>().Load();
 
-                 return _settings;
 
-             }
 
-         }
 
-         public void SaveSettings()
 
-         {
 
-             if(_settings != null)
 
-                 new UserConfiguration<KanbanSettings>().Save(_settings);
 
-         }
 
-         #endregion
 
-         #region IPanel Stuff
 
-         public event DataModelUpdateEvent? OnUpdateDataModel;
 
-         public bool IsReady { get; set; }
 
-         public void CreateToolbarButtons(IPanelHost host)
 
-         {
 
-             host.CreatePanelAction(
 
-                 new PanelAction
 
-                 {
 
-                     Caption = "New Task",
 
-                     OnExecute = a => {
 
-                         if(CreateKanban(k => { }) != null)
 
-                         {
 
-                             Refresh();
 
-                         }
 
-                     },
 
-                     Image = PRSDesktop.Resources.add
 
-                 }
 
-             );
 
-         }
 
-         public Dictionary<string, object[]> Selected()
 
-         {
 
-             return new Dictionary<string, object[]>();
 
-         }
 
-         public void Heartbeat(TimeSpan time)
 
-         {
 
-         }
 
-         private readonly Dictionary<KanbanView, TabItem> _viewmap = new();
 
-         private readonly List<ITaskControl> _initialized = new();
 
-         private ITaskControl 
 
-             GetCurrentPanel()
 
-         {
 
-             var result = (TaskPanels.SelectedContent as ITaskControl)!;
 
-             if (result == null)
 
-                 result = (TaskPanels.Items[0] as DynamicTabItem)?.Content as ITaskControl;
 
-             try
 
-             {
 
-                 //if (result != null)
 
-                 if (!_initialized.Contains(result))
 
-                 {
 
-                     result.Setup();
 
-                     result.IsReady = true;
 
-                     _initialized.Add(result);
 
-                 }
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", $"Error in TaskPanel.GetCurrentPanel: {CoreUtils.FormatException(e)}");
 
-             }
 
-             return result;
 
-         }
 
-         public void Setup()
 
-         {
 
-             _settings = new UserConfiguration<KanbanSettings>().Load();
 
-             TaskPanels.SelectedItem = _viewmap[_settings.ViewType];
 
-             kanbanTypes = new Client<KanbanType>()
 
-                 .Query(new Filter<KanbanType>(x => x.Hidden).IsEqualTo(false), new Columns<KanbanType>(x => x.ID, x => x.Code, x => x.Description))
 
-                 .Rows.Select(x => x.ToObject<KanbanType>()).ToArray();
 
-         }
 
-         public void Shutdown()
 
-         {
 
-         }
 
-         public void Refresh()
 
-         {
 
-             if (ParentID == Guid.Empty)
 
-             {
 
-                 if (TaskPanels.SelectedItem == TasksPlannerTabItem)
 
-                     TaskPanels.SelectedItem = _viewmap[KanbanView.Status];
 
-                 if (TasksPlannerTabItem.Visibility == Visibility.Visible)
 
-                     TasksPlannerTabItem.Visibility = Visibility.Collapsed;
 
-             }
 
-             else
 
-             {
 
-                 if (TasksPlannerTabItem.Visibility == Visibility.Collapsed)
 
-                     TasksPlannerTabItem.Visibility = Visibility.Visible;
 
-             }
 
-             TasksPlannerTabItem.Visibility = ParentID != Guid.Empty ? Visibility.Visible : Visibility.Collapsed;
 
-             GetCurrentPanel()?.Refresh(false);
 
-         }
 
-         public string SectionName => GetCurrentPanel().SectionName;
 
-         public TaskPanelProperties Properties { get; set; }
 
-         public DataModel DataModel(Selection selection)
 
-         {
 
-             return GetCurrentPanel().DataModel(selection);
 
-             //return new AutoDataModel<Kanban>(new Filter<Kanban>(x => x.ID).IsEqualTo(Guid.Empty));
 
-         }
 
-         #endregion
 
-         #region CRUD Functionality
 
-         private TEntity? DoCreate<TEntity>(Action<TEntity> customise)
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-         {
 
-             var result = new TEntity();
 
-             customise?.Invoke(result);
 
-             if (DoEdit(new[] { result }, null))
 
-                 return result;
 
-             return null;
 
-         }
 
-         private readonly Dictionary<Type, IDynamicGrid> _grids = new();
 
-         private readonly List<Tuple<Guid, Entity>> _entitycache = new();
 
-         private DynamicDataGrid<TEntity> GetGrid<TEntity>() where TEntity : Entity, IRemotable, IPersistent, new()
 
-         {
 
-             if(!_grids.TryGetValue(typeof(TEntity), out var grid))
 
-             {
 
-                 grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(TEntity)) as DynamicDataGrid<TEntity>)!;
 
-                 _grids[typeof(TEntity)] = grid;
 
-                 if (typeof(TEntity) == typeof(Kanban))
 
-                 {
 
-                     CustomiseKanbanGrid((grid as DynamicDataGrid<Kanban>)!);
 
-                 }
 
-             }
 
-             return (grid as DynamicDataGrid<TEntity>)!;
 
-         }
 
-         private IEnumerable<TEntity> DoLoad<TEntity>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-         {
 
-             var result = new List<TEntity>();
 
-             var load = new List<Guid>();
 
-             foreach (var model in models)
 
-             {
 
-                 var id = Guid.Parse(model.ID);
 
-                 var entity = _entitycache.FirstOrDefault(x => Equals(x.Item1, id) && x.Item2 is TEntity) as TEntity;
 
-                 if (entity is not null)
 
-                     result.Add(entity);
 
-                 else
 
-                     load.Add(id);
 
-             }
 
-             if (load.Any())
 
-             {
 
-                 var entities = new Client<TEntity>()
 
-                     .Query(new Filter<TEntity>(x => x.ID).InList(load.ToArray()), columns)
 
-                     .Rows.Select(x => x.ToObject<TEntity>()).ToList();
 
-                 foreach (var entity in entities)
 
-                     _entitycache.Add(new Tuple<Guid, Entity>(entity.ID, entity));
 
-                 result.AddRange(entities);
 
-             }
 
-             return result;
 
-         }
 
-         private IEnumerable<TEntity> DoLoad<TEntityKanban, TEntity, TLink>(IEnumerable<TaskModel> models, Columns<TEntity> columns)
 
-             where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-             where TLink : IEntityLink<TEntity>, new()
 
-         {
 
-             var result = DoLoad(models, columns);
 
-             if (!result.Any())
 
-                 foreach (var model in models)
 
-                 {
 
-                     var id = Guid.Parse(model.ID);
 
-                     result = new Client<TEntity>().Load(
 
-                         new Filter<TEntity>(x => x.ID).InQuery(new Filter<TEntityKanban>(x => x.Kanban.ID).IsEqualTo(id),
 
-                             x => x.Entity.ID));
 
-                     foreach (var r in result)
 
-                         _entitycache.Add(new Tuple<Guid, Entity>(id, r));
 
-                 }
 
-             return result;
 
-         }
 
-         private void DoCache<TEntity>(Guid kanbanid, TEntity entity) where TEntity : Entity
 
-         {
 
-             if (!_entitycache.Any(x => Equals(x.Item1, kanbanid) && x.Item2 is TEntity && Equals(x.Item2.ID, entity.ID)))
 
-                 _entitycache.Add(new Tuple<Guid, Entity>(kanbanid, entity));
 
-         }
 
-         private bool DoEdit<TEntity>(IEnumerable<TEntity> entities, Action<TEntity>? action = null)
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-         {
 
-             if (entities == null || !entities.Any())
 
-                 return false;
 
-             foreach (var entity in entities)
 
-                 action?.Invoke(entity);
 
-             return GetGrid<TEntity>().EditItems(entities.ToArray());
 
-         }
 
-         private void DoLink<TEntityKanban, TEntity, TLink>(TaskModel model, Guid entityid)
 
-             where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-             where TLink : IEntityLink<TEntity>, new()
 
-         {
 
-             var linktask = Task.Run(() =>
 
-             {
 
-                 var link = new TEntityKanban();
 
-                 link.Kanban.ID = Guid.Parse(model.ID);
 
-                 link.Entity.ID = entityid;
 
-                 new Client<TEntityKanban>().Save(link, "");
 
-             });
 
-             var kanbantask = Task.Run(() =>
 
-             {
 
-                 var kanban = LoadKanbans(new[] { model }, new Columns<Kanban>(x => x.ID, x => x.Locked)).FirstOrDefault();
 
-                 if (kanban is not null)
 
-                 {
 
-                     kanban.Locked = true;
 
-                     new Client<Kanban>().Save(kanban, "Locked because of linked " + typeof(TEntity).EntityName().Split('.').Last());
 
-                 }
 
-             });
 
-             Task.WaitAll(linktask, kanbantask);
 
-         }
 
-         private static void DoDelete<TEntity>(IList<TEntity> entities, string auditnote)
 
-             where TEntity : Entity, IRemotable, IPersistent, new()
 
-         {
 
-             new Client<TEntity>().Delete(entities, auditnote);
 
-         }
 
-         public Kanban? CreateKanban(Action<Kanban> customise)
 
-         {
 
-             var result = DoCreate<Kanban>(
 
-                 kanban =>
 
-                 {
 
-                     kanban.Title = "New Task";
 
-                     kanban.Description = "";
 
-                     kanban.Category = "Open";
 
-                     kanban.DueDate = DateTime.Today;
 
-                     kanban.Private = false;
 
-                     kanban.JobLink.ID = ParentID;
 
-                     kanban.EmployeeLink.ID = MyID;
 
-                     kanban.ManagerLink.ID = MyID;
 
-                     customise?.Invoke(kanban);
 
-                 });
 
-             if (result != null)
 
-                 DoCache(result.ID, result);
 
-             return result;
 
-         }
 
-         public IEnumerable<Kanban> LoadKanbans(IEnumerable<TaskModel> models, Columns<Kanban> columns)
 
-         {
 
-             columns.Add(x => x.ID);
 
-             columns.Add(x => x.Number);
 
-             columns.Add(x => x.Title);
 
-             columns.Add(x => x.Notes);
 
-             columns.Add(x => x.Summary);
 
-             columns.Add(x => x.Completed);
 
-             columns.Add(x => x.DueDate);
 
-             columns.Add(x => x.ManagerLink.ID);
 
-             columns.Add(x => x.EmployeeLink.ID);
 
-             return DoLoad(models, columns);
 
-         }
 
-         public void OnValidateKanban(object sender, Kanban[] items, List<string> errors)
 
-         {
 
-             if (Properties.RequireTaskTypes && items.Any(x => x.Type.ID == Guid.Empty))
 
-             {
 
-                 errors.Add("[Task Type] may not be blank!");
 
-             }
 
-         }
 
-         public void CustomiseKanbanGrid(DynamicDataGrid<Kanban> grid)
 
-         {
 
-             grid.OnValidate += OnValidateKanban;
 
-         }
 
-         public bool EditKanbans(IEnumerable<TaskModel> models, Action<Kanban>? customise = null)
 
-         {
 
-             var entities = LoadKanbans(models, GetGrid<Kanban>().LoadEditorColumns());
 
-             return DoEdit(entities, customise);
 
-         }
 
-         public void DeleteKanbans(IEnumerable<TaskModel> models, string auditnote)
 
-         {
 
-             var kanbans = models.Select(x => new Kanban { ID = Guid.Parse(x.ID) }).ToList();
 
-             DoDelete(kanbans, auditnote);
 
-         }
 
-         public Requisition? CreateRequisition(TaskModel model, Action<Requisition>? customise)
 
-         {
 
-             var result = DoCreate<Requisition>(
 
-                 requi =>
 
-                 {
 
-                     requi.JobLink.ID = ParentID;
 
-                     customise?.Invoke(requi);
 
-                 });
 
-             if (result != null)
 
-             {
 
-                 var id = Guid.Parse(model.ID);
 
-                 DoCache(id, result);
 
-                 DoLink<RequisitionKanban, Requisition, RequisitionLink>(model, result.ID);
 
-             }
 
-             return result;
 
-         }
 
-         public bool EditRequisitions(IEnumerable<TaskModel> models, Action<Requisition>? customise = null)
 
-         {
 
-             var requis = DoLoad<RequisitionKanban, Requisition, RequisitionLink>(models, GetGrid<Requisition>().LoadEditorColumns());
 
-             if (requis.Any())
 
-                 return DoEdit(requis, customise);
 
-             return false;
 
-         }
 
-         public Setout? CreateSetout(TaskModel model, Action<Setout> customise)
 
-         {
 
-             var result = DoCreate<Setout>(
 
-                 setout =>
 
-                 {
 
-                     setout.JobLink.ID = ParentID;
 
-                     customise?.Invoke(setout);
 
-                 });
 
-             if (result != null)
 
-             {
 
-                 var id = Guid.Parse(model.ID);
 
-                 DoCache(id, result);
 
-                 //DoLink<SetoutKanban, Setout, SetoutLink>(model, result.ID);
 
-             }
 
-             return result;
 
-         }
 
-         public bool EditSetouts(IEnumerable<TaskModel> models, Action<Setout>? customise = null)
 
-         {
 
-             var setouts = DoLoad<SetoutKanban, Setout, SetoutLink>(models, GetGrid<Setout>().LoadEditorColumns());
 
-             if (setouts.Any())
 
-                 return DoEdit(setouts, customise);
 
-             return false;
 
-         }
 
-         public Delivery? CreateDelivery(TaskModel model, Action<Delivery> customise)
 
-         {
 
-             var result = DoCreate<Delivery>(
 
-                 delivery =>
 
-                 {
 
-                     delivery.Job.ID = ParentID;
 
-                     customise?.Invoke(delivery);
 
-                 });
 
-             if (result != null)
 
-             {
 
-                 var id = Guid.Parse(model.ID);
 
-                 DoCache(id, result);
 
-                 DoLink<DeliveryKanban, Delivery, DeliveryLink>(model, result.ID);
 
-             }
 
-             return result;
 
-         }
 
-         public bool EditDeliveries(IEnumerable<TaskModel> models, Action<Delivery>? customise = null)
 
-         {
 
-             var deliveries = DoLoad<DeliveryKanban, Delivery, DeliveryLink>(models, GetGrid<Delivery>().LoadEditorColumns());
 
-             if (deliveries.Any())
 
-                 return DoEdit(deliveries, customise);
 
-             return false;
 
-         }
 
-         public PurchaseOrder? CreateOrder(TaskModel model, Action<PurchaseOrder> customise)
 
-         {
 
-             var result = DoCreate<PurchaseOrder>(
 
-                 order => { customise?.Invoke(order); });
 
-             if (result != null)
 
-             {
 
-                 var id = Guid.Parse(model.ID);
 
-                 DoCache(id, result);
 
-                 DoLink<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(model, result.ID);
 
-             }
 
-             return result;
 
-         }
 
-         public bool EditPurchaseOrders(IEnumerable<TaskModel> models, Action<PurchaseOrder>? customise = null)
 
-         {
 
-             var orders = DoLoad<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(models, GetGrid<PurchaseOrder>().LoadEditorColumns());
 
-             if (orders.Any())
 
-                 return DoEdit(orders, customise);
 
-             return false;
 
-         }
 
-         #endregion
 
-         #region EntityReferences
 
-         private static void AddQuery<TEntityKanban, TEntity, TLink>(MultiQuery query, Guid[] taskids)
 
-             where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 
-             where TEntity : Entity
 
-             where TLink : IEntityLink<TEntity>, new()
 
-         {
 
-             query.Add(
 
-                 new Filter<TEntityKanban>(x => x.Kanban.ID).InList(taskids),
 
-                 new Columns<TEntityKanban>(x => x.Entity.ID).Add(x => x.Kanban.ID)
 
-             );
 
-         }
 
-         private static Guid[] ExtractIDs<TEntityKanban, TEntity, TLink>(MultiQuery query)
 
-             where TEntityKanban : EntityKanban<TEntity, TLink>, new()
 
-             where TEntity : Entity
 
-             where TLink : IEntityLink<TEntity>, new()
 
-         {
 
-             var lookup = query.Get<TEntityKanban>().ToLookup<TEntityKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 
-             return query.Get<TEntityKanban>().ExtractValues<TEntityKanban, Guid>(x => x.Entity.ID).ToArray();
 
-         }
 
-         public KanbanReferences[] GetReferences(IEnumerable<TaskModel> models)
 
-         {
 
-             var result = new List<KanbanReferences>();
 
-             var ids = models.Select(x => Guid.Parse(x.ID)).ToArray();
 
-             var query = new MultiQuery();
 
-             AddQuery<RequisitionKanban, Requisition, RequisitionLink>(query, ids);
 
-             AddQuery<SetoutKanban, Setout, SetoutLink>(query, ids);
 
-             AddQuery<DeliveryKanban, Delivery, DeliveryLink>(query, ids);
 
-             AddQuery<PurchaseOrderKanban, PurchaseOrder, PurchaseOrderLink>(query, ids);
 
-             query.Query();
 
-             var requis = query.Get<RequisitionKanban>().ToLookup<RequisitionKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 
-             var setouts = query.Get<SetoutKanban>().ToLookup<SetoutKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 
-             var deliveries = query.Get<DeliveryKanban>().ToLookup<DeliveryKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 
-             var orders = query.Get<PurchaseOrderKanban>().ToLookup<PurchaseOrderKanban, Guid, Guid>(x => x.Kanban.ID, x => x.Entity.ID);
 
-             foreach (var id in ids)
 
-             {
 
-                 var references = new KanbanReferences
 
-                 {
 
-                     Kanban = id,
 
-                     Requisitions = requis.Contains(id) ? requis[id].ToArray() : Array.Empty<Guid>(),
 
-                     Setouts = setouts.Contains(id) ? setouts[id].ToArray() : Array.Empty<Guid>(),
 
-                     Deliveries = deliveries.Contains(id) ? deliveries[id].ToArray() : Array.Empty<Guid>(),
 
-                     Orders = orders.Contains(id) ? orders[id].ToArray() : Array.Empty<Guid>()
 
-                 };
 
-                 result.Add(references);
 
-             }
 
-             return result.ToArray();
 
-         }
 
-         public bool EditReferences(IEnumerable<TaskModel> models)
 
-         {
 
-             var result = false;
 
-             var refs = GetReferences(models).First();
 
-             if (refs.ReferenceType() == typeof(Requisition))
 
-                 result = EditRequisitions(
 
-                     models,
 
-                     requi =>
 
-                     {
 
-                         requi.Notes = Utility.ProcessNotes(requi.Notes, requi.Request);
 
-                         requi.Request = "";
 
-                     }
 
-                 );
 
-             else if (refs.ReferenceType() == typeof(Setout))
 
-                 result = EditSetouts(models);
 
-             else if (refs.ReferenceType() == typeof(Delivery))
 
-                 result = EditDeliveries(models);
 
-             else if (refs.ReferenceType() == typeof(PurchaseOrder))
 
-                 result = EditPurchaseOrders(models);
 
-             else
 
-                 result = EditKanbans(models);
 
-             return result;
 
-         }
 
-         #endregion
 
-     }
 
- }
 
 
  |