Kaynağa Gözat

Added optional Coalesce Value to If() aggregates
Fixed type on Formula.Divide aggregate
Added OnGenerateColumns event to DynamicGrid
DynamicGridUtils.CreateGridWindow can now be created with OK/Cancel buttons
Added WindowBehaviour class to enable hiding of Window min/max/close buttons

frankvandenbos 6 ay önce
ebeveyn
işleme
3b9f4fb5dc

+ 32 - 14
InABox.Core/Objects/Attributes/Aggregate.cs

@@ -95,8 +95,9 @@ namespace InABox.Core
 
 
     public class ComplexFormulaFieldNode<TType, TResult> : IComplexFormulaNode<TType, TResult>, IComplexFormulaFieldNode
     public class ComplexFormulaFieldNode<TType, TResult> : IComplexFormulaNode<TType, TResult>, IComplexFormulaFieldNode
     {
     {
-        //public Expression<Func<TType, TResult>> Expression { get; set; }
+
         public string Field { get; set; }
         public string Field { get; set; }
+        
 
 
         public ComplexFormulaFieldNode(Expression<Func<TType, TResult>> expression)
         public ComplexFormulaFieldNode(Expression<Func<TType, TResult>> expression)
         {
         {
@@ -109,6 +110,7 @@ namespace InABox.Core
         }
         }
 
 
         string IComplexFormulaFieldNode.GetField() => Field;
         string IComplexFormulaFieldNode.GetField() => Field;
+        
     }
     }
 
 
     #endregion
     #endregion
@@ -322,17 +324,20 @@ namespace InABox.Core
         public IComplexFormulaNode<TType, TCondition> Right { get; set; }
         public IComplexFormulaNode<TType, TCondition> Right { get; set; }
 
 
         public Condition Condition { get; set; }
         public Condition Condition { get; set; }
+        
+        public object? Coalesce { get; set; }
 
 
-        public ComplexFormulaPartial0ConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, Condition condition)
+        public ComplexFormulaPartial0ConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, Condition condition, object? coalesce)
         {
         {
             Left = left;
             Left = left;
             Right = right;
             Right = right;
             Condition = condition;
             Condition = condition;
+            Coalesce = coalesce;
         }
         }
 
 
         public ComplexFormulaPartial1ConditionNode<TType, TCondition, TValue> Then(IComplexFormulaNode<TType, TValue> then)
         public ComplexFormulaPartial1ConditionNode<TType, TCondition, TValue> Then(IComplexFormulaNode<TType, TValue> then)
         {
         {
-            return new ComplexFormulaPartial1ConditionNode<TType, TCondition, TValue>(Left, Right, Condition, then);
+            return new ComplexFormulaPartial1ConditionNode<TType, TCondition, TValue>(Left, Right, Condition, then, Coalesce);
         }
         }
     }
     }
 
 
@@ -345,18 +350,21 @@ namespace InABox.Core
         public IComplexFormulaNode<TType, TValue> True { get; set; }
         public IComplexFormulaNode<TType, TValue> True { get; set; }
 
 
         public Condition Condition { get; set; }
         public Condition Condition { get; set; }
+        
+        public object? Coalesce { get; set; }
 
 
-        public ComplexFormulaPartial1ConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, Condition condition, IComplexFormulaNode<TType, TValue> trueValue)
+        public ComplexFormulaPartial1ConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, Condition condition, IComplexFormulaNode<TType, TValue> trueValue, object? coalesce)
         {
         {
             Left = left;
             Left = left;
             Right = right;
             Right = right;
             Condition = condition;
             Condition = condition;
             True = trueValue;
             True = trueValue;
+            Coalesce = coalesce;
         }
         }
 
 
         public ComplexFormulaConditionNode<TType, TCondition, TValue> Else(IComplexFormulaNode<TType, TValue> elseValue)
         public ComplexFormulaConditionNode<TType, TCondition, TValue> Else(IComplexFormulaNode<TType, TValue> elseValue)
         {
         {
-            return new ComplexFormulaConditionNode<TType, TCondition, TValue>(Left, Right, True, elseValue, Condition);
+            return new ComplexFormulaConditionNode<TType, TCondition, TValue>(Left, Right, True, elseValue, Condition, Coalesce);
         }
         }
     }
     }
 
 
@@ -373,6 +381,9 @@ namespace InABox.Core
         public IComplexFormulaNode False { get; }
         public IComplexFormulaNode False { get; }
 
 
         public Condition Condition { get; }
         public Condition Condition { get; }
