|  | @@ -1,6 +1,7 @@
 | 
	
		
			
				|  |  |  using System;
 | 
	
		
			
				|  |  |  using System.Collections.Generic;
 | 
	
		
			
				|  |  |  using System.Linq;
 | 
	
		
			
				|  |  | +using System.Threading.Tasks;
 | 
	
		
			
				|  |  |  using System.Windows;
 | 
	
		
			
				|  |  |  using System.Windows.Media.Imaging;
 | 
	
		
			
				|  |  |  using Comal.Classes;
 | 
	
	
		
			
				|  | @@ -11,213 +12,226 @@ using InABox.DynamicGrid;
 | 
	
		
			
				|  |  |  using InABox.WPF;
 | 
	
		
			
				|  |  |  using NPOI.Util;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -namespace PRSDesktop
 | 
	
		
			
				|  |  | +namespace PRSDesktop;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class SupplierBills : DynamicDataGrid<Bill>
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    public class SupplierBills : DynamicDataGrid<Bill>
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        private static readonly BitmapImage? tick = PRSDesktop.Resources.tick.AsBitmapImage();
 | 
	
		
			
				|  |  | -        private static readonly BitmapImage? data = PRSDesktop.Resources.pencil.AsBitmapImage();
 | 
	
		
			
				|  |  | -        private static readonly BitmapImage? check = PRSDesktop.Resources.checklist.AsBitmapImage();
 | 
	
		
			
				|  |  | +    private static readonly BitmapImage? tick = PRSDesktop.Resources.tick.AsBitmapImage();
 | 
	
		
			
				|  |  | +    private static readonly BitmapImage? data = PRSDesktop.Resources.pencil.AsBitmapImage();
 | 
	
		
			
				|  |  | +    private static readonly BitmapImage? check = PRSDesktop.Resources.checklist.AsBitmapImage();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private SupplierBillPanelProperties _settings = null;
 | 
	
		
			
				|  |  | +    private SupplierBillPanelProperties _settings = null;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    public SupplierBills()
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -        public SupplierBills()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            _settings = new GlobalConfiguration<SupplierBillPanelProperties>().Load();
 | 
	
		
			
				|  |  | +        _settings = new GlobalConfiguration<SupplierBillPanelProperties>().Load();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            HiddenColumns.Add(x => x.Approved);
 | 
	
		
			
				|  |  | -            HiddenColumns.Add(x => x.DataEntered);
 | 
	
		
			
				|  |  | -            HiddenColumns.Add(x => x.Checked);
 | 
	
		
			
				|  |  | -            HiddenColumns.Add(x => x.ApprovalSet.ID);
 | 
	
		
			
				|  |  | +        HiddenColumns.Add(x => x.Approved);
 | 
	
		
			
				|  |  | +        HiddenColumns.Add(x => x.DataEntered);
 | 
	
		
			
				|  |  | +        HiddenColumns.Add(x => x.Checked);
 | 
	
		
			
				|  |  | +        HiddenColumns.Add(x => x.ApprovalSet.ID);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ActionColumns.Add(new DynamicImageColumn(DataEntered_Image, null) { ToolTip = DataEntered_ToolTip });
 | 
	
		
			
				|  |  | -            ActionColumns.Add(new DynamicImageColumn(Checked_Image, null) { ToolTip = Checked_ToolTip });
 | 
	
		
			
				|  |  | -            ActionColumns.Add(new DynamicImageColumn(Approved_Image, null) { ToolTip = Approved_ToolTip });
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicImageColumn(DataEntered_Image, null) { ToolTip = DataEntered_ToolTip });
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicImageColumn(Checked_Image, null) { ToolTip = Checked_ToolTip });
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicImageColumn(Approved_Image, null) { ToolTip = Approved_ToolTip });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            PostUtils.AddPostColumn(this);
 | 
	
		
			
				|  |  | +        PostUtils.AddPostColumn(this);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ActionColumns.Add(new DynamicMenuColumn(BuildMenu));
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        ActionColumns.Add(new DynamicMenuColumn(BuildMenu));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private void BuildMenu(DynamicMenuColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (row is null) return;
 | 
	
		
			
				|  |  | +    private void BuildMenu(DynamicMenuColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (row is null) return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var menu = column.GetMenu();
 | 
	
		
			
				|  |  | -            menu.AddItem("Change Approval Set", null, row, SetBillApprovalSet);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        var menu = column.GetMenu();
 | 
	
		
			
				|  |  | +        var approvalSetItem = menu.AddItem("Approval Set", null, null);
 | 
	
		
			
				|  |  | +        approvalSetItem.AddItem("Loading...", null, null, enabled: false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public override DynamicEditorPages LoadEditorPages(Bill item)
 | 
	
		
			
				|  |  | +        var id = row.Get<Bill, Guid>(x => x.ID);
 | 
	
		
			
				|  |  | +        var selectedApproval = row.Get<Bill, Guid>(x => x.ApprovalSet.ID);
 | 
	
		
			
				|  |  | +        Task.Run(() =>
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            // Need to re-order the pages, since we don't want approvals before lines or documents.
 | 
	
		
			
				|  |  | +            return Client.Query<BillApprovalSet>(
 | 
	
		
			
				|  |  | +                null,
 | 
	
		
			
				|  |  | +                Columns.None<BillApprovalSet>().Add(x => x.ID).Add(x => x.Code).Add(x => x.Description))
 | 
	
		
			
				|  |  | +                .ToArray<BillApprovalSet>();
 | 
	
		
			
				|  |  | +        }).ContinueWith(approvals =>
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            approvalSetItem.Items.Clear();
 | 
	
		
			
				|  |  | +            foreach(var approval in approvals.Result)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var item = approvalSetItem.AddItem($"{approval.Code}: {approval.Description}", null, (row, approval), ApprovalSet_Click);
 | 
	
		
			
				|  |  | +                item.IsChecked = approval.ID == selectedApproval;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }, TaskScheduler.FromCurrentSynchronizationContext());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var pages = base.LoadEditorPages(item);
 | 
	
		
			
				|  |  | +    private void ApprovalSet_Click((CoreRow row, BillApprovalSet approvalSet) item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        var bill = item.row.ToObject<Bill>();
 | 
	
		
			
				|  |  | +        if (bill.ApprovalSet.ID == item.approvalSet.ID) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        BillApprovalSetEmployee[] oldEmployees;
 | 
	
		
			
				|  |  | +        if(bill.ApprovalSet.ID != Guid.Empty)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            oldEmployees = Client.Query(
 | 
	
		
			
				|  |  | +                new Filter<BillApprovalSetEmployee>(x => x.ApprovalSet.ID).IsEqualTo(bill.ApprovalSet.ID),
 | 
	
		
			
				|  |  | +                Columns.None<BillApprovalSetEmployee>().Add(x => x.Employee.ID),
 | 
	
		
			
				|  |  | +                new SortOrder<BillApprovalSetEmployee>(x => x.Sequence))
 | 
	
		
			
				|  |  | +                .ToArray<BillApprovalSetEmployee>();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            oldEmployees = [];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if(pages.TryGetPage<SupplierBillLineGrid>(out var billLineGrid))
 | 
	
		
			
				|  |  | +        var newEmployees = Client.Query(
 | 
	
		
			
				|  |  | +            new Filter<BillApprovalSetEmployee>(x => x.ApprovalSet.ID).IsEqualTo(item.approvalSet.ID),
 | 
	
		
			
				|  |  | +            Columns.None<BillApprovalSetEmployee>().Add(x => x.Employee.ID),
 | 
	
		
			
				|  |  | +            new SortOrder<BillApprovalSetEmployee>(x => x.Sequence))
 | 
	
		
			
				|  |  | +            .ToArray<BillApprovalSetEmployee>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var approvals = Client.Query(
 | 
	
		
			
				|  |  | +            new Filter<BillApproval>(x => x.Bill.ID).IsEqualTo(bill.ID),
 | 
	
		
			
				|  |  | +            Columns.None<BillApproval>()
 | 
	
		
			
				|  |  | +                .Add(x => x.ID)
 | 
	
		
			
				|  |  | +                .Add(x => x.Approved)
 | 
	
		
			
				|  |  | +                .Add(x => x.Employee.ID)
 | 
	
		
			
				|  |  | +                .Add(x => x.Sequence),
 | 
	
		
			
				|  |  | +            new SortOrder<BillApproval>(x => x.Sequence))
 | 
	
		
			
				|  |  | +            .ToArray<BillApproval>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var toDelete = new List<BillApproval>();
 | 
	
		
			
				|  |  | +        var toSave = new List<BillApproval>();
 | 
	
		
			
				|  |  | +        foreach(var employee in newEmployees)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if(!approvals.Any(x => x.Employee.ID == employee.Employee.ID))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                billLineGrid.Order = 0;
 | 
	
		
			
				|  |  | +                var newApproval = new BillApproval();
 | 
	
		
			
				|  |  | +                newApproval.Employee.CopyFrom(employee.Employee);
 | 
	
		
			
				|  |  | +                newApproval.Bill.CopyFrom(bill);
 | 
	
		
			
				|  |  | +                toSave.Add(newApproval);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            if(pages.TryGetPage<DynamicDocumentGrid<BillDocument, Bill, BillLink>>(out var docGrid))
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        foreach(var approval in approvals)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if(approval.Approved == DateTime.MinValue
 | 
	
		
			
				|  |  | +                && oldEmployees.Any(x => x.Employee.ID == approval.Employee.ID)
 | 
	
		
			
				|  |  | +                && !newEmployees.Any(x => x.Employee.ID == approval.Employee.ID))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                docGrid.Order = 1;
 | 
	
		
			
				|  |  | +                toDelete.Add(approval);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            if(pages.TryGetPage<DynamicOneToManyGrid<Bill, BillApproval>>(out var approvalGrid))
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                approvalGrid.Order = 2;
 | 
	
		
			
				|  |  | +                toSave.Add(approval);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            return pages;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private void SetBillApprovalSet(CoreRow row)
 | 
	
		
			
				|  |  | +        foreach(var (i, approval) in toSave.WithIndex())
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var bill = row.ToObject<Bill>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if(MultiSelectDialog<BillApprovalSet>.SelectItem(
 | 
	
		
			
				|  |  | -                out var approvalSet,
 | 
	
		
			
				|  |  | -                filter: new Filter<BillApprovalSet>(x => x.ID).IsNotEqualTo(bill.ApprovalSet.ID),
 | 
	
		
			
				|  |  | -                columns: Columns.None<BillApprovalSet>().Add(x => x.ID),
 | 
	
		
			
				|  |  | -                title: "Select Approval Set:"))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                BillApprovalSetEmployee[] oldEmployees;
 | 
	
		
			
				|  |  | -                if(bill.ApprovalSet.ID != Guid.Empty)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    oldEmployees = Client.Query(
 | 
	
		
			
				|  |  | -                        new Filter<BillApprovalSetEmployee>(x => x.ApprovalSet.ID).IsEqualTo(bill.ApprovalSet.ID),
 | 
	
		
			
				|  |  | -                        Columns.None<BillApprovalSetEmployee>().Add(x => x.Employee.ID),
 | 
	
		
			
				|  |  | -                        new SortOrder<BillApprovalSetEmployee>(x => x.Sequence))
 | 
	
		
			
				|  |  | -                        .ToArray<BillApprovalSetEmployee>();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                else
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    oldEmployees = [];
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                var newEmployees = Client.Query(
 | 
	
		
			
				|  |  | -                    new Filter<BillApprovalSetEmployee>(x => x.ApprovalSet.ID).IsEqualTo(approvalSet.ID),
 | 
	
		
			
				|  |  | -                    Columns.None<BillApprovalSetEmployee>().Add(x => x.Employee.ID),
 | 
	
		
			
				|  |  | -                    new SortOrder<BillApprovalSetEmployee>(x => x.Sequence))
 | 
	
		
			
				|  |  | -                    .ToArray<BillApprovalSetEmployee>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                var approvals = Client.Query(
 | 
	
		
			
				|  |  | -                    new Filter<BillApproval>(x => x.Bill.ID).IsEqualTo(bill.ID),
 | 
	
		
			
				|  |  | -                    Columns.None<BillApproval>()
 | 
	
		
			
				|  |  | -                        .Add(x => x.ID)
 | 
	
		
			
				|  |  | -                        .Add(x => x.Approved)
 | 
	
		
			
				|  |  | -                        .Add(x => x.Employee.ID)
 | 
	
		
			
				|  |  | -                        .Add(x => x.Sequence),
 | 
	
		
			
				|  |  | -                    new SortOrder<BillApproval>(x => x.Sequence))
 | 
	
		
			
				|  |  | -                    .ToArray<BillApproval>();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                var toDelete = new List<BillApproval>();
 | 
	
		
			
				|  |  | -                var toSave = new List<BillApproval>();
 | 
	
		
			
				|  |  | -                foreach(var employee in newEmployees)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    if(!approvals.Any(x => x.Employee.ID == employee.Employee.ID))
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        var newApproval = new BillApproval();
 | 
	
		
			
				|  |  | -                        newApproval.Employee.CopyFrom(employee.Employee);
 | 
	
		
			
				|  |  | -                        newApproval.Bill.CopyFrom(bill);
 | 
	
		
			
				|  |  | -                        toSave.Add(newApproval);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                foreach(var approval in approvals)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    if(approval.Approved == DateTime.MinValue
 | 
	
		
			
				|  |  | -                        && oldEmployees.Any(x => x.Employee.ID == approval.Employee.ID)
 | 
	
		
			
				|  |  | -                        && !newEmployees.Any(x => x.Employee.ID == approval.Employee.ID))
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        toDelete.Add(approval);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    else
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        toSave.Add(approval);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                foreach(var (i, approval) in toSave.WithIndex())
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    approval.Sequence = i;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                Client.Delete(toDelete, "Deleted by changing approval set.");
 | 
	
		
			
				|  |  | -                Client.Save(toSave, "Updated when changing approval set.");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                bill.ApprovalSet.CopyFrom(approvalSet);
 | 
	
		
			
				|  |  | -                SaveItem(bill);
 | 
	
		
			
				|  |  | -                Refresh(false, true);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            approval.Sequence = i;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        Client.Delete(toDelete, "Deleted by changing approval set.");
 | 
	
		
			
				|  |  | +        Client.Save(toSave, "Updated when changing approval set.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        bill.ApprovalSet.CopyFrom(item.approvalSet);
 | 
	
		
			
				|  |  | +        SaveItem(bill);
 | 
	
		
			
				|  |  | +        Refresh(false, true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public override DynamicEditorPages LoadEditorPages(Bill item)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        // Need to re-order the pages, since we don't want approvals before lines or documents.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        var pages = base.LoadEditorPages(item);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private FrameworkElement? Approved_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +        if(pages.TryGetPage<SupplierBillLineGrid>(out var billLineGrid))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return row is null ? column.TextToolTip("Has this bill been approved?")
 | 
	
		
			
				|  |  | -                : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Not yet approved")
 | 
	
		
			
				|  |  | -                : column.TextToolTip("Approved");
 | 
	
		
			
				|  |  | +            billLineGrid.Order = 0;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private FrameworkElement? Checked_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +        if(pages.TryGetPage<DynamicDocumentGrid<BillDocument, Bill, BillLink>>(out var docGrid))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return row is null ? column.TextToolTip("Has this bill been checked?")
 | 
	
		
			
				|  |  | -                : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Not yet checked")
 | 
	
		
			
				|  |  | -                : column.TextToolTip("Checked");
 | 
	
		
			
				|  |  | +            docGrid.Order = 1;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private FrameworkElement? DataEntered_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +        if(pages.TryGetPage<DynamicOneToManyGrid<Bill, BillApproval>>(out var approvalGrid))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return row is null ? column.TextToolTip("Has this bill been entered via Data Entry?")
 | 
	
		
			
				|  |  | -                : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Data not entered.")
 | 
	
		
			
				|  |  | -                : column.TextToolTip("Data Entered");
 | 
	
		
			
				|  |  | +            approvalGrid.Order = 2;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        return pages;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        protected override void DoReconfigure(DynamicGridOptions options)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            base.DoReconfigure(options);
 | 
	
		
			
				|  |  | +    private FrameworkElement? Approved_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return row is null ? column.TextToolTip("Has this bill been approved?")
 | 
	
		
			
				|  |  | +            : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Not yet approved")
 | 
	
		
			
				|  |  | +            : column.TextToolTip("Approved");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            options.FilterRows = true;
 | 
	
		
			
				|  |  | -            options.SelectColumns = true;
 | 
	
		
			
				|  |  | -            options.MultiSelect = true;
 | 
	
		
			
				|  |  | -            options.RecordCount = true;
 | 
	
		
			
				|  |  | -            options.ShowHelp = true; 
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private FrameworkElement? Checked_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return row is null ? column.TextToolTip("Has this bill been checked?")
 | 
	
		
			
				|  |  | +            : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Not yet checked")
 | 
	
		
			
				|  |  | +            : column.TextToolTip("Checked");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private BitmapImage? DataEntered_Image(CoreRow? row)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return (row != null) && row.Get<Bill, DateTime>(x => x.DataEntered).IsEmpty()
 | 
	
		
			
				|  |  | -                ? null
 | 
	
		
			
				|  |  | -                : data;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    private FrameworkElement? DataEntered_ToolTip(DynamicActionColumn column, CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return row is null ? column.TextToolTip("Has this bill been entered via Data Entry?")
 | 
	
		
			
				|  |  | +            : row.Get<Bill, DateTime>(x => x.Approved).IsEmpty() ? column.TextToolTip("Data not entered.")
 | 
	
		
			
				|  |  | +            : column.TextToolTip("Data Entered");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private BitmapImage? Checked_Image(CoreRow? row)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return (row != null) && row.Get<Bill, DateTime>(x => x.Checked).IsEmpty()
 | 
	
		
			
				|  |  | -                ? null
 | 
	
		
			
				|  |  | -                : check;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    protected override void DoReconfigure(DynamicGridOptions options)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        base.DoReconfigure(options);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private BitmapImage? Approved_Image(CoreRow? row)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return (row != null) && row.Get<Bill, DateTime>(x => x.Approved).IsEmpty()
 | 
	
		
			
				|  |  | -                ? null
 | 
	
		
			
				|  |  | -                : tick;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        options.FilterRows = true;
 | 
	
		
			
				|  |  | +        options.SelectColumns = true;
 | 
	
		
			
				|  |  | +        options.MultiSelect = true;
 | 
	
		
			
				|  |  | +        options.RecordCount = true;
 | 
	
		
			
				|  |  | +        options.ShowHelp = true; 
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private BitmapImage? DataEntered_Image(CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return (row != null) && row.Get<Bill, DateTime>(x => x.DataEntered).IsEmpty()
 | 
	
		
			
				|  |  | +            ? null
 | 
	
		
			
				|  |  | +            : data;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private BitmapImage? Checked_Image(CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return (row != null) && row.Get<Bill, DateTime>(x => x.Checked).IsEmpty()
 | 
	
		
			
				|  |  | +            ? null
 | 
	
		
			
				|  |  | +            : check;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private BitmapImage? Approved_Image(CoreRow? row)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return (row != null) && row.Get<Bill, DateTime>(x => x.Approved).IsEmpty()
 | 
	
		
			
				|  |  | +            ? null
 | 
	
		
			
				|  |  | +            : tick;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Bill[] LoadBills(CoreRow[] rows)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return LoadItems(rows);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected override void DoValidate(Bill[] items, List<string> errors)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        base.DoValidate(items, errors);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public Bill[] LoadBills(CoreRow[] rows)
 | 
	
		
			
				|  |  | +        if(items.Any(x => x.Number.IsNullOrWhiteSpace()) && !_settings.AllowBlankBillNumbers)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return LoadItems(rows);
 | 
	
		
			
				|  |  | +            errors.Add($"[{nameof(Bill.Number)}] may not be blank!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        protected override void DoValidate(Bill[] items, List<string> errors)
 | 
	
		
			
				|  |  | +        if(items.Any(x => x.SupplierLink.ID == Guid.Empty))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            base.DoValidate(items, errors);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if(items.Any(x => x.Number.IsNullOrWhiteSpace()) && !_settings.AllowBlankBillNumbers)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                errors.Add($"[{nameof(Bill.Number)}] may not be blank!");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if(items.Any(x => x.SupplierLink.ID == Guid.Empty))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                errors.Add($"[{nameof(Bill.SupplierLink)}] may not be blank!");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            errors.Add($"[{nameof(Bill.SupplierLink)}] may not be blank!");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |