using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using Comal.Classes; using Comal.Classes.SecurityDescriptors; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.Integration.Logikal; using InABox.Wpf; using InABox.WPF; using PRSDesktop.Integrations.V6; using PRSDesktop.Integrations.Logikal; namespace PRSDesktop; public class JobGridSettings : IUserConfigurationSettings { [Obsolete] private CoreFilterDefinition? _currentFilter; [Obsolete] public CoreFilterDefinition? CurrentFilter { get => _currentFilter; set { if (value is not null) { Filters = new DynamicGridSelectedFilterSettings(new List { value }, false, null); } } } public DynamicGridSelectedFilterSettings Filters { get; set; } = new(); } public class ProjectsGrid : DynamicDataGrid { private Guid _statusid = Guid.Empty; private JobGridSettings _settings; public ProjectsGrid() { _settings = new UserConfiguration().Load(); FilterComponent.SetSettings(_settings.Filters, false); FilterComponent.OnFiltersSelected += FilterComponent_OnFilterSelected; HiddenColumns.Add(x => x.ID); HiddenColumns.Add(x => x.JobNumber); HiddenColumns.Add(x => x.Name); HiddenColumns.Add(x => x.Customer.ID); HiddenColumns.Add(x => x.Customer.Code); HiddenColumns.Add(x => x.Customer.Name); HiddenColumns.Add(x => x.Customer.Terms.ID); HiddenColumns.Add(x => x.Customer.Terms.Code); HiddenColumns.Add(x => x.Customer.Terms.Description); HiddenColumns.Add(x => x.Customer.Terms.Calculation); HiddenColumns.Add(x => x.SiteAddress.Street); HiddenColumns.Add(x => x.SiteAddress.City); HiddenColumns.Add(x => x.SiteAddress.State); HiddenColumns.Add(x => x.SiteAddress.PostCode); HiddenColumns.Add(x => x.Account.ID); HiddenColumns.Add(x => x.Account.Code); HiddenColumns.Add(x => x.Account.Name); HiddenColumns.Add(x => x.Account.Terms.ID); HiddenColumns.Add(x => x.Account.Terms.Code); HiddenColumns.Add(x => x.Account.Terms.Description); HiddenColumns.Add(x => x.Account.Terms.Calculation); HiddenColumns.Add(x => x.Notes); HiddenColumns.Add(x => x.JobStatus.ID); HiddenColumns.Add(x => x.JobStatus.Active); HiddenColumns.Add(x => x.DefaultScope.ID); HiddenColumns.Add(x => x.SourceRef); ActionColumns.Add(new DynamicMapColumn(this, x => x.SiteAddress)); //ActionColumns.Add(new DynamicMenuColumn(BuildMenu)); } protected override void DoReconfigure(DynamicGridOptions options) { base.DoReconfigure(options); options.RecordCount = true; options.SelectColumns = true; options.FilterRows = true; } // private void BuildMenu(DynamicMenuColumn column, CoreRow? row) // { // if (Security.IsAllowed()) // { // column.AddItem("Cancel all active requisitions", null, CancelJobRequisitions_Click); // } // if (Security.IsAllowed()) // { // column.AddItem("Release Job Reserves", null, ReleaseJobReserves_Click); // } // } // // private void CancelJobRequisitions_Click(CoreRow? obj) // { // var job = obj?.ToObject(); // if (job is null) // { // MessageWindow.ShowMessage("Please select a job.", "No job selected"); // return; // } // // if(MessageWindow.ShowYesNoCancel("Are you sure you wish to do this? This will cancel all requisitions for this job.", "Confirm") != MessageWindowResult.Yes) // { // MessageWindow.ShowMessage("No action taken.", "Process aborted"); // return; // } // // var requisitionItems = Client.Query( // new Filter(x => x.Requisition.Job.ID).IsEqualTo(job.ID) // .And(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Cancelled) // .And(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Issued) // .And(x => x.Status).IsNotEqualTo(JobRequisitionItemStatus.Archived), // new Columns(x => x.ID) // .Add(x => x.Cancelled)) // .ToList(); // foreach(var jri in requisitionItems) // { // jri.Cancelled = DateTime.Now; // } // Client.Save(requisitionItems, "Cancelled all job requisitions for job"); // MessageWindow.ShowMessage("All job requisitions cancelled.", "Success"); // } // // private void ReleaseJobReserves_Click(CoreRow? obj) // { // var job = obj?.ToObject(); // if (job is null) // { // MessageWindow.ShowMessage("Please select a job.", "No job selected"); // return; // } // // if(MessageWindow.ShowYesNoCancel("Are you sure you wish to do this? This will release all reserves for this job.", "Confirm") != MessageWindowResult.Yes) // { // MessageWindow.ShowMessage("No action taken.", "Process aborted"); // return; // } // // var movements = Client.Query( // new Filter(x => x.Job.ID).IsEqualTo(job.ID), // new Columns(x => x.Units) // .Add(x => x.Location.ID) // .Add(x => x.Product.ID) // .Add(x => x.Style.ID) // .AddDimensionsColumns(x => x.Dimensions) // .Add(x => x.Cost) // .Add(x => x.OrderItem.ID) // .Add(x => x.JobRequisitionItem.ID)) // .ToObjects() // .GroupBy(x => new // { // Location = x.Location.ID, // Product = x.Product.ID, // Style = x.Style.ID, // x.Dimensions, // x.Cost, // OrderItem = x.OrderItem.ID, // JobRequisitionItem = x.JobRequisitionItem.ID // }) // .Select(x => new { x.Key, Units = x.Sum(x => x.Units) }); // // var toSave = new List(); // foreach(var group in movements) // { // var from = new StockMovement(); // from.Location.ID = group.Key.Location; // from.Style.ID = group.Key.Style; // from.Product.ID = group.Key.Product; // from.Dimensions.CopyFrom(group.Key.Dimensions); // // var to = from.CreateMovement(); // // from.Job.ID = job.ID; // // from.Cost = group.Key.Cost; // to.Cost = group.Key.Cost; // from.OrderItem.ID = group.Key.OrderItem; // to.OrderItem.ID = group.Key.OrderItem; // from.JobRequisitionItem.ID = group.Key.JobRequisitionItem; // to.JobRequisitionItem.ID = group.Key.JobRequisitionItem; // // from.Type = StockMovementType.TransferOut; // to.Type = StockMovementType.TransferIn; // to.Transaction = from.Transaction; // // from.Units = -group.Units; // to.Units = group.Units; // // toSave.Add(from); // toSave.Add(to); // } // Client.Save(toSave, "Released all job stock."); // MessageWindow.ShowMessage("All job stock reserves released.", "Success"); // } public Guid StatusID { get => _statusid; set { _statusid = value; } } protected override void Reload( Filters criteria, Columns columns, ref SortOrder? sort, CancellationToken token, Action action) { if (_statusid != Guid.Empty) criteria.Add(new Filter(x => x.JobStatus.ID).IsEqualTo(_statusid)); //criteria.Add(new Filter(x => x.JobType).IsEqualTo(JobType.Project)); sort = new SortOrder(x => x.JobNumber, SortDirection.Descending); base.Reload(criteria, columns, ref sort, token, action); } public override DynamicEditorPages LoadEditorPages(Job item) { var pages = new DynamicEditorPages(new IDynamicEditorPage[] { new DynamicManyToManyGrid(), //new DynamicManyToManyGrid(), new DynamicOneToManyGrid(), new JobFormDefinitionGrid(), //new DynamicOneToManyGrid(), }); return pages; } private LogikalSettings? _logikalSettings; private V6Settings? _v6Settings; protected override void DoAdd(bool openEditorOnDirectEdit = false) { ContextMenu? menu = null; if (Security.IsAllowed()) { _v6Settings ??= new GlobalConfiguration().Load(); if (_v6Settings.ImportProjects == V6ProjectType.Project) { menu ??= new ContextMenu(); var item = new MenuItem() { Header = "Import from V6", Icon = new Image() { Source = PRSDesktop.Resources.v6.AsBitmapImage() } }; item.Click += ImportFromV6; menu.Items.Add(item); } } if (Security.IsAllowed()) { _logikalSettings ??= new GlobalConfiguration().Load(); if (_logikalSettings.ImportProjects == LogikalProjectType.Project) { menu ??= new ContextMenu(); var item = new MenuItem() { Header = "Import from Logikal", Icon = new Image() { Source = PRSDesktop.Resources.logikal.AsBitmapImage() } }; item.Click += ImportFromLogikal; menu.Items.Add(item); } } if (menu != null) { menu.Items.Insert(0,new Separator()); var item = new MenuItem() { Header = "New Project" }; item.Click += (o, e) => base.DoAdd(openEditorOnDirectEdit); menu.Items.Insert(0,item); menu.IsOpen = true; } else base.DoAdd(openEditorOnDirectEdit); } private void ImportFromLogikal(object sender, RoutedEventArgs e) { LogikalClient.Instance.Initialize() .Error(error => { MessageWindow.ShowMessage($"Unable to locate Logikal App!\n\n{error.Message}", "Error"); }) .Success(initialize => { LogikalClient.Instance.Connect(initialize.Path) .Error(error => MessageWindow.ShowMessage($"Unable to connect to Logikal!\n\n{initialize.Path}\n\n{error.Message}", "Error")) .Success(connect => { LogikalClient.Instance.Login() .Error(error => MessageWindow.ShowMessage($"Unable to log in to Logikal!\n\n{error.Message}", "Error")) .Success(login => { var import = new LogikalProjectImport(FilterLogikalProjects, CreateLogikalProject); if (import.ShowDialog() == true) Refresh(false, true); }); }); }); } private List? _logikalSources; private bool FilterLogikalProjects(LogikalProject project) { _logikalSettings ??= new GlobalConfiguration().Load(); if (_logikalSettings.UseLogikalProjectNumber) { _logikalSources ??= Client.Query( null, Columns.None().Add(x => x.JobNumber) ).Rows .Select(r => r.Get(c => c.JobNumber)) .ToList(); return !string.IsNullOrWhiteSpace(project.JobNumber) && !_logikalSources.Contains($"{_logikalSettings.ProjectPrefix}{project.JobNumber}"); } else { _logikalSources ??= Client.Query( new Filter(x => x.SourceRef).BeginsWith("Logikal:"), Columns.None().Add(x => x.SourceRef) ).Rows .Select(r => r.Get(c => c.SourceRef)) .ToList(); return !_logikalSources.Contains(project.GetReference()); } } private void CreateLogikalProject(LogikalProject project) { _logikalSettings ??= new GlobalConfiguration().Load(); var _job = new Job(); if (_logikalSettings.UseLogikalProjectNumber) _job.JobNumber = $"{_logikalSettings.ProjectPrefix}{project.JobNumber}"; else _job.SourceRef = project.GetReference(); _job.Name = project?.Title ?? "New Logikal Project"; //_job.Customer.CopyFrom(_customer); //_job.Account.CopyFrom(_customer.Account); // _job.SiteAddress.Street = project.Street; // _job.SiteAddress.City = project.City; // _job.SiteAddress.State = project.State; // _job.SiteAddress.PostCode = project.PostCode; Client.Save(_job,"Imported From Logikal"); if (_logikalSources != null) _logikalSources.Add(project.GetReference()); // var _scope = Client.Query( // new Filter(x=>x.ID).IsEqualTo(_job.DefaultScope.ID), // Columns.Required() // ).Rows.FirstOrDefault()?.ToObject(); // if (_scope != null) // { // _scope.ExTax = project.SellPrice; // Client.Save(_scope, "Imported From V6"); // } } private void ImportFromV6(object sender, RoutedEventArgs e) { var _client = new V6Client(); if (!_client.Connect()) { MessageBox.Show("Unable to connect to V6!"); return; } var import = new V6ProjectSelection(_client,FilterV6Projects,CreateV6Project); if (import.ShowDialog() == true) Refresh(false,true); } private List? _v6Sources; private bool FilterV6Projects(V6Project project) { _v6Settings ??= new GlobalConfiguration().Load(); if (_v6Settings.UseV6QuoteNumber) { _v6Sources ??= Client.Query( null, Columns.None().Add(x => x.JobNumber) ).Rows .Select(r => r.Get(c => c.JobNumber)) .ToList(); return !_v6Sources.Contains($"{_v6Settings.ProjectPrefix}{project.Number}"); } else { _v6Sources ??= Client.Query( new Filter(x => x.SourceRef).BeginsWith("V6:"), Columns.None().Add(x => x.SourceRef) ).Rows .Select(r => r.Get(c => c.SourceRef)) .ToList(); return !_v6Sources.Contains(project.GetReference()); } } private void CreateV6Project(V6Project project) { _v6Settings ??= new GlobalConfiguration().Load(); var _job = new Job(); var _customer = new Customer(); if (!string.IsNullOrWhiteSpace(project.ClientID)) { _customer = Client.Query( new Filter(x => x.Code).IsEqualTo(project.ClientID), Columns.Required() ).ToObjects() .FirstOrDefault(); if (_customer == null) { _customer = new Customer(); _customer.Code = project.ClientID; _customer.Name = project.ClientName; _customer.Delivery.Street = project.Street; _customer.Delivery.City = project.City; _customer.Delivery.State = project.State; _customer.Delivery.PostCode = project.PostCode; Client.Save(_customer, "Imported From V6"); } } if (_v6Settings.UseV6QuoteNumber) _job.JobNumber = $"{_v6Settings.ProjectPrefix}{project.Number}"; else _job.SourceRef = project.GetReference(); _job.Name = project.Title; _job.Customer.CopyFrom(_customer); _job.Account.CopyFrom(_customer.Account); _job.SiteAddress.Street = project.Street; _job.SiteAddress.City = project.City; _job.SiteAddress.State = project.State; _job.SiteAddress.PostCode = project.PostCode; Client.Save(_job,"Imported From V6"); if (_v6Sources != null) _v6Sources.Add($"V6:{project.Number}"); var _scope = Client.Query( new Filter(x=>x.ID).IsEqualTo(_job.DefaultScope.ID), Columns.Required() ).Rows.FirstOrDefault()?.ToObject(); if (_scope != null) { _scope.ExTax = project.SellPrice; Client.Save(_scope, "Imported From V6"); } } public override Job CreateItem() { var result = base.CreateItem(); result.JobType = JobType.Project; return result; } protected override void CustomiseEditor(IDynamicEditorForm form, Job[] items, DynamicGridColumn column, BaseEditor editor) { base.CustomiseEditor(form, items, column, editor); if(new Column(x => x.Customer.ID).IsEqualTo(column.ColumnName) && editor is CodePopupEditor popup) { popup.CanAdd = Security.CanEdit(); } } protected override Dictionary EditorValueChanged(IDynamicEditorForm editor, Job[] items, string name, object value) { var result = base.EditorValueChanged(editor, items, name, value); if (name.Equals("Customer.ID")) { // false here because a customer has a defaultcontact // and we need to load the lookups before we set the default value var contact = editor.FindEditor("Contact.ID") as ILookupEditorControl; if (contact != null) DefineLookups(contact,items,false); } return result; } private void FilterComponent_OnFilterSelected(DynamicGridSelectedFilterSettings settings) { _settings.Filters = settings; new UserConfiguration().Save(_settings); } }