Browse Source

Added button to update all dimensions for a given unit

Kenric Nugteren 10 tháng trước cách đây
mục cha
commit
2c9455671e

+ 106 - 0
prs.classes/EnclosedEntities/Dimensions/DimensionUnit.cs

@@ -1,3 +1,4 @@
+using InABox.Clients;
 using InABox.Core;
 using System;
 using System.Collections.Generic;
@@ -130,4 +131,109 @@ namespace Comal.Classes
             }
         }
     }
+
+    public static class DimensionUnitUtils
+    {
+        public static Dictionary<Type, int> UpdateExpressions<T, TLink>(T[] items)
+            where T : DimensionUnit, new()
+            where TLink : DimensionUnitLink<T>
+        {
+            var dimensionTypes = new List<(Type dimType, Type linkType)>();
+            foreach(var entity in CoreUtils.Entities)
+            {
+                var def = entity.GetSuperclassDefinition(typeof(Dimensions<,>));
+                if(def != null && def.GenericTypeArguments[1] == typeof(T))
+                {
+                    dimensionTypes.Add((entity, def.GenericTypeArguments[0]));
+                }
+            }
+
+            var updateTypes = new Dictionary<Type, List<IProperty>>();
+            foreach(var entity in CoreUtils.Entities)
+            {
+                if(entity.IsSubclassOf(typeof(Entity))
+                    && !entity.HasAttribute<AutoEntity>()
+                    && entity.HasInterface<IRemotable>()
+                    && entity.HasInterface<IPersistent>())
+                {
+                    if(entity == typeof(SupplierProduct))
+                    {
+                        var props = DatabaseSchema.Properties(entity).OrderBy(x => x.Name).ToArray();
+                    }
+                    foreach(var property in DatabaseSchema.Properties(entity))
+                    {
+                        if (property.Parent is null
+                            || property.Parent.Parent is null
+                            || property.IsCalculated
+                            || property.Parent.HasParentEntityLink()
+                            || !typeof(TLink).IsAssignableFrom(property.Parent.PropertyType)
+                            || !property.Name.EndsWith(".ID")) continue;
+
+                        var dimType = dimensionTypes.FirstOrDefault(x => property.Parent.Parent.PropertyType == x.dimType);
+                        if(dimType.dimType != null)
+                        {
+                            var dict = updateTypes.GetValueOrAdd(entity);
+                            dict.Add(property.Parent.Parent);
+                        }
+                    }
+                }
+            }
+
+            var nResults = new Dictionary<Type, int>();
+
+            var ids = items.ToArray(x => x.ID);
+            foreach(var (type, properties) in updateTypes)
+            {
+                var columns = Columns.Create(type, ColumnTypeFlags.Required);
+                foreach(var prop in properties)
+                {
+                    columns.Add(prop.Name + "." + Dimensions.unitid.Property);
+                    columns.Add(prop.Name + "." + Dimensions.quantity.Property);
+                    columns.Add(prop.Name + "." + Dimensions.length.Property);
+                    columns.Add(prop.Name + "." + Dimensions.width.Property);
+                    columns.Add(prop.Name + "." + Dimensions.height.Property);
+                    columns.Add(prop.Name + "." + Dimensions.weight.Property);
+                    columns.Add(prop.Name + "." + Dimensions.unitSize.Property);
+                    columns.Add(prop.Name + "." + Dimensions.value.Property);
+                }
+                IFilter? filter = null;
+                foreach(var prop in properties)
+                {
+                    var newFilter = Filter.Create(type, prop.Name + "." + Dimensions.unitid.Property, Operator.InList, ids);
+                    if(filter is null)
+                    {
+                        filter = newFilter;
+                    }
+                    else
+                    {
+                        filter = filter.Or(newFilter);
+                    }
+                }
+                if(filter != null)
+                {
+                    var results = Client.Create(type).Query(filter, columns).ToObjects(type).Cast<Entity>().ToArray();
+                    if(results.Length > 0)
+                    {
+                        foreach(var result in results)
+                        {
+                            foreach(var property in properties)
+                            {
+                                var id = CoreUtils.GetPropertyValue(result, property.Name + "." + Dimensions.unitid.Property);
+                                if(id is Guid guid)
+                                {
+                                    var unit = items.First(x => x.ID == guid);
+                                    var dim = (property.Getter()(result) as IDimensions)!;
+                                    dim.Calculate(dim.Quantity, dim.Length, dim.Width, dim.Height, dim.Weight, unit.Formula, unit.Format);
+                                }
+                            }
+                        }
+                        results = results.Where(x => x.IsChanged()).ToArray();
+                        nResults[type] = results.Length;
+                        Client.Create(type).Save(results, "Updated Value and UnitSize to match dimension unit.");
+                    }
+                }
+            }
+            return nResults;
+        }
+    }
 }

