using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.Wpf; using InABox.WPF; using Color = System.Drawing.Color; namespace PRSDesktop { public class RequisitionSettings : IUserConfigurationSettings { public DynamicGridSelectedFilterSettings Filters { get; set; } = new(); } internal class RequisitionGrid : DynamicDataGrid { //public Dictionary _Employees = new Dictionary(); //public Dictionary _Jobs = new Dictionary(); private readonly BitmapImage barcode = PRSDesktop.Resources.barcode.AsBitmapImage(); private RequisitionSettings _settings; private bool bSplitting; private readonly BitmapImage docs = PRSDesktop.Resources.doc_png.AsBitmapImage(); private readonly BitmapImage forklift = PRSDesktop.Resources.forklift.AsBitmapImage(Color.White); private readonly BitmapImage printer = PRSDesktop.Resources.printer.AsBitmapImage(); private readonly BitmapImage tick = PRSDesktop.Resources.tick.AsBitmapImage(Color.White); private readonly BitmapImage truck = PRSDesktop.Resources.truck.AsBitmapImage(); public RequisitionGrid() { _settings = new UserConfiguration().Load(); FilterComponent.SetSettings(_settings.Filters, false); FilterComponent.OnFiltersSelected += FilterComponent_OnFilterSelected; ActionColumns.Add(new DynamicImageColumn(DocumentsImage, DocumentsClick) { Position = DynamicActionColumnPosition.Start }); ActionColumns.Add(new DynamicImageColumn(FilledImage)); ActionColumns.Add(new DynamicImageColumn(DeliveryImage)); ActionColumns.Add(new DynamicImageColumn(StockImage)); //ActionColumns.Add(new DynamicImageColumn() { Action = LabelClick, Image = GetLabelImage }); //ActionColumns.Add(new DynamicImageColumn() { Action = DeliveryDocketClick, Image = GetPrinterImage }); HiddenColumns.Add(x => x.JobLink.ID); HiddenColumns.Add(x => x.JobLink.JobNumber); HiddenColumns.Add(x => x.JobLink.Name); HiddenColumns.Add(x => x.JobScope.ID); HiddenColumns.Add(x => x.Boxes); HiddenColumns.Add(x => x.Filled); HiddenColumns.Add(x => x.Title); HiddenColumns.Add(x => x.Request); HiddenColumns.Add(x => x.Notes); HiddenColumns.Add(x => x.Number); HiddenColumns.Add(x => x.Employee.ID); HiddenColumns.Add(x => x.Employee.Name); HiddenColumns.Add(x => x.Due); HiddenColumns.Add(x => x.RequestedBy.ID); HiddenColumns.Add(x => x.RequestedBy.Name); HiddenColumns.Add(x => x.Documents); HiddenColumns.Add(x => x.Archived); HiddenColumns.Add(x => x.TakenBy.ID); HiddenColumns.Add(x => x.TakenBy.Name); HiddenColumns.Add(x => x.Delivery.ID); HiddenColumns.Add(x => x.Delivery.Number); HiddenColumns.Add(x => x.Delivery.Completed); HiddenColumns.Add(x => x.StockUpdated); //CoreTable employees = new Client().Query( // null, // new Columns(x => x.ID, x => x.Name), // new SortOrder(x => x.Name) //); //foreach (CoreRow row in employees.Rows) // _Employees[row.Get(x => x.ID)] = row.Get(x => x.Name); //Job[] jobs = new Client().Load(null, new SortOrder(x => x.JobNumber)); //foreach (Job job in jobs) //_Jobs[job] = job.ToString(); AddButton("-", PRSDesktop.Resources.box.AsBitmapImage(Color.White), DelBoxClick); AddButton("+", PRSDesktop.Resources.box.AsBitmapImage(Color.White), AddBoxClick); AddButton("Split", PRSDesktop.Resources.split.AsBitmapImage(), SplitRequiClick); //AddButton("Labels", PRSDesktop.Resources.barcode.AsBitmapImage(System.Drawing.Color.White), LabelClick); //AddButton("Del Dkt", PRSDesktop.Resources.printer.AsBitmapImage(System.Drawing.Color.White), DeliveryDocketClick); //AddButton("Complete", PRSDesktop.Resources.tick.AsBitmapImage(System.Drawing.Color.White), FilledClick); OnCustomiseEditor += CustomiseEditor; } private void FilterComponent_OnFilterSelected(DynamicGridSelectedFilterSettings settings) { _settings.Filters = settings; new UserConfiguration().Save(_settings); } protected override void DoReconfigure(DynamicGridOptions options) { base.DoReconfigure(options); options.SelectColumns = true; options.AddRows = true; options.EditRows = true; options.FilterRows = true; if (Security.IsAllowed()) options.DeleteRows = true; } public CoreTable Requisitions { get; private set; } private void CustomiseEditor(IDynamicEditorForm sender, Requisition[]? items, DynamicGridColumn column, BaseEditor editor) { if (column.ColumnName.Equals("Notes")) { if (editor is NotesEditor notes) notes.AlwaysEnabled = bSplitting; } else if (column.ColumnName.Equals("Filled")) { editor.Editable = Security.IsAllowed() || (items != null && items.Any() && items.First().Documents > 0) ? Editable.Enabled : Editable.Hidden; } else if (column.ColumnName.Equals("TakenBy.ID")) { editor.Editable = items != null && items.Any() && !items.First().Filled.IsEmpty() ? Editable.Enabled : Editable.Disabled; } } protected override Dictionary EditorValueChanged(IDynamicEditorForm editor, Requisition[] items, string name, object value) { var result = base.EditorValueChanged(editor, items, name, value); if (name.Equals("TakenBy.ID") && (value == null || Equals(value, Guid.Empty))) editor.SetEditorValue("Archived", DateTime.MinValue); else if (name.Equals("JobLink.ID")) { // false here because a job has a defaultscope // and we need to load the lookups before we set the default value var scope = editor.FindEditor("JobScope.ID") as ILookupEditorControl; if (scope != null) DefineLookups(scope,items,false); } return result; } private bool DocumentsClick(CoreRow? arg) { if (arg == null) return false; var docs = new List(); using (new WaitCursor()) { var deliveryid = arg.Get(x => x.ID); var table = new Client().Query( new Filter(x => x.EntityLink.ID).IsEqualTo(deliveryid) ); foreach (var row in table.Rows) docs.Add(row.ToObject()); } if (docs.Any()) { var editor = new DocumentEditor(docs.ToArray()); //editor.PrintAllowed = Security.IsAllowed(); editor.SaveAllowed = Security.IsAllowed(); editor.ShowDialog(); } else { MessageBox.Show("No Documents Available!"); } return false; } private BitmapImage? DocumentsImage(CoreRow? arg) { if (arg is null) return docs; return arg.Get(x => x.Documents) > 0 ? docs : null; } private bool SplitRequiClick(Button sender, CoreRow[] rows) { var result = false; if ((rows?.Length ?? 0) != 1) { MessageBox.Show("Please select a single Picking List to Split!"); return result; } var confirm = MessageWindow.ShowYesNoCancel("Do you wish to move unpicked items to the new picking list?","Confirm"); if (confirm == MessageWindowResult.Cancel) return false; bSplitting = true; if (SplitPickingList(rows![0], confirm == MessageWindowResult.Yes, (r) => EditItems(new Requisition[] { r }) )) result = true; bSplitting = false; return result; } public bool SplitPickingList(CoreRow row, bool moveunpickeditems, Func edit, IProgress? progress = null) { var oldrequi = row.ToObject(); var newrequi = row.ToObject(); newrequi.ID = Guid.Empty; newrequi.Number = 0; newrequi.CommitChanges(); newrequi.Filled = DateTime.MinValue; List unpicked = moveunpickeditems ? Client.Query( new Filter(x => x.RequisitionLink.ID).IsEqualTo(oldrequi.ID) .And(x => x.ActualQuantity).IsEqualTo(0.0), Columns.Required() ).Rows.Select(x => x.ToObject()).ToList() : new List(); newrequi.Notes = new[] { string.Format("Items unavailable on Picking List #{0}:\n{1}{2}", oldrequi, string.Join("\n",unpicked.Select(x=>$"{x.Quantity} x {x.Description}")), string.Join("\n\n==============================", oldrequi.Notes) ) }; if (edit(newrequi)) { progress?.Report("Creating new Picking List"); bSplitting = false; new Client().Save(newrequi, "Created by Splitting Picking List #" + oldrequi.Number); if (unpicked.Any()) { progress?.Report("Moving unpicked items"); foreach (var item in unpicked) item.RequisitionLink.ID = newrequi.ID; Client.Save(unpicked,$"Moved from {oldrequi.Number} to {newrequi.Number}"); } progress?.Report("Updating Original Picking List"); var _notes = oldrequi.Notes.ToList(); _notes.Insert(0, $"Created secondary Picking List #{newrequi.Number} for further action:\n\nOriginal Picking List Notes:\n"); oldrequi.Notes = _notes.ToArray(); new Client().Save(oldrequi, "Split Picking List to #" + newrequi); return true; } return false; } private bool AddBoxClick(Button btn, CoreRow[] rows) { if (rows.Length != 1) { MessageBox.Show("Please select one row to process!"); return false; } var row = rows.First(); var id = row.Get(x => x.ID); var req = new Client().Load( new Filter(x => x.ID).IsEqualTo(id) ).FirstOrDefault(); if (req != null) { req.Boxes++; new Client().Save(req, string.Format("Set Number of Boxes to {0}", req.Boxes)); //OnRequisitionBoxesChanged?.Invoke(req.ID, req.Boxes); return true; } MessageBox.Show("Cannot locate Requisition"); return true; } private bool DelBoxClick(Button btn, CoreRow[] rows) { if (rows.Length != 1) { MessageBox.Show("Please select one row to process!"); return false; } var row = rows.First(); var id = row.Get(x => x.ID); var req = new Client().Load( new Filter(x => x.ID).IsEqualTo(id) ).FirstOrDefault(); if (req != null) { if (req.Boxes > 0) { req.Boxes--; new Client().Save(req, string.Format("Set Number of Boxes to {0}", req.Boxes)); //OnRequisitionBoxesChanged?.Invoke(req.ID, req.Boxes); } return true; } MessageBox.Show("Cannot Locate Requisition!"); return true; } public override Requisition CreateItem() { var requi = base.CreateItem(); var role = new Client().Load(new Filter(x => x.Code).IsEqualTo("STORES")).FirstOrDefault(); if (role != null) { var emprole = new Client().Load(new Filter(x => x.RoleLink.ID).IsEqualTo(role.ID)).FirstOrDefault(); if (emprole != null) requi.Employee.ID = emprole.EmployeeLink.ID; } return requi; } private BitmapImage? GetBitmapImage(CoreRow? row, BitmapImage image) { if (row == null) return image; var filled = row.Get(x => x.Filled); return filled.IsEmpty() ? null : image; } private BitmapImage? GetLabelImage(CoreRow row) { return GetBitmapImage(row, barcode); } private BitmapImage? GetPrinterImage(CoreRow row) { return GetBitmapImage(row, printer); } private BitmapImage? FilledImage(CoreRow? row) { if (row == null) return tick; var filled = row.Get(x => x.Filled); return filled.IsEmpty() ? null : tick; } private BitmapImage? StockImage(CoreRow? row) { if (row == null) return forklift; var stockupdated = row.Get(x => x.StockUpdated); return stockupdated.IsEmpty() ? null : forklift; } private BitmapImage? DeliveryImage(CoreRow? row) { if (row == null) return truck; var archived = row.Get(x => x.Archived); return archived.IsEmpty() ? null : truck; } private void SendNotifications(CoreRow row) { var updates = new List(); var roles = new Client().Query(new Filter(x => x.RoleLink.Code).IsEqualTo("DELIVERIES")); foreach (var role in roles.Rows) { var notification = new Notification { Title = string.Format("Requi #{0} is ready", row.Get(x => x.Number)), Description = "The requisition has been packed and labelled, and is ready to be assigned to a Delivery" }; notification.Sender.ID = row.Get(x => x.Employee.ID); notification.Employee.ID = role.Get(x => x.EmployeeLink.ID); notification.Job.ID = row.Get(x => x.JobLink.ID); updates.Add(notification); } new Client().Save(updates, "Sent Notification"); } protected override void Reload( Filters criteria, Columns columns, ref SortOrder? sort, CancellationToken token, Action action) { sort = new SortOrder(x => x.Number, SortDirection.Descending); base.Reload(criteria, columns, ref sort, token, action); } } }