| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.IO;
 
- 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.Integration.V6;
 
- using InABox.Wpf;
 
- using InABox.WPF;
 
- using NPOI.Util;
 
- using PRSDesktop.Integrations.Common;
 
- using PRSDesktop.Integrations.Logikal;
 
- using PRSDesktop.Integrations.V6;
 
- namespace PRSDesktop
 
- {
 
-     internal class JobBillOfMaterialsGrid : DynamicDataGrid<JobBillOfMaterials>, IMasterDetailControl<Job,JobBillOfMaterials>
 
-     {
 
-         private readonly Button _approve;
 
-         
 
-         public Job? Master { get; set; }
 
-         public Filter<JobBillOfMaterials> MasterDetailFilter => (Master?.ID ?? Guid.Empty) != Guid.Empty
 
-             ? new Filter<JobBillOfMaterials>(x => x.Job.ID).IsEqualTo(Master.ID)
 
-             : new Filter<JobBillOfMaterials>().None();
 
-         public JobBillOfMaterialsGrid()
 
-         {
 
-             HiddenColumns.Add(x => x.Approved);
 
-             HiddenColumns.Add(x => x.Job.ID);
 
-             if (Security.IsAllowed<CanApproveBillsOfMaterials>())
 
-                 _approve = AddButton("Approve", null, ApproveClick);
 
-         }
 
-         protected override void DoReconfigure(DynamicGridOptions options)
 
-         {
 
-             base.DoReconfigure(options);
 
-             options.AddRows = true;
 
-             options.EditRows = true;
 
-             options.DeleteRows = true;
 
-             options.FilterRows = true;
 
-             options.HideDatabaseFilters = true;
 
-             options.SelectColumns = true;
 
-             options.RecordCount = true;
 
-             options.ReorderRows = false;
 
-         }
 
-         
 
-         private bool ApproveClick(Button button, CoreRow[] rows)
 
-         {
 
-             if (rows == null || !rows.Any())
 
-             {
 
-                 MessageBox.Show("Please select a row first!");
 
-                 return false;
 
-             }
 
-             var bom = rows[0].ToObject<JobBillOfMaterials>();
 
-             bom.Approved = bom.Approved.IsEmpty() ? DateTime.Now : DateTime.MinValue;
 
-             UpdateRow<DateTime?>(rows[0], "Approved", bom.Approved.IsEmpty() ? null : bom.Approved, true);
 
-             new Client<JobBillOfMaterials>().Save(bom, bom.Approved.IsEmpty() ? "Cleared Approval" : "Marked as Approved");
 
-             UpdateButton(_approve, null,
 
-                 _approve.IsEnabled && !bom.Approved.IsEmpty() ? "Unapprove" : "Approve");
 
-             return false;
 
-         }
 
-         protected override void SelectItems(CoreRow[] rows)
 
-         {
 
-             base.SelectItems(rows);
 
-             if (rows?.Length == 1)
 
-             {
 
-                 _approve.Visibility = Visibility.Visible;
 
-                 UpdateButton(_approve, null,
 
-                     _approve.IsEnabled && !rows[0].Get<JobBillOfMaterials, DateTime>(c => c.Approved).IsEmpty() ? "Unapprove" : "Approve");
 
-             }
 
-             else
 
-                 _approve.Visibility = Visibility.Collapsed;
 
-         }
 
-         protected override void Reload(
 
-         	Filters<JobBillOfMaterials> criteria, Columns<JobBillOfMaterials> columns, ref SortOrder<JobBillOfMaterials>? sort,
 
-         	CancellationToken token, Action<CoreTable?, Exception?> action)
 
-         {
 
-             criteria.Add(MasterDetailFilter);
 
-             base.Reload(criteria, columns, ref sort, token, action);
 
-         }
 
-         protected override bool CanCreateItems()
 
-         {
 
-             return base.CanCreateItems() && ((Master?.ID ?? Guid.Empty) != Guid.Empty);
 
-         }
 
-         public override JobBillOfMaterials CreateItem()
 
-         {
 
-             var result = base.CreateItem();
 
-             result.Job.ID = Master?.ID ?? Guid.Empty;
 
-             result.Job.Synchronise(Master ?? new Job());
 
-             return result;
 
-         }
 
-         private LogikalSettings? _logikalSettings;
 
-         private V6Settings? _v6Settings;
 
-         
 
-         protected override void DoAdd(bool openEditorOnDirectEdit = false)
 
-         {
 
-             
 
-             ContextMenu? menu = null;
 
-             _v6Settings ??= new GlobalConfiguration<V6Settings>().Load();
 
-             if (_v6Settings.CanImport<ImportV6BillsOfMaterials>(_v6Settings.ImportBoms, Master))
 
-             {
 
-                 menu ??= new ContextMenu();
 
-                 
 
-                 var profiles = new MenuItem()
 
-                 {
 
-                     Header = "Import from V6",
 
-                     Icon = new Image() { Source = PRSDesktop.Resources.v6.AsBitmapImage() }
 
-                 };
 
-                 profiles.Click += ImportFromV6;
 
-                 menu.Items.Add(profiles);
 
-             }
 
-             _logikalSettings ??= new GlobalConfiguration<LogikalSettings>().Load();
 
-             if (_logikalSettings.CanImport<ImportLogikalBillsOfMaterials>(_logikalSettings.ImportBoms, Master))
 
-             {
 
-                 menu ??= new ContextMenu();
 
-                 
 
-                 var item = new MenuItem()
 
-                 {
 
-                     Header = $"Import from Logikal/ReynaPro",
 
-                     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 Bill Of Materials"
 
-                 };
 
-                 item.Click += (o, e) => base.DoAdd(openEditorOnDirectEdit);
 
-                 menu.Items.Insert(0,item);
 
-                 menu.IsOpen = true;
 
-             }
 
-             else
 
-                 base.DoAdd(openEditorOnDirectEdit);
 
-         }
 
-         private List<JobBillOfMaterialsItem> materials = new();
 
-         private List<JobBillOfMaterialsActivity> activities = new();
 
-         
 
-         private void ImportFromLogikal(object sender, RoutedEventArgs e)
 
-         {
 
-             if (Master == null)
 
-                 return;
 
-             
 
-             LogikalClient.Instance.Initialize()
 
-                 .Error(error => MessageWindow.ShowMessage($"Unable to locate Logikal App!\n\n{error.Message}", "Error"))
 
-                 .Success<LogikalInitializeResponse>(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<LogikalConnectResponse>(connect =>
 
-                         {
 
-                             LogikalClient.Instance.Login()
 
-                                 .Error(error =>
 
-                                     MessageWindow.ShowMessage($"Unable to login to Logikal!\n\n{error.Message}",
 
-                                         "Error"))
 
-                                 .Success<LogikalLoginResponse>(login =>
 
-                                 {
 
-                                     ImportBOMFromLogikal();
 
-                                 });
 
-                         });
 
-                 });
 
-         }
 
-         private void ImportBOMFromLogikal()
 
-         {
 
-             materials.Clear();
 
-             activities.Clear();
 
-             byte[] exceldata = null;
 
-             var import = new LogikalElevationSelection(Master, LogikalElevationSelectionType.BOM, (project, boms) =>
 
-             {
 
-                 var bom = boms.FirstOrDefault();
 
-                 if (bom != null)
 
-                 {
 
-                     exceldata = bom.ExcelData;
 
-                     if (_logikalSettings.SaveFiles)
 
-                     {
 
-                         var _ssFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
 
-                             "BillOfMaterials.xlsx");
 
-                         try
 
-                         {
 
-                             File.WriteAllBytes(_ssFile, bom.ExcelData);
 
-                         }
 
-                         catch (Exception e)
 
-                         {
 
-                             MessageWindow.ShowError($"Unable to Save File: {_ssFile}",e);
 
-                         }
 
-                         
 
-                         var _sqlFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
 
-                             "BillOfMaterials.sqlite");
 
-                         try
 
-                         {
 
-                             File.WriteAllBytes(_sqlFile, bom.SQLiteData);
 
-                         }
 
-                         catch (Exception e)
 
-                         {
 
-                             MessageWindow.ShowError($"Unable to Save File: {_sqlFile}",e);
 
-                         }
 
-                     }
 
-                     AWGMappingWindow window = new AWGMappingWindow(
 
-                         IntegrationSourceType.Logikal,
 
-                         bom.Styles,
 
-                         bom.Groups,
 
-                         bom.Suppliers,
 
-                         bom.Discounts,
 
-                         bom.Profiles,
 
-                         bom.Gaskets,
 
-                         bom.Components,
 
-                         bom.Glass,
 
-                         bom.Labour,
 
-                         CreateDiscount,
 
-                         CreateBOMPart,
 
-                         CreateBOMLabour);
 
-                     var result = window.ShowDialog();
 
-                     return result == true;
 
-                 }
 
-                 return false;
 
-             });
 