+ 51 - 56
prs.classes/EnclosedEntities/Dimensions/Dimensions.cs

@@ -106,21 +106,21 @@ namespace Comal.Classes
             {
 
                 if (unitid.IsEqualTo(name))
-                    Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
                 else if (quantity.IsEqualTo(name))
-                    Calculate(after, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(after, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
                 else if (length.IsEqualTo(name))
-                    Calculate(Quantity, after, Width, Height, Weight, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, after, Width, Height, Weight, Unit.Formula, Unit.Format);
                 else if (width.IsEqualTo(name))
-                    Calculate(Quantity, Length, after, Height, Weight, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, Length, after, Height, Weight, Unit.Formula, Unit.Format);
                 else if (height.IsEqualTo(name))
-                    Calculate(Quantity, Length, Width, after, Weight, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, Length, Width, after, Weight, Unit.Formula, Unit.Format);
                 else if (weight.IsEqualTo(name))
-                    Calculate(Quantity, Length, Width, Height, after, Unit.Formula, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, Length, Width, Height, after, Unit.Formula, Unit.Format);
                 else if (sizeformula.IsEqualTo(name))
-                    Calculate(Quantity, Length, Width, Height, Weight, after as string, Unit.Format);
+                    (this as IDimensions).Calculate(Quantity, Length, Width, Height, Weight, after as string, Unit.Format);
                 else if (sizeformat.IsEqualTo(name))
-                    Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, after as string);
+                    (this as IDimensions).Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, after as string);
             }
             finally
             {
@@ -148,7 +148,7 @@ namespace Comal.Classes
                 Width = width;
                 Height = height;
                 Weight = weight;
-                Calculate(quantity, length, width, height, weight, unit.Formula, unit.Format);
+                (this as IDimensions).Calculate(quantity, length, width, height, weight, unit.Formula, unit.Format);
             }
             finally
             {
@@ -158,47 +158,7 @@ namespace Comal.Classes
 
         public void CalculateValueAndUnitSize()
         {
-            Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
-        }
-
-        private void Calculate(object? quantity, object? length, object? width, object? height, object? weight, string? formula, string? format)
-        {
-            if (Evaluate<double>(formula, quantity, length, width, height, weight, out double value))
-                Value = value;
-            if (Evaluate<String>(format, quantity, length, width, height, weight, out string unitsize))
-                UnitSize = unitsize;
-        }
-
-        private bool Evaluate<T>(string? formula, object? quantity, object? length, object? width, object? height, object? weight, out T result)
-        {
-
-            if (!String.IsNullOrWhiteSpace(formula))
-            {
-                var variables = new Dictionary<string, object?>()
-                {
-                    { "Quantity", Convert.ToDouble(quantity) },
-                    { "Length", Convert.ToDouble(length) },
-                    { "Width", Convert.ToDouble(width) },
-                    { "Height", Convert.ToDouble(height) },
-                    { "Weight", Convert.ToDouble(weight) }
-                };
-                try
-                {
-                    var expr = new CoreExpression(formula);
-                    var eval = expr.Evaluate(variables);
-                    result = (T)CoreUtils.ChangeType(eval, typeof(T));
-                    return true;
-                }
-                catch (Exception e)
-                {
-                    Logger.Send(LogType.Information, "", String.Format("Error in Formula: [{0}] ({1})", formula, e.Message));
-                    result = default(T);
-                    return false;
-                }
-            }
-
-            result = default(T);
-            return true;
+            (this as IDimensions).Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
         }
 
         public void CopyFrom(IDimensions source, bool observing = false)
@@ -259,12 +219,15 @@ namespace Comal.Classes
     public static class Dimensions
     {
 
-        private static readonly Column<IDimensions> unitid = new Column<IDimensions>(x => x.Unit.ID);
-        private static readonly Column<IDimensions> quantity = new Column<IDimensions>(x => x.Quantity);
-        private static readonly Column<IDimensions> length = new Column<IDimensions>(x => x.Length);
-        private static readonly Column<IDimensions> width = new Column<IDimensions>(x => x.Width);
-        private static readonly Column<IDimensions> height = new Column<IDimensions>(x => x.Height);
-        private static readonly Column<IDimensions> weight = new Column<IDimensions>(x => x.Weight);
+        public static readonly Column<IDimensions> unitid = new Column<IDimensions>(x => x.Unit.ID);
+        public static readonly Column<IDimensions> quantity = new Column<IDimensions>(x => x.Quantity);
+        public static readonly Column<IDimensions> length = new Column<IDimensions>(x => x.Length);
+        public static readonly Column<IDimensions> width = new Column<IDimensions>(x => x.Width);
+        public static readonly Column<IDimensions> height = new Column<IDimensions>(x => x.Height);
+        public static readonly Column<IDimensions> weight = new Column<IDimensions>(x => x.Weight);
+
+        public static readonly Column<IDimensions> unitSize = new Column<IDimensions>(x => x.UnitSize);
+        public static readonly Column<IDimensions> value = new Column<IDimensions>(x => x.Value);
 
         public static IEnumerable<Column<IDimensions>> GetFilterColumns()
         {
@@ -457,5 +420,37 @@ namespace Comal.Classes
                 _ => LocalColumns<TDim>()
             });
         }
