123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- 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 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",
- 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();
- var import = new LogikalElevationSelection(Master, LogikalElevationSelectionType.BOM, (project, boms) =>
- {
- var bom = boms.FirstOrDefault();
- if (bom != null)
- {
- if (_logikalSettings.SaveFiles)
- {
- File.WriteAllBytes(
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
- "BillOfMaterials.xlsx"), bom.ExcelData);
- File.WriteAllBytes(
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
- "BillOfMaterials.sqlite"), bom.SQLiteData);
- }
- AWGMappingWindow window = new AWGMappingWindow(
- IntegrationSourceType.Logikal,
- bom.Finishes,
- bom.Profiles,
- bom.Gaskets,
- bom.Components,
- bom.Glass,
- bom.Labour,
- CreateBOMPart,
- CreateBOMLabour);
- var result = window.ShowDialog();
- return result == true;
- }
- return false;
- });
- if (import.ShowDialog() == true && (materials.Any() || activities.Any()))
- CreateBOM();
- }
- private void CreateBOM()
- {
- Progress.ShowModal("Creating Bill of Materials", progress =>
- {
- var bom = new JobBillOfMaterials();
- 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);
- }
- 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);
- }
- if (activities.Any())
- Client.Save(activities,"Imported From Logikal");
-
- });
- Refresh(false,true);
- }
- 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.UnitCost = 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();
- 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>())
- .ToArray<JobScope>();
- var 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.Finishes,
- bom.Profiles,
- bom.Gaskets,
- bom.Components,
- bom.Glass,
- bom.Labour,
- CreateBOMPart,
- CreateBOMLabour);
- var result = window.ShowDialog();
- return result == true;
- });
- if (import.ShowDialog() == true)
- CreateBOM();
- }
-
- }
- }
|