+        
+        public object? Coalesce { get; }
+        
     }
     }
     public class ComplexFormulaConditionNode<TType, TCondition, TValue> : IComplexFormulaNode<TType, TValue>, IComplexFormulaConditionNode
     public class ComplexFormulaConditionNode<TType, TCondition, TValue> : IComplexFormulaNode<TType, TValue>, IComplexFormulaConditionNode
     {
     {
@@ -387,14 +398,17 @@ namespace InABox.Core
         public IComplexFormulaNode<TType, TValue> False { get; set; }
         public IComplexFormulaNode<TType, TValue> False { get; set; }
 
 
         public Condition Condition { get; set; }
         public Condition Condition { get; set; }
-
-        public ComplexFormulaConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, IComplexFormulaNode<TType, TValue> trueValue, IComplexFormulaNode<TType, TValue> falseValue, Condition condition)
+        
+        public object? Coalesce { get; }
+        
+        public ComplexFormulaConditionNode(IComplexFormulaNode<TType, TCondition> left, IComplexFormulaNode<TType, TCondition> right, IComplexFormulaNode<TType, TValue> trueValue, IComplexFormulaNode<TType, TValue> falseValue, Condition condition, object? coalesce)
         {
         {
             Left = left;
             Left = left;
             Right = right;
             Right = right;
             True = trueValue;
             True = trueValue;
             False = falseValue;
             False = falseValue;
             Condition = condition;
             Condition = condition;
+            Coalesce = coalesce;
         }
         }
 
 
         IComplexFormulaNode IComplexFormulaConditionNode.Left => Left;
         IComplexFormulaNode IComplexFormulaConditionNode.Left => Left;
@@ -468,9 +482,10 @@ namespace InABox.Core
         public static ComplexFormulaPartial0ConditionNode<TType, TCondition, TValue> If<TType, TCondition, TValue>(
         public static ComplexFormulaPartial0ConditionNode<TType, TCondition, TValue> If<TType, TCondition, TValue>(
             IComplexFormulaNode<TType, TCondition> left,
             IComplexFormulaNode<TType, TCondition> left,
             Condition condition,
             Condition condition,
-            IComplexFormulaNode<TType, TCondition> right)
+            IComplexFormulaNode<TType, TCondition> right,
+            object? coalesce = null)
         {
         {
-            return new ComplexFormulaPartial0ConditionNode<TType, TCondition, TValue>(left, right, condition);
+            return new ComplexFormulaPartial0ConditionNode<TType, TCondition, TValue>(left, right, condition, coalesce);
         }
         }
     }
     }
 
 
@@ -505,7 +520,8 @@ namespace InABox.Core
         ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(
         ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(
             Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left,
             Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left,
             Condition condition,
             Condition condition,
-            Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right);
+            Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right,
+            object? coalesce);
     }
     }
 
 
     internal class InternalComplexFormulaGenerator<TType, TResult> : IComplexFormulaGenerator<TType, TResult>
     internal class InternalComplexFormulaGenerator<TType, TResult> : IComplexFormulaGenerator<TType, TResult>
@@ -545,13 +561,15 @@ namespace InABox.Core
         public ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(
         public ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(
             Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left,
             Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left,
             Condition condition,
             Condition condition,
-            Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right)
+            Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right,
+            object? coalesce)
         {
         {
             var generator = new InternalComplexFormulaGenerator<TType, TCondition>();
             var generator = new InternalComplexFormulaGenerator<TType, TCondition>();
             return ComplexFormulaGenerator.If<TType, TCondition, TResult>(
             return ComplexFormulaGenerator.If<TType, TCondition, TResult>(
                 left(generator),
                 left(generator),
                 condition,
                 condition,
-                right(generator));
+                right(generator),
+                coalesce);
         }
         }
 
 
         public IComplexFormulaNode<TType, int> Count<TAggregate, TExpression>(Func<IComplexFormulaGenerator<TAggregate, TExpression>, IComplexFormulaNode<TAggregate, TExpression>> expression, KeyValuePair<Expression<Func<TAggregate, object?>>, Expression<Func<TType, object?>>>[] links, Filter<TAggregate>? filter = null)
         public IComplexFormulaNode<TType, int> Count<TAggregate, TExpression>(Func<IComplexFormulaGenerator<TAggregate, TExpression>, IComplexFormulaNode<TAggregate, TExpression>> expression, KeyValuePair<Expression<Func<TAggregate, object?>>, Expression<Func<TType, object?>>>[] links, Filter<TAggregate>? filter = null)
@@ -607,9 +625,9 @@ namespace InABox.Core
             return ((IComplexFormulaGenerator<TType, TResult>)InternalGenerator).Aggregate(calculation, expression, filter);
             return ((IComplexFormulaGenerator<TType, TResult>)InternalGenerator).Aggregate(calculation, expression, filter);
         }
         }
 
 
