using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; 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; namespace PRSDesktop; public class SupplierBillLineGrid : DynamicOneToManyGrid { private static readonly BitmapImage pencil = InABox.Wpf.Resources.pencil.AsBitmapImage(); public SupplierBillLineGrid() { // AddButton("Import", PRSDesktop.Resources.purchase.AsBitmapImage(), ImportLines); HiddenColumns.Add(x => x.TaxCode.ID); HiddenColumns.Add(x => x.TaxCode.Code); HiddenColumns.Add(x => x.TaxCode.Description); HiddenColumns.Add(x => x.TaxCode.Rate); HiddenColumns.Add(x => x.TaxRate); HiddenColumns.Add(x => x.ExTax); HiddenColumns.Add(x => x.Tax); HiddenColumns.Add(x => x.IncTax); HiddenColumns.Add(x => x.Description); HiddenColumns.Add(x=>x.Product.ID); HiddenColumns.Add(x=>x.Product.Code); HiddenColumns.Add(x=>x.Product.Name); HiddenColumns.Add(x=>x.Product.TaxCode.ID); HiddenColumns.Add(x=>x.Product.PurchaseGL.ID); HiddenColumns.Add(x=>x.Product.SellGL.ID); HiddenColumns.Add(x=>x.Product.CostCentre.ID); HiddenColumns.Add(x=>x.Consignment.ID); HiddenColumns.Add(x=>x.Consignment.Number); HiddenColumns.Add(x=>x.OrderItem.ID); HiddenColumns.Add(x=>x.OrderItem.PurchaseOrderLink.ID); HiddenColumns.Add(x=>x.OrderItem.PurchaseOrderLink.PONumber); HiddenColumns.Add(x=>x.OrderItem.Product.Code); HiddenColumns.Add(x=>x.OrderItem.Description); HiddenColumns.Add(x=>x.OrderItem.Qty); HiddenColumns.Add(x=>x.OrderItem.ExTax); HiddenColumns.Add(x=>x.OrderItem.TaxCode.ID); HiddenColumns.Add(x=>x.OrderItem.Tax); HiddenColumns.Add(x=>x.OrderItem.IncTax); ActionColumns.Add( new DynamicTextColumn(DisplayLinkText,DisplayLinkClick) { Position = DynamicActionColumnPosition.Start, Width = 30, HeaderText = "?", ToolTip = DisplayLinkToolTip, Alignment = Alignment.MiddleCenter } ); ActionColumns.Add(new DynamicImageColumn(pencil, BillLineEdit_Click)); } private object DisplayLinkText(CoreRow? row) { if (row == null) return ""; var prodid = row.Get(x => x.Product.ID); var poid = row.Get(x => x.OrderItem.PurchaseOrderLink.ID); var conid = row.Get(x => x.Consignment.ID); return !Guid.Equals(poid,Guid.Empty) ? "O" : !Guid.Equals(conid,Guid.Empty) ? "C" : !Guid.Equals(prodid,Guid.Empty) ? "P" : "--"; } private bool DisplayLinkClick(CoreRow? row) { return false; } private FrameworkElement? DisplayLinkToolTip(DynamicActionColumn column, CoreRow? row) { var text = !Guid.Equals(Guid.Empty, row?.Get(x => x.OrderItem.PurchaseOrderLink.ID) ?? Guid.Empty) ? String.Format("Purchase Order: {0}: {1:F2} x {2}", row?.Get(x => x.OrderItem.PurchaseOrderLink.PONumber), row?.Get(x => x.OrderItem.Qty), row?.Get(x => x.OrderItem.Description) ) : !Guid.Equals(Guid.Empty, row?.Get(x => x.Consignment.ID) ?? Guid.Empty) ? String.Format("Consignment: {0}: {1}", row?.Get(x => x.Consignment.Number), row?.Get(x => x.Consignment.Description) ) : !Guid.Equals(Guid.Empty, row?.Get(x => x.Product.ID) ?? Guid.Empty) ? String.Format("Product: {0}: {1}", row?.Get(x => x.Product.Code), row?.Get(x => x.Product.Name)) : ""; return String.IsNullOrWhiteSpace(text) ? column.TextToolTip(text) : null; } // private class BillLineConverter : IValueConverter // { // public Func Data { get; set; } // // public object Convert(object value, Type targetType, object parameter, CultureInfo culture) // { // if (value is null) // return value; // // var datarow = (value as DataRowView).Row; // var index = datarow.Table.Rows.IndexOf(datarow); // var row = Data().Rows[index]; // // } // // public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) // { // throw new NotImplementedException(); // } // } // // private FrameworkElement DisplayLink() // { // var button = new Button(); // button.SetBinding(Button.ContentProperty, new Binding(".") { Converter = new BillLineConverter() { Data = () => Data} }); // button.SetBinding(Button.DataContextProperty, new Binding(".")); // button.Click += (sender, args) => // { // var datarow = ((sender as Button)?.DataContext as DataRowView)?.Row; // if (datarow != null) // { // var index = datarow.Table.Rows.IndexOf(datarow); // var row = Data.Rows[index]; // // ContextMenu menu = new ContextMenu(); // // var cons = new MenuItem() { Header = "Consignment" }; // cons.Click += (o,e) => SelectConsignment(row); // menu.Items.Add(cons); // // var po = new MenuItem() { Header = "PO Item" }; // po.Click += (o,e) => SelectPOItem(row); // menu.Items.Add(po); // // menu.IsOpen = true; // } // }; // // return button; // } // // private void SelectPOItem(CoreRow row) // { // if (ImportPOLines(row)) // InvalidateRow(row); // } // // private void SelectConsignment(CoreRow row) // { // throw new NotImplementedException(); // } public override DynamicGridColumns GenerateColumns() { if (IsDirectEditMode()) { var columns = new DynamicGridColumns(); columns.Add(x => x.Description, 0, "Description", "", Alignment.MiddleLeft); columns.Add(x => x.OrderItem.ID, 100, "POItem", "", Alignment.MiddleLeft); columns.Add(x => x.PurchaseGL.ID, 100, "Purchase GL", "", Alignment.MiddleLeft); columns.Add(x => x.ExTax, 70, "Ex. Tax", "", Alignment.MiddleLeft); columns.Add(x => x.TaxCode.ID, 70, "Tax Code", "", Alignment.MiddleLeft); columns.Add(x => x.Tax, 70, "Tax", "", Alignment.MiddleLeft); columns.Add(x => x.IncTax, 70, "Inc. Tax", "", Alignment.MiddleLeft); return columns; } else { return base.GenerateColumns(); } } protected override void ConfigureColumns(DynamicGridColumns columns) { base.ConfigureColumns(columns); var editor = columns .FirstOrDefault(x => String.Equals(x.ColumnName, nameof(BillLine.ForeignCurrencyCost)))?.Editor as CurrencyEditor; if (editor != null) editor.CurrencySymbol = Item.SupplierLink.Currency.Symbol; } protected override void CustomiseEditor(BillLine[] items, DynamicGridColumn column, BaseEditor editor) { base.CustomiseEditor(items, column, editor); if (column.ColumnName.Equals("Product.ID")) editor.Editable = items.All(x => x.Product.ID != Guid.Empty) ? Editable.Enabled : Editable.Hidden; else if (column.ColumnName.Equals("Consignment.ID")) editor.Editable = items.All(x => x.Consignment.ID != Guid.Empty) ? Editable.Disabled : Editable.Hidden; else if (column.ColumnName.Equals("OrderItem.ID")) editor.Editable = items.All(x => x.OrderItem.ID != Guid.Empty) ? Editable.Disabled : Editable.Hidden; else if(editor is CurrencyEditor curr) { var settings = new GlobalConfiguration().Load(); curr.Digits = settings.CurrencyDecimalPlaces; if (column.ColumnName.Equals(nameof(BillLine.ForeignCurrencyCost))) curr.CurrencySymbol = items.FirstOrDefault().BillLink.SupplierLink.Currency.Symbol; } } protected override void DoReconfigureEditors(DynamicEditorGrid grid, BillLine[] items) { base.DoReconfigureEditors(grid, items); var fcp = grid.FindEditor(nameof(BillLine.ForeignCurrencyCost)) as CurrencyEditorControl; if (fcp != null) { fcp.SetEnabled(items.All(x=>x.BillLink.SupplierLink.Currency.ID != Guid.Empty)); fcp.CurrencySymbol = items.First().BillLink.SupplierLink.Currency.Symbol; } var tp = grid.FindEditor(nameof(BillLine.ExTax)); if (tp != null) { tp.SetEnabled(items.All(x=>x.BillLink.SupplierLink.Currency.ID == Guid.Empty)); } } protected override void DoReconfigure(DynamicGridOptions options) { base.DoReconfigure(options); options.AddRows = true; options.DeleteRows = true; options.SelectColumns = true; options.DirectEdit = true; options.DragTarget = true; } private bool BillLineEdit_Click(CoreRow? row) { if(row is null) { return false; } var item = LoadItem(row); if (EditItems(new BillLine[] { item })) { SaveItem(item); DoChanged(); return true; } return false; } protected override void DoAdd(bool OpenEditorOnDirectEdit = false) { ContextMenu menu = new ContextMenu(); var blank = new MenuItem() { Header = "Blank Row" }; blank.Click += (o,e) => CreateBlankRow(); menu.Items.Add(blank); menu.Items.Add(new Separator()); var po = new MenuItem() { Header = "Purchase Order Items" }; po.Click += (o, e) => ImportPOLines(); menu.Items.Add(po); var cons = new MenuItem() { Header = "Consignments" }; cons.Click += (o,e) => ImportConsignments(); menu.Items.Add(cons); var prod = new MenuItem() { Header = "Products (Non-stock)" }; prod.Click += (o, e) => ImportProducts(); menu.Items.Add(prod); menu.IsOpen = true; } private void CreateBlankRow() { CreateItems(() => new List() { CreateItem() }); } private void ImportProducts() { var dlg = new MultiSelectDialog( new Filter(x => x.Product.NonStock).IsEqualTo(true), Columns.None() .Add(x => x.ID) ); if (dlg.ShowDialog() == true) { var query = new MultiQuery(); query.Add( new Filter(x => x.ID).InList(dlg.IDs()), Columns.None().Add(x => x.ID) .Add(x => x.Product.ID) .Add(x => x.Product.Name) .Add(x => x.Product.TaxCode.ID) .Add(x => x.Product.TaxCode.Code) .Add(x => x.Product.TaxCode.Description) .Add(x => x.Product.TaxCode.Rate) .Add(x => x.NettCost) .Add(x => x.Product.PurchaseGL.ID) .Add(x => x.Product.PurchaseGL.Code) .Add(x => x.Product.PurchaseGL.Description) .Add(x => x.Product.CostCentre.ID) .Add(x => x.Product.CostCentre.Code) .Add(x => x.Product.CostCentre.Description) ); query.Query(); var items = query.Get().ToObjects(); CreateItems(() => { List lines = new List(); foreach (var item in items) { var line = CreateItem(); line.Product.CopyFrom(item.Product); line.PurchaseGL.CopyFrom(item.Product.PurchaseGL); line.CostCentre.CopyFrom(item.Product.CostCentre); line.TaxCode.CopyFrom(item.Product.TaxCode); line.ExTax = item.NettCost; lines.Add(line); } return lines; }); DoChanged(); Refresh(false, false); } } private void ImportConsignments() { var consignments = ExtractValues(x => x.Consignment.ID, Selection.All).ToArray(); var dlg = new MultiSelectDialog( new Filter(x => x.Supplier.ID).IsEqualTo(Item.SupplierLink.ID) .And(x => x.BillLine.ID).IsEqualTo(Guid.Empty) .And(x => x.ID).NotInList(consignments), Columns.None().Add( x => x.ID)); if (dlg.ShowDialog() == true) { var imports = dlg.Data(); var consids = imports.ExtractValues(x => x.Consignment.ID).Where(x => x != Guid.Empty).Distinct().ToArray(); var results = Client.QueryMultiple( new KeyedQueryDef( new Filter(x => x.ID).InList(dlg.IDs()), Columns.None().Add(x => x.ID) .Add(x => x.Number) .Add(x => x.Description) .Add(x => x.TaxCode.ID) .Add(x => x.TaxCode.Code) .Add(x => x.TaxCode.Description) .Add(x => x.TaxCode.Rate) .Add(x => x.TaxRate) .Add(x=>x.ForeignCurrencyCost) .Add(x => x.ExTax) .Add(x => x.Tax) .Add(x => x.IncTax) .Add(x => x.Created)), new KeyedQueryDef( new Filter(x => x.EntityLink.ID).InList(consids), Columns.None().Add(x => x.DocumentLink.ID) .Add(x => x.DocumentLink.FileName) .Add(x => x.Thumbnail))); var items = results.Get(); CreateItems(() => { List lines = new List(); foreach (var row in items.Rows) { var line = CreateItem(); line.Consignment.ID = row.Get(x => x.ID); line.Consignment.Number = row.Get(x => x.Number); line.Consignment.Description = row.Get(x => x.Description); line.ForeignCurrencyCost = row.Get(x => x.ForeignCurrencyCost); line.ExTax = row.Get(x => x.ExTax); line.TaxCode.ID = row.Get(x => x.TaxCode.ID); line.TaxCode.Code = row.Get(x => x.TaxCode.Code); line.TaxCode.Description = row.Get(x => x.TaxCode.Description); line.TaxCode.Rate = row.Get(x => x.TaxCode.Rate); line.TaxRate = row.Get(x => x.TaxRate); line.Tax = row.Get(x => x.Tax); line.IncTax = row.Get(x => x.IncTax); line.Description = $"{row.Get(x => x.Number)} : {row.Get(x => x.Description)}"; lines.Add(line); } return lines; }); var docpage = EditorGrid.Pages.FirstOrDefault(x=>x is BillDocumentGrid) as BillDocumentGrid; if (!docpage.Ready) docpage.Load(Item,null); if (docpage != null) { var docIDs = docpage.Data.ExtractValues(x => x.DocumentLink.ID).ToHashSet(); foreach(var eDoc in results.GetObjects()) { if (!docIDs.Contains(eDoc.DocumentLink.ID)) { var doc = new BillDocument(); doc.EntityLink.ID = Item.ID; doc.DocumentLink.ID = eDoc.DocumentLink.ID; doc.DocumentLink.FileName = eDoc.DocumentLink.FileName; doc.Thumbnail = eDoc.Thumbnail; docpage.SaveItem(doc); docIDs.Add(eDoc.DocumentLink.ID); } } docpage.Refresh(false,true); } DoChanged(); Refresh(false,false); } } private void ImportPOLines() { var poItems = ExtractValues(x => x.OrderItem.ID, Selection.All).ToArray(); var dlg = new MultiSelectDialog( new Filter(x => x.PurchaseOrderLink.SupplierLink.ID).IsEqualTo(Item.SupplierLink.ID) .And(x => x.BillLine.ID).IsEqualTo(Guid.Empty) .And(x => x.ID).NotInList(poItems), Columns.None().Add( x => x.ID, x => x.Consignment.ID, x => x.PurchaseOrderLink.ID)); if (dlg.ShowDialog() == true) { var imports = dlg.Data(); var poids = imports.ExtractValues(x => x.PurchaseOrderLink.ID).Distinct().ToArray(); var consids = imports.ExtractValues(x => x.Consignment.ID).Distinct().ToArray(); var results = Client.QueryMultiple( new KeyedQueryDef( new Filter(x => x.ID).InList(dlg.IDs()), Columns.None().Add(x => x.ID) .Add(x => x.Description) .Add(x => x.TaxCode.ID) .Add(x => x.TaxCode.Code) .Add(x => x.TaxCode.Description) .Add(x => x.TaxCode.Rate) .Add(x => x.Qty) .Add(x => x.ForeignCurrencyCost) .Add(x => x.TaxRate) .Add(x => x.ExTax) .Add(x => x.Tax) .Add(x => x.IncTax) .Add(x => x.Created) .Add(x => x.PurchaseOrderLink.ID) .Add(x => x.PurchaseOrderLink.PONumber) .Add(x => x.Consignment.ID) .Add(x => x.Product.ID) .Add(x => x.Product.Code) .Add(x => x.Product.Name) .Add(x => x.PurchaseGL.ID) .Add(x => x.CostCentre.ID)), new KeyedQueryDef( new Filter(x => x.EntityLink.ID).InList(poids), Columns.None().Add(x => x.DocumentLink.ID) .Add(x => x.DocumentLink.FileName) .Add(x => x.Thumbnail)), new KeyedQueryDef( new Filter(x => x.EntityLink.ID).InList(consids), Columns.None().Add(x => x.DocumentLink.ID) .Add(x => x.DocumentLink.FileName) .Add(x => x.Thumbnail))); var items = results.Get(); CreateItems(() => { List lines = new List(); foreach (var row in items.Rows) { var line = CreateItem(); line.OrderItem.ID = row.Get(x => x.ID); line.OrderItem.PurchaseOrderLink.ID = row.Get(x => x.PurchaseOrderLink.ID); line.OrderItem.PurchaseOrderLink.PONumber = row.Get(x => x.PurchaseOrderLink.PONumber); line.OrderItem.Product.ID = row.Get(x => x.Product.ID); line.OrderItem.Product.Code = row.Get(x => x.Product.Code); line.OrderItem.Product.Name = row.Get(x => x.Product.Name); line.OrderItem.Description = row.Get(x => x.Description); line.OrderItem.Qty = row.Get(x => x.Qty); line.ForeignCurrencyCost = row.Get(x => x.ForeignCurrencyCost); line.OrderItem.ExTax = row.Get(x => x.ExTax); line.OrderItem.TaxCode.ID = row.Get(x => x.TaxCode.ID); line.OrderItem.TaxCode.Code = row.Get(x => x.TaxCode.Code); line.OrderItem.TaxCode.Description = row.Get(x => x.TaxCode.Description); line.OrderItem.TaxCode.Rate = row.Get(x => x.TaxCode.Rate); line.OrderItem.PurchaseGL.ID = row.Get(x => x.PurchaseGL.ID); line.OrderItem.CostCentre.ID = row.Get(x => x.CostCentre.ID); line.ExTax = row.Get(x => x.ExTax); line.TaxCode.ID = row.Get(x => x.TaxCode.ID); line.TaxCode.Code = row.Get(x => x.TaxCode.Code); line.TaxCode.Description = row.Get(x => x.TaxCode.Description); line.TaxCode.Rate = row.Get(x => x.TaxCode.Rate); line.TaxRate = row.Get(x => x.TaxRate); line.Tax = row.Get(x => x.Tax); line.IncTax = row.Get(x => x.IncTax); line.PurchaseGL.ID = row.Get(x => x.PurchaseGL.ID); line.CostCentre.ID = row.Get(x => x.CostCentre.ID); var description = row.Get(x => x.Description); if (String.IsNullOrWhiteSpace(description)) description = row.Get(x => x.Product.Name); line.Description = description; //$"{row.Get(x => x.Qty):F2} x {description}"; lines.Add(line); } return lines; }); var docpage = EditorGrid.Pages.FirstOrDefault(x=>x is BillDocumentGrid) as BillDocumentGrid; if (!docpage.Ready) docpage.Load(Item,null); if (docpage != null) { var docIDs = docpage.Data.ExtractValues(x => x.DocumentLink.ID).ToHashSet(); foreach(var eDoc in (results.GetObjects() as IEnumerable) .Concat(results.GetObjects())) { if (!docIDs.Contains(eDoc.DocumentLink.ID)) { var doc = new BillDocument(); doc.EntityLink.ID = Item.ID; doc.DocumentLink.ID = eDoc.DocumentLink.ID; doc.DocumentLink.FileName = eDoc.DocumentLink.FileName; doc.Thumbnail = eDoc.Thumbnail; docpage.SaveItem(doc); docIDs.Add(eDoc.DocumentLink.ID); } } docpage.Refresh(false,true); } DoChanged(); Refresh(false,false); } } protected override void HandleDragOver(object sender, DragEventArgs e) { base.HandleDragOver(sender, e); if (e.Data.GetDataPresent(typeof(Product))) { if (e.Data.GetData(typeof(Product)) is Product product) { if (!Security.CanEdit() || !Security.CanEdit()) { e.Effects = DragDropEffects.None; } } } } protected override void HandleDragDrop(object sender, DragEventArgs e) { base.HandleDragDrop(sender, e); if (e.Data.GetDataPresent(typeof(Product))) { if (e.Data.GetData(typeof(Product)) is Product product) { if (Security.CanEdit() && Security.CanEdit()) { var item = CreateItem(); item.Product.ID = product.ID; item.Product.Synchronise(product); item.Description = product.Name; SaveItem(item); DoChanged(); Refresh(false, true); } } } } }