Пример #1
0
        public TableRowViewModel(IList <MoneyStateModel> item, List <MoneyColumnMetadataJsModel> headers, Dictionary <string, MoneyColumnMetadataJsModel> headersCached, Dictionary <MoneyColumnMetadataJsModel, Dictionary <DateTime, double> > paymentsToExempt)
        {
            var minDate = item.Select(v => v.When).Min();
            var maxDate = item.Select(v => v.When).Max();

            When = minDate.AddSeconds((maxDate - minDate).TotalSeconds / 2);

            When = When.Date.AddHours(12);

            var grouped = item.GroupBy(v => v.Column).ToDictionary(v => v.Key,
                                                                   s => s.OrderByDescending(t => t.When).First());

            CalculatedCells = new Dictionary <MoneyColumnMetadataJsModel, CalculatedResult>();
            foreach (var h in headers)
            {
                CalculatedResult cell = null;
                var money             = grouped.GetValueOrDefault(h.Column);

                if (money == null && h.IsComputed)
                {
                    cell = CalculatedResult.FromComputed(headersCached, h, CalculatedCells);
                }
                else if (money != null)
                {
                    var adj = paymentsToExempt.GetValueOrDefault(h)?.GetValueOrDefault(money.When.Date.AddDays(-1)) ?? 0;

                    cell = CalculatedResult.FromMoney(h, money, adj);
                }

                CalculatedCells[h] = cell ?? CalculatedResult.Missing(h);
            }

            // make a copy of dictionary to make it editable and to not lost references to dependencies
            CalculatedCells = CalculatedCells.ToDictionary(v => v.Key, v => v.Value);
        }
Пример #2
0
        private TableViewModel(
            ObjectRepository repository)
        {
            Headers = repository.Set <MoneyColumnMetadataModel>().SortColumns().ToList();

            Dictionary <string, MoneyColumnMetadataModel> headersCached = new Dictionary <string, MoneyColumnMetadataModel>();

            foreach (var h in Headers)
            {
                if (!string.IsNullOrWhiteSpace(h.UserFriendlyName))
                {
                    headersCached[h.UserFriendlyName] = h;
                }

                headersCached[h.Provider + "/" + h.AccountName] = h;
            }

            Values = repository.Set <MoneyStateModel>()
                     .GroupBy(x => x.When.Date)
                     .OrderByDescending(v => v.Key)
                     .Select(v => new TableRowViewModel(v.ToList(), Headers, headersCached))
                     .ToList();

            for (int i = 0; i < Values.Count - 1; i++)
            {
                var row = Values[i];
                row.Previous = Values[i + 1];
                foreach (var value in row.Cells)
                {
                    var previous = Values[i + 1];
                    value.PreviousValue = previous.Cells.FirstOrDefault(v => v.Column == value.Column);
                }
            }

            var markedAsOkCells = Enumerable.Empty <MoneyColumnMetadataModel>();

            for (int i = Values.Count - 1; i >= 0; i--)
            {
                var row = Values[i];

                var toAddMissing = markedAsOkCells.Except(row.Cells.Select(v => v.Column)).ToList();

                foreach (var item in toAddMissing)
                {
                    row.Cells.Add(CalculatedResult.Empty(item));
                }

                markedAsOkCells = row.Cells.Where(v => v.Value != null && double.IsNaN(v.Value.Value))
                                  .Select(v => v.Column).ToList();
            }

            foreach (var rowViewModel in Values)
            {
                rowViewModel.CalculateItems();
            }
        }
Пример #3
0
        public override void Evaluate(Dictionary <MoneyColumnMetadataJsModel, CalculatedResult> dependencies)
        {
            if (!_evaluated)
            {
                _evaluated = true;

                dependencies.TryGetValue(_column, out var matchedDependency);

                Value = matchedDependency?.IsOk == true
                    ? matchedDependency
                    : CalculatedResult.ResolutionFail(_column,
                                                      _column.IsComputed
                            ? _column.UserFriendlyName
                            : (_column.Provider + "/" + (_column.UserFriendlyName ?? _column.AccountName)));
            }
        }