-             if (import.ShowDialog() == true && (materials.Any() || activities.Any()))
 
-             {
 
-                 var bom = CreateBOM(null);
 
-                 if (exceldata != null)
 
-                 {
 
-                     var ss = new JobSpreadsheet();
 
-                     ss.Code = $"BOM {bom.Number}";
 
-                     ss.Description = $"Logikal BOM {bom.Number} Imported {DateTime.Now:f}";
 
-                     ss.Data = exceldata;
 
-                     ss.Parent.ID = Master.ID;
 
-                     Client.Save(ss, "Imported From Logikal");
 
-                 }
 
-             }
 
-         }
 
-         private void CreateDiscount(SupplierDiscountGroupLink group, double value)
 
-         {
 
-             var discounts = Client.Query(
 
-                 new Filter<SupplierDiscount>(x => x.Group.ID).IsEqualTo(group.ID)
 
-                     .And(
 
-                         new Filter<SupplierDiscount>(x => x.Job.ID).IsEqualTo(Master.ID)
 
-                             .Or(x=>x.Job.ID).IsEqualTo(Guid.Empty)
 
-                     ),
 
-                 Columns.Local<SupplierDiscount>()
 
-             ).Rows.ToArray<SupplierDiscount>();
 
-             var general = discounts.FirstOrDefault(x => x.Job.ID == Guid.Empty);
 
-             if (general == null)
 
-             {
 
-                 general = new SupplierDiscount();
 
-                 general.Group.ID = group.ID;
 
-                 Client.Save(general,"Created by BOM Import");
 
-             }
 
-             
 
-             var supplierdiscount = discounts.FirstOrDefault(x=>x.Job.ID == Master.ID);
 
-             
 
-             if (value.IsEffectivelyEqual(general.Value))
 
-             {
 
-                 if (supplierdiscount != null)
 
-                     Client.Delete(supplierdiscount,"Merged with General Discount");
 
-             }
 
-             else
 
-             {
 
-                 if (supplierdiscount == null)
 
-                 {
 
-                     supplierdiscount = new SupplierDiscount();
 
-                     supplierdiscount.Group.ID = group.ID;
 
-                     supplierdiscount.Job.ID = Master.ID;
 
-                 }
 
-                 supplierdiscount.Value = value;
 
-                 Client.Save(supplierdiscount,"Created by BOM Import");
 
-             }
 
-         }
 
