using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media.Imaging; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.Integration.Logikal; using InABox.WPF; using Microsoft.Xaml.Behaviors.Core; using PRSDesktop.Integrations.Logikal; namespace PRSDesktop.Integrations.Common; public class IntegrationBOMWindowViewModel : DependencyObject { public static DependencyProperty JobIDProperty = DependencyProperty.Register( nameof(JobID), typeof(Guid), typeof(IntegrationBOMWindowViewModel) ); public Guid JobID { get => (Guid)GetValue(JobIDProperty); set => SetValue(JobIDProperty, value); } public static DependencyProperty BOMProperty = DependencyProperty.Register( nameof(BOM), typeof(ILogikalPartsResponse), typeof(IntegrationBOMWindowViewModel), new FrameworkPropertyMetadata(BOMChanged)); private static void BOMChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not IntegrationBOMWindowViewModel model) return; var bom = e.NewValue as ILogikalPartsResponse; var styles = model.ExtractMappings( bom?.Finishes, x => x.Code, x => x.Description, x => x.Code); var profiles = model.ExtractMappings( bom?.Profiles, x => x.Code, x => x.Description, x => x.Code); var components = model.ExtractMappings( bom?.Components, x => x.Code, x => x.Description, x => x.Code); var glass = model.ExtractMappings( bom?.Glass, x => x.Code, x => x.Description, x => x.Code); var labour = model.ExtractMappings( bom?.Labour, x => x.Code, x => x.Description, x => x.Code); Task.WaitAll(styles, profiles, components, glass, labour); model.Styles = styles.Result; model.Profiles = profiles.Result; model.Components = components.Result; model.Glass = glass.Result; model.Labour = labour.Result; model.CheckChanged(); } public ILogikalPartsResponse? BOM { get => GetValue(BOMProperty) as ILogikalPartsResponse; set => SetValue(BOMProperty, value); } private static readonly DependencyProperty StylesProperty = DependencyProperty.Register( nameof(Styles), typeof(List), typeof(IntegrationBOMWindowViewModel) ); public List? Styles { get => GetValue(StylesProperty) as List; set => SetValue(StylesProperty, value); } private static readonly DependencyProperty ProfilesProperty = DependencyProperty.Register( nameof(Profiles), typeof(List), typeof(IntegrationBOMWindowViewModel) ); public List? Profiles { get => GetValue(ProfilesProperty) as List; set => SetValue(ProfilesProperty, value); } private static readonly DependencyProperty ComponentsProperty = DependencyProperty.Register( nameof(Components), typeof(List), typeof(IntegrationBOMWindowViewModel) ); public List? Components { get => GetValue(ComponentsProperty) as List; set => SetValue(ComponentsProperty, value); } private static readonly DependencyProperty GlassProperty = DependencyProperty.Register( nameof(Glass), typeof(List), typeof(IntegrationBOMWindowViewModel) ); public List? Glass { get => GetValue(GlassProperty) as List; set => SetValue(GlassProperty, value); } private static readonly DependencyProperty LabourProperty = DependencyProperty.Register( nameof(Labour), typeof(List), typeof(IntegrationBOMWindowViewModel) ); public List? Labour { get => GetValue(LabourProperty) as List; set => SetValue(LabourProperty, value); } private static readonly DependencyProperty SectionsProperty = DependencyProperty.Register( nameof(Sections), typeof(Dictionary), typeof(IntegrationBOMWindowViewModel) ); private Dictionary _sections = new() { { nameof(Styles), PRSDesktop.Resources.palette.AsBitmapImage(64, 64) }, { nameof(Profiles), PRSDesktop.Resources.profile.AsBitmapImage(64, 64) }, { nameof(Components), PRSDesktop.Resources.fixings.AsBitmapImage(64, 64) }, { nameof(Glass), PRSDesktop.Resources.glass.AsBitmapImage(64, 64) }, { nameof(Labour), PRSDesktop.Resources.quality.AsBitmapImage(64, 64) }, }; public Dictionary Sections { get => (Dictionary)GetValue(SectionsProperty); set => SetValue(SectionsProperty, value); } private static readonly DependencyProperty SelectedSectionProperty = DependencyProperty.Register( nameof(SelectedSection), typeof(KeyValuePair), typeof(IntegrationBOMWindowViewModel) ); public KeyValuePair SelectedSection { get => (KeyValuePair)GetValue(SelectedSectionProperty); set => SetValue(SelectedSectionProperty, value); } private static readonly DependencyProperty MappingsCompleteProperty = DependencyProperty.Register( nameof(MappingsComplete), typeof(bool), typeof(IntegrationBOMWindowViewModel) ); public bool MappingsComplete { get => (bool)GetValue(MappingsCompleteProperty); set => SetValue(MappingsCompleteProperty, value); } private LogikalSettings _settings; private ProductDimensionUnit _profileUom; private ProductDimensionUnit _componentUom; private ProductDimensionUnit _glassUom; public IntegrationBOMWindowViewModel() { Sections = _sections; SelectedSection = Sections.First(); _settings = new GlobalConfiguration().Load(); var uoms = new Client().Query( new Filter(x => x.Code).IsEqualTo(_settings.ProfileUom) .Or(x => x.Code).IsEqualTo(_settings.ComponentUom) .Or(x => x.Code).IsEqualTo(_settings.GlassUom) ).ToObjects().ToArray(); _profileUom = uoms.FirstOrDefault(x=>x.Code == _settings.ProfileUom) ?? new ProductDimensionUnit(); _componentUom = uoms.FirstOrDefault(x=>x.Code == _settings.ComponentUom) ?? new ProductDimensionUnit(); _glassUom = uoms.FirstOrDefault(x=>x.Code == _settings.GlassUom) ?? new ProductDimensionUnit(); } public Task> ExtractMappings( IEnumerable? items, Func logikalcode, Func logikaldescription, Expression> entitycode) where TCode : BaseIntegrationSource, new() where TEntity : Entity, IRemotable,IPersistent, new() where TLink :EntityLink where TMapping : BaseIntegrationSource, IRemotable, IPersistent, new() { return Task.Run(() => { var f = entitycode.Compile(); var results = new List(); if (items == null) return results; var sourceitems = new Dictionary(); foreach (var item in items) sourceitems[logikalcode(item) ?? ""] = logikaldescription(item) ?? ""; MultiQuery query = new(); query.Add( new Filter(entitycode).InList(sourceitems.Keys.ToArray()), Columns.Required().Add(x => x.ID).Add(entitycode) ); var entitycodecol = $"Entity.{CoreUtils.GetFullPropertyName(entitycode, ".")}"; query.Add( new Filter(x => x.Code).InList(sourceitems.Keys.ToArray()), Columns.Required() .Add(x => x.ID) .Add(x => x.Code) .Add(x=>x.Entity.ID) .Add(entitycodecol) ); query.Query(); var mappings = query.Get().ToObjects().ToArray(); var entities = query.Get().ToDictionary(entitycode, x => x.ID); foreach (var sourceitem in sourceitems) { var result = new TCode() { Code = sourceitem.Key, Description = sourceitem.Value }; var mapping = mappings.FirstOrDefault(x => string.Equals(x.Code, sourceitem.Key)); if (mapping != null) { result.Entity.ID = mapping.Entity.ID; CoreUtils.SetPropertyValue(result, entitycodecol, CoreUtils.GetPropertyValue(mapping, entitycodecol)); } else if (entities.ContainsKey(sourceitem.Key)) { result.Entity.ID = entities[sourceitem.Key]; CoreUtils.SetPropertyValue(result.Entity, CoreUtils.GetFullPropertyName(entitycode, "."), sourceitem.Key); } results.Add(result); result.PropertyChanged += (s, e) => { // TMapping mapping = mappingtable.Rows.FirstOrDefault(r => // string.Equals(r.Get(c => c.Code), result.Code))?.ToObject(); // if (mapping == null) // mapping = new TMapping() { Code = result.Code }; // mapping.Entity.ID = result.Entity.ID; // new Client().Save(mapping, "Created from BOM Integration Window"); CheckChanged(); }; } return results; }); } private void CheckChanged() { Dispatcher.BeginInvoke(() => { var styles = Styles?.All(x => x.Entity.ID != Guid.Empty) ?? false; var profiles = Profiles?.All(x => x.Entity.ID != Guid.Empty) ?? false; var glass = Glass?.All(x => x.Entity.ID != Guid.Empty) ?? false; var components = Components?.All(x => x.Entity.ID != Guid.Empty) ?? false; var labour = Labour?.All(x => x.Entity.ID != Guid.Empty) ?? false; MappingsComplete = styles && profiles && glass && components && labour; }); } public ICommand CreateStyle => new ActionCommand( o => { if (o is IntegrationGridCreateEntityArgs args) { args.Entity.Code = args.Mapping.Code ?? ""; args.Entity.Description = args.Mapping.Description ?? ""; args.Entity.Problem.Notes = ["Created from BOM Integration Window"]; } } ); public ICommand CreateProfile => new ActionCommand( o => { if (o is IntegrationGridCreateEntityArgs args) { args.Entity.Code = args.Mapping.Code ?? ""; args.Entity.Name = args.Mapping.Description ?? ""; args.Entity.UnitOfMeasure.CopyFrom(_profileUom); args.Entity.Problem.Notes = ["Created from BOM Integration Window"]; } } ); public ICommand CreateComponent => new ActionCommand( o => { if (o is IntegrationGridCreateEntityArgs args) { args.Entity.Code = args.Mapping.Code ?? ""; args.Entity.Name = args.Mapping.Description ?? ""; args.Entity.UnitOfMeasure.CopyFrom(_componentUom); args.Entity.Problem.Notes = ["Created from BOM Integration Window"]; } } ); public ICommand CreateGlass => new ActionCommand( o => { if (o is IntegrationGridCreateEntityArgs args) { args.Entity.Code = args.Mapping.Code ?? ""; args.Entity.Name = args.Mapping.Description ?? ""; args.Entity.UnitOfMeasure.CopyFrom(_glassUom); args.Entity.Problem.Notes = ["Created from BOM Integration Window"]; } } ); public ICommand CreateActivity => new ActionCommand( o => { if (o is IntegrationGridCreateEntityArgs args) { args.Entity.Code = args.Mapping.Code ?? ""; args.Entity.Description = args.Mapping.Description ?? ""; args.Entity.Problem.Notes = ["Created from BOM Integration Window"]; } } ); public void CreateBOM() { if (BOM == null) return; List items = new List(); foreach (var profile in BOM.Profiles) { var profilemapping = Profiles?.FirstOrDefault(x => x.Code == profile.Code); var stylemapping = Styles?.FirstOrDefault(x => string.Equals(x.Code, profile.Finish)); if (profilemapping != null) { JobBillOfMaterialsItem newitem = new JobBillOfMaterialsItem(); newitem.Product.CopyFrom(profilemapping.Entity); newitem.Dimensions.Unit.CopyFrom(profilemapping.Entity.UnitOfMeasure); newitem.Dimensions.Length = profile.Length; if (stylemapping != null) newitem.Style.CopyFrom(stylemapping.Entity); newitem.Quantity = profile.Quantity; newitem.UnitCost = profile.Cost; items.Add(newitem); } } foreach (var component in BOM.Components) { var componentmapping = Components?.FirstOrDefault(x => string.Equals(x.Code, component.Code)); if (componentmapping != null) { JobBillOfMaterialsItem newitem = new JobBillOfMaterialsItem(); newitem.Product.CopyFrom(componentmapping.Entity); newitem.Dimensions.Unit.CopyFrom(componentmapping.Entity.UnitOfMeasure); newitem.Dimensions.Quantity = component.PackSize; newitem.Quantity = component.Quantity; newitem.UnitCost = component.Cost; items.Add(newitem); } } foreach (var glass in BOM.Glass) { var glassmapping = Glass?.FirstOrDefault(x => string.Equals(x.Code, glass.Code)); if (glassmapping != null) { JobBillOfMaterialsItem newitem = new JobBillOfMaterialsItem(); newitem.Product.CopyFrom(glassmapping.Entity); newitem.Dimensions.Unit.CopyFrom(glassmapping.Entity.UnitOfMeasure); newitem.Dimensions.Height = glass.Height; newitem.Dimensions.Height = glass.Width; newitem.Quantity = glass.Quantity; newitem.UnitCost = glass.Cost; items.Add(newitem); } } List activities = new List(); foreach (var activity in BOM.Labour) { var activitymapping = Labour?.FirstOrDefault(x => string.Equals(x.Code, activity.Code)); if (activitymapping != null) { JobBillOfMaterialsActivity newactivity = new JobBillOfMaterialsActivity(); newactivity.ActivityLink.CopyFrom(activitymapping.Entity); newactivity.Duration = TimeSpan.FromHours(activity.Quantity); newactivity.HourlyCost = activity.Cost; activities.Add(newactivity); } } var _jobbom = new JobBillOfMaterials(); _jobbom.Job.ID = JobID; _jobbom.Description = $"BOM Imported {DateTime.Now}"; Progress.ShowModal("Creating BOM...", progress => { Client.Save(_jobbom, "Imported From Logikal"); progress.Report("Updating Items"); foreach (var item in items) { item.BillOfMaterials.ID = _jobbom.ID; item.Job.ID = _jobbom.Job.ID; } Client.Save(items, "Imported From Logikal"); progress.Report("Updating Labour"); foreach (var activity in activities) { activity.BillOfMaterials.ID = _jobbom.ID; activity.JobLink.ID = _jobbom.Job.ID; } Client.Save(activities, "Imported From Logikal"); }); } }