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); }
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()); }
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)); } } } }
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()); }