+
+        public static bool Evaluate<T>(string? formula, object? quantity, object? length, object? width, object? height, object? weight, out T result)
+        {
+
+            if (!String.IsNullOrWhiteSpace(formula))
+            {
+                var variables = new Dictionary<string, object?>()
+                {
+                    { "Quantity", Convert.ToDouble(quantity) },
+                    { "Length", Convert.ToDouble(length) },
+                    { "Width", Convert.ToDouble(width) },
+                    { "Height", Convert.ToDouble(height) },
+                    { "Weight", Convert.ToDouble(weight) }
+                };
+                try
+                {
+                    var expr = new CoreExpression(formula);
+                    var eval = expr.Evaluate(variables);
+                    result = (T)CoreUtils.ChangeType(eval, typeof(T));
+                    return true;
+                }
+                catch (Exception e)
+                {
+                    Logger.Send(LogType.Information, "", String.Format("Error in Formula: [{0}] ({1})", formula, e.Message));
+                    result = default(T);
+                    return false;
+                }
+            }
+
+            result = default(T);
+            return true;
+        }
     }
 }

+ 13 - 0
prs.classes/EnclosedEntities/Dimensions/IDimensions.cs

@@ -18,5 +18,18 @@ namespace Comal.Classes
 
         void Set(IDimensionUnit unit, double quantity, double length, double width, double height, double weight);
         void CopyFrom(IDimensions source, bool observing = false);
+
+        public void Calculate(object? quantity, object? length, object? width, object? height, object? weight, string? formula, string? format)
+        {
+            if (Dimensions.Evaluate<double>(formula, quantity, length, width, height, weight, out double value))
+                Value = value;
+            if (Dimensions.Evaluate<String>(format, quantity, length, width, height, weight, out string unitsize))
+                UnitSize = unitsize;
+        }
+
+        public void CalculateValueAndUnitSize()
+        {
+            this.Calculate(Quantity, Length, Width, Height, Weight, Unit.Formula, Unit.Format);
+        }
     }
 }

+ 1 - 1
prs.classes/Entities/Product/ProductDimensions/ProductDimensionUnit.cs

