| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 | using InABox.Clients;using InABox.Core;using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;namespace Comal.Classes{        public abstract class DimensionUnit : Entity, IRemotable, IPersistent, ISequenceable, IDimensionUnit    {                [UniqueCodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]        [EditorSequence(1)]        public virtual String Code { get; set; }                [TextBoxEditor]        [EditorSequence(2)]        public virtual String Description { get; set; }        [CheckBoxEditor]        [EditorSequence(3)]        public virtual bool HasQuantity { get; set; } = false;                [CheckBoxEditor]        [EditorSequence(4)]        public virtual bool HasLength { get; set; } = false;        [CheckBoxEditor]        [EditorSequence(5)]        public virtual bool HasWidth { get; set; } = false;        [CheckBoxEditor]        [EditorSequence(6)]        public virtual bool HasHeight { get; set; } = false;        [CheckBoxEditor]        [EditorSequence(7)]        public virtual bool HasWeight { get; set; } = false;        [ExpressionEditor(null, typeof(DimensionsExpressionModelGenerator))]        [EditorSequence(8)]        public virtual string Formula { get; set; } = "1";        [ExpressionEditor(null, typeof(DimensionsExpressionModelGenerator))]        [EditorSequence(9)]        public virtual string Format { get; set; } = "\"EACH\"";                [ScriptEditor]        [EditorSequence(10)]        public virtual string Conversion { get; set; } = "";                                [NullEditor]        public long Sequence { get; set; }        public bool HasDimensions() => HasHeight || HasWidth || HasLength || HasWeight || HasQuantity;                public static string ConvertDimensionsMethodName() => "ConvertDimensions";        public static string DefaultConvertDimensionsScript()        {            return                "using Comal.Classes;\n"+                "\n"+                "public class Module\n"+                "{\n"+                "    public void " + ConvertDimensionsMethodName() + "(PurchaseOrderItem item)\n"+                "    {\n"+                        "    }\n"+                "}\n";        }        public bool Validate(List<String> errors)        {            bool result = true;            var variables = new Dictionary<string, object?>()            {                { "Quantity", 1.00F },                { "Length", 1.00F },                { "Width", 1.00F },                { "Height", 1.00F },                { "Weight", 1.00F }            };                        try            {                var expr = new CoreExpression(Formula);                expr.Evaluate(variables);                result = true;            }            catch (Exception e)            {                errors.Add($"{Code}: Formula [{Formula}] =>  {e.Message}");                result = false;            }                        try            {                var expr = new CoreExpression(Format);                expr.Evaluate(variables);                result = true;            }            catch (Exception e)            {                errors.Add($"{Code}: Format [{Format}] =>  {e.Message}");                result = false;            }            return result;        }        private class DimensionsExpressionModelGenerator : IExpressionModelGenerator        {            public List<string> GetVariables(object?[] items)            {                var dimensionUnits = items.Select(x => x as IDimensionUnit).Where(x => x != null).Cast<IDimensionUnit>();                var variables = new List<string>();                if (dimensionUnits.All(x => x.HasQuantity)) variables.Add("Quantity");                if (dimensionUnits.All(x => x.HasLength)) variables.Add("Length");                if (dimensionUnits.All(x => x.HasWidth)) variables.Add("Width");                if (dimensionUnits.All(x => x.HasHeight)) variables.Add("Height");                if (dimensionUnits.All(x => x.HasWeight)) variables.Add("Weight");                return variables;            }        }        public override string ToString()        {            return $"(ProductDimensionUnit: {Code})";        }    }    public static class DimensionUnitUtils    {        public static Dictionary<Type, int> UpdateExpressions<T, TLink>(T[] items, IProgress<string> progress)            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>())                {                    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 propList = updateTypes.GetValueOrAdd(entity);                            propList.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)                {                    progress.Report($"Updating {CoreUtils.Neatify(type.GetCaption())}");                    var nTotal = Client.Create(type).Query(filter, Columns.None(type).Add("ID")).Rows.Count;                    var nProcessed = 0;                    var nResult = 0;                    var done = false;                    var percentStep = Math.Max(nTotal / 100, 1);                    var range = CoreRange.Database(1000);                    while(nProcessed < nTotal && !done)                    {                        var rows = Client.Create(type).Query(filter, columns, range: range).Rows;                        if (rows.Count == 0) break;                        if(rows.Count < 1000)                        {                            done = true;                        }                        range.Next();                        var results = new List<Entity>(rows.Count);                        for(int i = 0; i < rows.Count; ++i)                        {                            if(nProcessed % percentStep == 0)                            {                                progress.Report($"Updating {CoreUtils.Neatify(type.GetCaption())}: {(double)nProcessed / (double)nTotal * 100:F0}%");                            }                            var obj = (rows[i].ToObject(type) as Entity)!;                            foreach(var property in properties)                            {                                var id = CoreUtils.GetPropertyValue(obj, property.Name + "." + Dimensions.unitid.Property);                                if(id is Guid guid)                                {                                    var unit = items.First(x => x.ID == guid);                                    var dim = (property.Getter()(obj) as IDimensions)!;                                    dim.Calculate(dim.Quantity, dim.Length, dim.Width, dim.Height, dim.Weight, unit.Formula, unit.Format);                                }                            }                            if (obj.IsChanged())                            {                                results.Add(obj);                                nResult++;                            }                            nProcessed++;                        }                        Client.Create(type).Save(results, "Updated Value and UnitSize to match dimension unit.");                    }                    nResults[type] = nResult;                }            }            return nResults;        }    }}
 |