123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- 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 Double Quantity { get; set; }\n"+
- " public IDimensions Dimensions { get; set; }\n"+
- "\n" +
- " public void " + ConvertDimensionsMethodName() + "()\n"+
- " {\n"+
- " // Update Dimensions and Quantity here\n"+
- " // eg. the following will explode a pack into its component parts:\n"+
- " // \n"+
- " // var qty = Dimensions.Quantity;\n"+
- " // Dimensions.Quantity = 1;\n"+
- " // Quantity *= qty;\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;
- }
- }
- }
|