Пример #4
0
        public override void Evaluate(Dictionary <MoneyColumnMetadataJsModel, CalculatedResult> dependencies)
        {
            var match = parseRegex.Match(_source);

            var valueString      = match.Groups["value"].Captures.FirstOrDefault()?.Value;
            var ccy              = match.Groups["ccy"].Captures.FirstOrDefault()?.Value;
            var adjustmentString = match.Groups["adj"].Captures.FirstOrDefault()?.Value;

            valueString      = valueString?.Replace(",", ".");
            adjustmentString = adjustmentString?.Replace(",", ".");

            var numberFormatInfo = new NumberFormatInfo {
                NumberDecimalSeparator = "."
            };

            double.TryParse(valueString, NumberStyles.Any, numberFormatInfo, out var value);
            double.TryParse(adjustmentString, NumberStyles.Any, numberFormatInfo, out var adjustment);

            Value = CalculatedResult.FromComputed(_model, value, ccy, Enumerable.Empty <string>(), adjustment, ToString());
        }
Пример #5
0
        public TableRowViewModel(IList <MoneyStateModel> item, List <MoneyColumnMetadataModel> headers, Dictionary <string, MoneyColumnMetadataModel> headersCached)
        {
            When  = item.OrderByDescending(v => v.When).Select(v => v.When).FirstOrDefault();
            Cells = new List <CalculatedResult>();

            foreach (var h in headers)
            {
                if (h.IsComputed)
                {
                    Cells.Add(CalculatedResult.FromComputed(headersCached, h));
                }
                else
                {
                    var money = item.Where(v => v.Provider == h.Provider && v.AccountName == h.AccountName).OrderByDescending(v => v.When).FirstOrDefault();
                    if (money != null)
                    {
                        Cells.Add(CalculatedResult.FromMoney(h, money));
                    }
                }
            }
        }
Пример #6
0
 public EmptyExpression(MoneyColumnMetadataJsModel model)
 {
     Value = CalculatedResult.Empty(model);
 }
Пример #7
0
        public TableViewModel(ObjectRepository repository)
        {
            var headersDictionary = repository.Set <MoneyColumnMetadataModel>().SortColumns()
                                    .ToDictionary(v => new MoneyColumnMetadataJsModel(v), v => v);

            Headers = headersDictionary.Keys.ToList();

            var headersCached = new Dictionary <string, MoneyColumnMetadataJsModel>();

            foreach (var h in Headers)
            {
                if (!string.IsNullOrWhiteSpace(h.UserFriendlyName))
                {
                    headersCached[h.UserFriendlyName] = h;
                }

                headersCached[h.Provider + "/" + h.AccountName] = h;
            }

            var paymentsToExempt = repository.Set <PaymentModel>().Where(v => v.Kind == PaymentKind.Transfer).ToList().GroupBy(v => v.Column)
                                   .ToDictionary(v => new MoneyColumnMetadataJsModel(v.Key), v =>
            {
                var d = new Dictionary <DateTime, double>();
                foreach (var item in v)
                {
                    d[item.When.Date] = d.GetValueOrDefault(item.When.Date, 0) + item.Amount;
                }
                return(d);
            });

            var rows = repository.Set <MoneyStateModel>()
                       .GroupBy(x => x.When.Date)
                       .OrderByDescending(v => v.Key)
                       .ToList();

            var end = rows.Select(v => (DateTime?)v.Key.Date).FirstOrDefault();

            foreach (var col in paymentsToExempt)
            {
                var      cumulative = 0.0;
                DateTime start      = col.Value.Keys.Min();
                for (; start <= (end ?? start); start = start.AddDays(1))
                {
                    var curValue = col.Value.GetValueOrDefault(start, 0);
                    if (Math.Abs(cumulative + curValue) >= 0.0001)
                    {
                        col.Value[start] = -(curValue + cumulative);
                        cumulative      += curValue;
                    }
                }
            }

            Values = rows
                     .Select(v => new TableRowViewModel(v.ToList(), Headers, headersCached, paymentsToExempt))
                     .ToList();

            for (int i = 0; i < Values.Count - 1; i++)
            {
                var row = Values[i];
                row.Previous = Values[i + 1];
                foreach (var value in row.CalculatedCells.Values)
                {
                    var previous = Values[i + 1];
                    value.PreviousValue = previous.CalculatedCells.GetValueOrDefault(value.Column);
                }
            }

            var markedAsOkCells = Enumerable.Empty <MoneyColumnMetadataJsModel>();

            for (int i = Values.Count - 1; i >= 0; i--)
            {
                var row = Values[i];

                var toAddMissing = markedAsOkCells.Except(row.CalculatedCells.Keys).ToList();

                foreach (var item in toAddMissing)
                {
                    row.CalculatedCells.Add(item, CalculatedResult.Empty(item));
                }

                markedAsOkCells = row.CalculatedCells.Values.Where(v => !(v is ExpressionCalculatedResult) && v.Value != null && double.IsNaN(v.Value.Value))
                                  .Select(v => v.Column).ToList();
            }

            var columnsToCheck = Values.SelectMany(v => v.CalculatedCells.Keys).Distinct()
                                 .Where(v => !v.IsComputed).ToList();

            for (int i = Values.Count - 1; i >= 0; i--)
            {
                var row = Values[i];

                columnsToCheck = columnsToCheck.Except(row.CalculatedCells.Keys).ToList();

                foreach (var item in columnsToCheck)
                {
                    row.CalculatedCells.Add(item, CalculatedResult.Empty(item));
                }
            }

            foreach (var r in Values)
            {
                foreach (var cell in r.CalculatedCells.Values.OfType <ExpressionCalculatedResult>())
                {
                    if (cell.IsOk && cell.Value != null)
                    {
                        repository.Add(new MoneyStateModel
                        {
                            Amount      = cell.Value.Value,
                            Ccy         = cell.Ccy,
                            Column      = headersDictionary[cell.Column],
                            When        = r.When,
                            Description = cell.TooltipWithoutAdjustment
                        });
                    }
                }
            }
        }
 public FailedToParseExpression(MoneyColumnMetadataJsModel model, string function)
 {
     _function = function;
     Value     = CalculatedResult.ResolutionFail(model, function);
 }