-         
 
-         private JobBillOfMaterials CreateBOM(JobScope? scope)
 
-         {
 
-             JobBillOfMaterials bom = new();
 
-             Progress.ShowModal("Creating Bill of Materials", progress =>
 
-             {
 
-                 bom.Job.CopyFrom(Master);
 
-                 bom.Description = $"BOM Imported {DateTime.Now}";
 
-                 Client.Save(bom, "Imported From Logikal");
 
-                     
 
-                 progress.Report($"Saving Materials ({materials.Count})");
 
-                 materials.SortBy(x=>x.Product.Code);
 
-                 foreach (var material in materials)
 
-                 {
 
-                     material.BillOfMaterials.CopyFrom(bom);
 
-                     material.Job.CopyFrom(Master);
 
-                     material.Scope.CopyFrom(scope ?? new JobScope());
 
-                 }
 
-                 if (materials.Any())
 
-                     Client.Save(materials,"Imported From Logikal");
 
-                     
 
-                 progress.Report($"Saving Labour ({activities.Count})");
 
-                 activities.SortBy(x=>x.ActivityLink.Code);
 
-                 foreach (var activity in activities)
 
-                 {
 
-                     activity.BillOfMaterials.CopyFrom(bom);
 
-                     activity.JobLink.CopyFrom(Master);
 
-                     activity.Scope.CopyFrom(scope ?? new JobScope());
 
-                 }
 
-                 if (activities.Any())
 
-                     Client.Save(activities,"Imported From Logikal");
 
-                     
 
-             });
 
-             Refresh(false,true);
 
-             return bom;
 
-         }
 