@@ -3,7 +3,7 @@ using PRSClasses;
 
 namespace Comal.Classes
 {
-    public class ProductDimensionUnit : DimensionUnit, ILicense<ProductManagementLicense>
+    public class ProductDimensionUnit : DimensionUnit, ILicense<ProductManagementLicense>, IMergeable
     {
         
     }

+ 92 - 22
prs.desktop/Grids/ProductDimensionUnitGrid.cs

@@ -1,39 +1,109 @@
+using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Windows;
 using Comal.Classes;
 using InABox.Core;
 using InABox.DynamicGrid;
+using InABox.Wpf;
+using InABox.WPF;
 
-namespace PRSDesktop.Grids
+namespace PRSDesktop.Grids;
+
+public class ProductDimensionUnitGrid : DynamicDataGrid<ProductDimensionUnit>
 {
-    public class ProductDimensionUnitGrid : DynamicDataGrid<ProductDimensionUnit>
+    protected override void Init()
+    {
+        base.Init();
+
+        AddButton("Update Expressions", null, (button, rows) =>
+        {
+            UpdateExpressions(rows.ToArray<ProductDimensionUnit>());
+            return false;
+        });
+    }
+
+    protected override void DoValidate(ProductDimensionUnit[] items, List<string> errors)
+    {
+        base.DoValidate(items, errors);
+        foreach (var item in items)
+            item.Validate(errors);
+    }
+
+    private void UpdateExpressions(ProductDimensionUnit[] items)
+    {
+        Dictionary<Type, int>? results = null;
+        Exception? exception = null;
+        Progress.ShowModal("Updating Dimensions", progress =>
+        {
+            try
+            {
+                results = DimensionUnitUtils.UpdateExpressions<ProductDimensionUnit, ProductDimensionUnitLink>(items);
+            }
+            catch(Exception e)
+            {
+                exception = e;
+            }
+        });
+        if(results is not null)
+        {
+            MessageWindow.ShowMessage($"Update successful:\n{string.Join("\n", results.Select(x => $"- {x.Key.Name}: {x.Value} items updated"))}", "Success");
+        }
+        else if(exception is not null)
+        {
+            MessageWindow.ShowError("Error while updating dimensions", exception);
+        }
+    }
+
+    private bool ShouldUpdateExpressions = false;
+
+    protected override void DoBeforeSave(IDynamicEditorForm editor, ProductDimensionUnit[] items)
     {
-        protected override void DoValidate(ProductDimensionUnit[] items, List<string> errors)
+        base.DoBeforeSave(editor, items);
+
+        ShouldUpdateExpressions = false;
+        if(items.Any(x => x.HasOriginalValue(x => x.Format) || x.HasOriginalValue(x => x.Formula)))
         {
-            base.DoValidate(items, errors);
-            foreach (var item in items)
-                item.Validate(errors);
+            if(MessageWindow.ShowYesNo("The format and/or formula has been changed; do you wish to update the UnitSize/Value of every item that uses dimension to match the new expression? (This may take a while)", "Update expressions?"))
+            {
+                ShouldUpdateExpressions = true;
+            }
         }
+    }
 
-        protected override void CustomiseEditor(ProductDimensionUnit[] items, DynamicGridColumn column, BaseEditor editor)
+    protected override void DoAfterSave(IDynamicEditorForm editor, ProductDimensionUnit[] items)
+    {
+        base.DoAfterSave(editor, items);
+
+        if (ShouldUpdateExpressions)
         {
-            base.CustomiseEditor(items, column, editor);
-            if (column.ColumnName == nameof(ProductDimensionUnit.Conversion) && editor is ScriptEditor scriptEditor)
+            UpdateExpressions(items);
+        }
+    }
+
+    protected override bool DoMerge(CoreRow[] rows)
+    {
+        return base.DoMerge(rows);
+    }
+
+    protected override void CustomiseEditor(ProductDimensionUnit[] items, DynamicGridColumn column, BaseEditor editor)
+    {
+        base.CustomiseEditor(items, column, editor);
+        if (column.ColumnName == nameof(ProductDimensionUnit.Conversion) && editor is ScriptEditor scriptEditor)
+        {
+            scriptEditor.Type = ScriptEditorType.TemplateEditor;
+            scriptEditor.OnEditorClicked += () =>
             {
-                scriptEditor.Type = ScriptEditorType.TemplateEditor;
-                scriptEditor.OnEditorClicked += () =>
+                var script = items.FirstOrDefault()?.Conversion.NotWhiteSpaceOr()
+                             ?? DimensionUnit.DefaultConvertDimensionsScript();
+
+                var editor = new ScriptEditorWindow(script, SyntaxLanguage.CSharp);
+                if (editor.ShowDialog() == true)
                 {
-                    var script = items.FirstOrDefault()?.Conversion.NotWhiteSpaceOr()
-                                 ?? DimensionUnit.DefaultConvertDimensionsScript();
-
-                    var editor = new ScriptEditorWindow(script, SyntaxLanguage.CSharp);
-                    if (editor.ShowDialog() == true)
-                    {
-                        foreach (var item in items)
-                            SetEditorValue(item, column.ColumnName, editor.Script);
-                    }
-                };
-            }
+                    foreach (var item in items)
+                        SetEditorValue(item, column.ColumnName, editor.Script);
+                }
+            };
         }
     }
 }