Пример #9
0
        public override void Evaluate(Dictionary <MoneyColumnMetadataJsModel, CalculatedResult> dependencies)
        {
            if (Left == null || Right == null)
            {
                Value = CalculatedResult.ResolutionFail(_model, _symbol);

                return;
            }

            Left.Evaluate(dependencies);
            Right.Evaluate(dependencies);

            var leftValue  = Left.Value.Value;
            var rightValue = Right.Value.Value;

            bool leftIsNan  = leftValue != null && double.IsNaN(leftValue.Value);
            bool rightIsNan = rightValue != null && double.IsNaN(rightValue.Value);

            if (leftIsNan && !rightIsNan)
            {
                leftValue = 0;
            }

            if (rightIsNan && !leftIsNan)
            {
                rightValue = 0;
            }

            IEnumerable <string> failedToResolve = Left.Value.FailedToResolve.Concat(Right.Value.FailedToResolve).ToList();
            double?value      = null;
            double adjustment = 0;
            string ccy        = null;

            var leftValueAdj  = Left.Value;
            var rightValueAdj = Right.Value;

            while (leftValueAdj?.Value != null && double.IsNaN(leftValueAdj.Value.Value))
            {
                leftValueAdj = leftValueAdj.PreviousValue;
            }
            while (rightValueAdj?.Value != null && double.IsNaN(rightValueAdj.Value.Value))
            {
                rightValueAdj = rightValueAdj.PreviousValue;
            }


            switch (_symbol)
            {
            case "??":
                value      = leftValue ?? rightValue;
                ccy        = SelectCcy(Left.Value.Ccy, Right.Value.Ccy);
                adjustment = leftValueAdj?.Adjustment ?? rightValueAdj?.Adjustment ?? 0;
                break;

            case "+":
                value      = (leftValue ?? 0) + (rightValue ?? 0);
                ccy        = SelectCcy(Left.Value.Ccy, Right.Value.Ccy);
                adjustment = (leftValueAdj?.Adjustment ?? 0) + (rightValueAdj?.Adjustment ?? 0);
                break;

            case "-":
                value      = (leftValue ?? 0) - (rightValue ?? 0);
                ccy        = SelectCcy(Left.Value.Ccy, Right.Value.Ccy);
                adjustment = (leftValueAdj?.Adjustment ?? 0) - (rightValueAdj?.Adjustment ?? 0);
                break;

            case "*":
                value      = (leftValue ?? 0) * (rightValue ?? 0);
                adjustment = (leftValueAdj?.Adjustment ?? 0) * (rightValueAdj?.Adjustment ?? 0);
                ccy        = SelectCcy(Left.Value.Ccy, Right.Value.Ccy);

                // TODO ccy?
                break;

            case "/":
                value = (leftValue ?? 0) / (rightValue ?? 0);

                var leftAdj  = leftValueAdj?.Adjustment ?? 0;
                var rightAdj = rightValueAdj?.Adjustment ?? 0;

                if (Math.Abs(rightAdj) < double.Epsilon)
                {
                    rightAdj = 1;
                }

                adjustment = leftAdj / rightAdj;
                ccy        = SelectCcy(Left.Value.Ccy, Right.Value.Ccy);

                // TODO ccy?
                break;

            default:
                failedToResolve = new[] { _symbol };
                break;
            }

            Value = CalculatedResult.FromComputed(_model, value, ccy, failedToResolve, adjustment, ToString());
        }