-         private void CreateBOMPart(ProductLink product, ProductStyleLink? style, IBaseDimensions dimensions, double quantity, double cost)
 
-         {
 
-             var item = new JobBillOfMaterialsItem();
 
-             item.Product.CopyFrom(product);
 
-             item.Dimensions.Unit.CopyFrom(product.UnitOfMeasure);
 
-             item.Dimensions.CopyFrom(dimensions);
 
-             item.Dimensions.CalculateValueAndUnitSize();
 
-             item.Style.CopyFrom(style ?? new ProductStyleLink());
 
-             item.Quantity = quantity;
 
-             item.TotalCost = cost;
 
-             materials.Add(item);
 
-         }
 
-         
 
-         private void CreateBOMLabour(ActivityLink activity, TimeSpan duration, double cost)
 
-         {
 
-             var item = activities.FirstOrDefault(x => x.ActivityLink.ID == activity.ID);
 
-             if (item == null)
 
-             {
 
-                 item = new JobBillOfMaterialsActivity();
 
-                 item.ActivityLink.CopyFrom(activity);
 
-                 activities.Add(item);
 
-             }
 
-             var total = item.TotalCost;
 
-             item.Duration += duration;
 
-             item.TotalCost = total + (duration.TotalHours * cost);
 
-         }
 
-         
 
-         private void ImportFromV6(object sender, RoutedEventArgs e)
 
-         {
 
-             _v6Settings ??= new GlobalConfiguration<V6Settings>().Load();
 
-             var _client = new V6Client();
 
-             if (!_client.Connect())
 
-             {
 
-                 MessageBox.Show("Unable to connect to V6");
 
-                 return;
 
-             }
 
-             var _project = _client.GetProject(Master?.JobNumber, Master?.SourceRef);
 
-             if (_project == null)
 
-             {
 
-                 MessageBox.Show("This is not a V6 project!");
 
-                 return;
 
-             }
 
-             
 
-             materials.Clear();
 
-             activities.Clear();
 
-             JobScope scope = new JobScope();
 
-             var import = new V6VariationSelection(_client, _project, _ => true, (variation) =>
 
-             {
 
-                 if (Master == null)
 
-                     return false;
 
-                 
 
-                 var scopes = Client.Query(new Filter<JobScope>(x => x.Job.ID).IsEqualTo(Master.ID), Columns.Required<JobScope>().Add(x=>x.SourceRef))
 
-                     .ToArray<JobScope>();
 
-                 scope = scopes.FirstOrDefault(x => string.Equals(x.SourceRef ?? "", string.IsNullOrWhiteSpace(variation.ID) ? "" : variation.GetReference()));
 
-                 if (scope == null && MessageWindow.ShowOKCancel("Create Variation?", "Confirm"))
 
-                 {
 
-                     scope = new JobScope();
 
-                     scope.Job.ID = Master.ID;
 
-                     scope.Description = variation.Description;
 
-                     _v6Settings ??= new GlobalConfiguration<V6Settings>().Load();
 
-                     if (_v6Settings.UseV6QuoteNumber)
 
-                         scope.Number = variation.GetReference();
 
-                     scope.ExTax = variation.SellPrice;
 
-                     Client.Save(scope,"Created from Bill of Materials Import");
 
-                 }
 
-                 if (scope == null)
 
-                     return false;
 
-                 
 
-                 var bom = _client.GetBOM(_project,variation.ID);
 
-                 AWGMappingWindow window = new AWGMappingWindow(
 
-                     IntegrationSourceType.V6,
 
-                     bom.Styles,
 
-                     bom.Groups,
 
-                     bom.Suppliers,
 
-                     bom.Discounts,
 
-                     bom.Profiles,
 
-                     bom.Gaskets, 
 
-                     bom.Components, 
 
-                     bom.Glass, 
 
-                     bom.Labour,
 
-                     CreateDiscount,
 
-                     CreateBOMPart,
 
-                     CreateBOMLabour);
 
-                 var result = window.ShowDialog();
 
-                 return result == true;
 
-             });
 
-             if (import.ShowDialog() == true)
 
-                 CreateBOM(scope);
 
-         }
 
-         
 
-     }
 
- }
 
 
  |