/// <summary> /// Analyses the supplied statement using the supplied budget within the criteria given to this method. /// </summary> /// <param name="budgets">The current budgets collection.</param> /// <param name="criteria">The criteria to limit the analysis.</param> /// <param name="statementModel">The current statement model.</param> /// <exception cref="BudgetException"> /// Will be thrown if no budget is supplied or if no budget can be found for the dates /// given in the criteria. /// </exception> /// <exception cref="ArgumentException">If statement or budget is null.</exception> public virtual OverallPerformanceBudgetResult Analyse(StatementModel statementModel, BudgetCollection budgets, [NotNull] GlobalFilterCriteria criteria) { DateTime endDate, beginDate; AnalysisPreconditions(criteria, statementModel, budgets, out beginDate, out endDate); var result = new OverallPerformanceBudgetResult(); List <BudgetModel> budgetsInvolved = budgets.ForDates(beginDate, endDate).ToList(); result.UsesMultipleBudgets = budgetsInvolved.Count() > 1; var currentBudget = budgetsInvolved.Last(); // Use most recent budget as the current result.DurationInMonths = StatementModel.CalculateDuration(criteria, statementModel.Transactions); CalculateTotalsAndAverage(beginDate, statementModel, budgets, result); result.AnalysesList = new List <BucketPerformanceResult>(); var list = new List <BucketPerformanceResult>(); foreach (var bucket in this.bucketRepository.Buckets) { var bucketCopy = bucket; List <Transaction> query = statementModel.Transactions.Where(t => t.BudgetBucket == bucketCopy).ToList(); var totalSpent = query.Sum(t => t.Amount); var averageSpend = totalSpent / result.DurationInMonths; if (bucket == this.bucketRepository.SurplusBucket) { var budgetedTotal = CalculateBudgetedTotalAmount(beginDate, b => b.Surplus, budgets, result); var perMonthBudget = budgetedTotal / result.DurationInMonths; // Calc an average in case multiple budgets are used and the budgeted amounts are different. var surplusAnalysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = -totalSpent, Balance = budgetedTotal - totalSpent, BudgetTotal = budgetedTotal, Budget = perMonthBudget, AverageSpend = -averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per Month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(surplusAnalysis); continue; } // If the most recent budget does not contain this bucket, then skip it. if (currentBudget.Expenses.Any(e => e.Bucket == bucket)) { var totalBudget = CalculateBudgetedTotalAmount(beginDate, BuildExpenseFinder(bucket), budgets, result); var perMonthBudget = totalBudget / result.DurationInMonths; var analysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = -totalSpent, Balance = totalBudget - totalSpent, BudgetTotal = totalBudget, Budget = perMonthBudget, AverageSpend = -averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per Month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(analysis); continue; } // If the most recent budget does not contain this bucket, then skip it. if (currentBudget.Incomes.Any(i => i.Bucket == bucket)) { var totalBudget = CalculateBudgetedTotalAmount(beginDate, BuildIncomeFinder(bucket), budgets, result); var perMonthBudget = totalBudget / result.DurationInMonths; var analysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = totalSpent, Balance = totalBudget - totalSpent, BudgetTotal = totalBudget, Budget = perMonthBudget, AverageSpend = averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(analysis); } } result.AnalysesList = list.OrderByDescending(a => a.Percent).ToList(); return(result); }
/// <summary> /// Analyses the supplied statement using the supplied budget within the criteria given to this method. /// </summary> /// <param name="budgets">The current budgets collection.</param> /// <param name="criteria">The criteria to limit the analysis.</param> /// <param name="statementModel">The current statement model.</param> /// <exception cref="BudgetException"> /// Will be thrown if no budget is supplied or if no budget can be found for the dates /// given in the criteria. /// </exception> /// <exception cref="ArgumentException">If statement or budget is null.</exception> public virtual OverallPerformanceBudgetResult Analyse(StatementModel statementModel, BudgetCollection budgets, [NotNull] GlobalFilterCriteria criteria) { DateTime endDate, beginDate; AnalysisPreconditions(criteria, statementModel, budgets, out beginDate, out endDate); var result = new OverallPerformanceBudgetResult(); List<BudgetModel> budgetsInvolved = budgets.ForDates(beginDate, endDate).ToList(); result.UsesMultipleBudgets = budgetsInvolved.Count() > 1; var currentBudget = budgetsInvolved.Last(); // Use most recent budget as the current result.DurationInMonths = StatementModel.CalculateDuration(criteria, statementModel.Transactions); CalculateTotalsAndAverage(beginDate, statementModel, budgets, result); result.AnalysesList = new List<BucketPerformanceResult>(); var list = new List<BucketPerformanceResult>(); foreach (var bucket in this.bucketRepository.Buckets) { var bucketCopy = bucket; List<Transaction> query = statementModel.Transactions.Where(t => t.BudgetBucket == bucketCopy).ToList(); var totalSpent = query.Sum(t => t.Amount); var averageSpend = totalSpent / result.DurationInMonths; if (bucket == this.bucketRepository.SurplusBucket) { var budgetedTotal = CalculateBudgetedTotalAmount(beginDate, b => b.Surplus, budgets, result); var perMonthBudget = budgetedTotal / result.DurationInMonths; // Calc an average in case multiple budgets are used and the budgeted amounts are different. var surplusAnalysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = -totalSpent, Balance = budgetedTotal - totalSpent, BudgetTotal = budgetedTotal, Budget = perMonthBudget, AverageSpend = -averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per Month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(surplusAnalysis); continue; } // If the most recent budget does not contain this bucket, then skip it. if (currentBudget.Expenses.Any(e => e.Bucket == bucket)) { var totalBudget = CalculateBudgetedTotalAmount(beginDate, BuildExpenseFinder(bucket), budgets, result); var perMonthBudget = totalBudget / result.DurationInMonths; var analysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = -totalSpent, Balance = totalBudget - totalSpent, BudgetTotal = totalBudget, Budget = perMonthBudget, AverageSpend = -averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per Month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(analysis); continue; } // If the most recent budget does not contain this bucket, then skip it. if (currentBudget.Incomes.Any(i => i.Bucket == bucket)) { var totalBudget = CalculateBudgetedTotalAmount(beginDate, BuildIncomeFinder(bucket), budgets, result); var perMonthBudget = totalBudget / result.DurationInMonths; var analysis = new BucketPerformanceResult { Bucket = bucket, TotalSpent = totalSpent, Balance = totalBudget - totalSpent, BudgetTotal = totalBudget, Budget = perMonthBudget, AverageSpend = averageSpend, BudgetComparedToAverage = string.Format(CultureInfo.CurrentCulture, "Budget per Month: {0:C}, Actual per month: {1:C}", perMonthBudget, -averageSpend) }; list.Add(analysis); } } result.AnalysesList = list.OrderByDescending(a => a.Percent).ToList(); return result; }