-        public ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left, Condition condition, Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right)
+        public ComplexFormulaPartial0ConditionNode<TType, TCondition, TResult> If<TCondition>(Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> left, Condition condition, Func<IComplexFormulaGenerator<TType, TCondition>, IComplexFormulaNode<TType, TCondition>> right, object? coalesce = null)
         {
         {
-            return ((IComplexFormulaGenerator<TType, TResult>)InternalGenerator).If(left, condition, right);
+            return ((IComplexFormulaGenerator<TType, TResult>)InternalGenerator).If(left, condition, right, coalesce);
         }
         }
 
 
         public IComplexFormulaNode<TType, int> Count<TAggregate, TExpression>(Func<IComplexFormulaGenerator<TAggregate, TExpression>, IComplexFormulaNode<TAggregate, TExpression>> expression, KeyValuePair<Expression<Func<TAggregate, object?>>, Expression<Func<TType, object?>>>[] links, Filter<TAggregate>? filter = null)
         public IComplexFormulaNode<TType, int> Count<TAggregate, TExpression>(Func<IComplexFormulaGenerator<TAggregate, TExpression>, IComplexFormulaNode<TAggregate, TExpression>> expression, KeyValuePair<Expression<Func<TAggregate, object?>>, Expression<Func<TType, object?>>>[] links, Filter<TAggregate>? filter = null)

+ 10 - 3
inabox.database.sqlite/SQLiteProvider.cs

@@ -2275,15 +2275,17 @@ public class SQLiteProvider : IProvider
                 var operands = new List<string>();
                 var operands = new List<string>();
                 var op = formula.GetOperator();
                 var op = formula.GetOperator();
 
 
+                bool bFirst = true;
                 foreach (var field in formula.GetOperands())
                 foreach (var field in formula.GetOperands())
                 {
                 {
                     var operand = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, field, useparams);
                     var operand = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, field, useparams);
                     if (op == FormulaOperator.Divide)
                     if (op == FormulaOperator.Divide)
-                        operands.Add($"IFNULL({operand}, 1.00)");
+                        operands.Add($"IFNULL({operand}, {(bFirst ? 0.00 : 1.00)})");
                     else if (op == FormulaOperator.Format)
                     else if (op == FormulaOperator.Format)
                         operands.Add(operand);
                         operands.Add(operand);
                     else
                     else
                         operands.Add($"IFNULL({operand}, 0.00)");
                         operands.Add($"IFNULL({operand}, 0.00)");
+                    bFirst = true;
                 }
                 }
 
 
                 switch (op)
                 switch (op)
@@ -2377,11 +2379,16 @@ public class SQLiteProvider : IProvider
                         throw new Exception($"Invalid formula of type {op}.");
                         throw new Exception($"Invalid formula of type {op}.");
                 }
                 }
             case IComplexFormulaConditionNode condition:
             case IComplexFormulaConditionNode condition:
+                
                 var left = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.Left, useparams);
                 var left = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.Left, useparams);
                 var right = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.Right, useparams);
                 var right = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.Right, useparams);
                 var trueVal = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.True, useparams);
                 var trueVal = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.True, useparams);
                 var falseVal = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.False, useparams);
                 var falseVal = LoadComplexFormula(command, type, prefix, fieldmap, tables, columns, condition.False, useparams);
-
+                
+                var coalesce = condition.Coalesce != null
+                    ? EscapeValue(condition.Coalesce)
+                    : EscapeValue(condition.TCondition.GetDefault());
+                
                 var conditionOp = condition.Condition switch
                 var conditionOp = condition.Condition switch
                 {
                 {
                     Condition.Equals => "=",
                     Condition.Equals => "=",
@@ -2392,7 +2399,7 @@ public class SQLiteProvider : IProvider
                     Condition.LessThanOrEqualTo => "<=",
                     Condition.LessThanOrEqualTo => "<=",
                     _ => throw new Exception($"{condition.Condition} is not a valid condition")
                     _ => throw new Exception($"{condition.Condition} is not a valid condition")
                 };
                 };
-                return $"(CASE WHEN COALESCE({left}, {condition.TCondition.GetDefault()}) {conditionOp} {right} THEN " +
+                return $"(CASE WHEN COALESCE({left}, {coalesce}) {conditionOp} {right} THEN " +
                     $" {trueVal} ELSE {falseVal} END)";
                     $" {trueVal} ELSE {falseVal} END)";
             default:
             default:
                 throw new Exception($"Unknown ComplexFormula type {node.GetType()}");
                 throw new Exception($"Unknown ComplexFormula type {node.GetType()}");