Esempio n. 1
0
        public void NoExpenses_Test()
        {
            // Arrange

            var account      = AccountHelper.CreateAccountModel(1);
            var typeEntities = new List <ExpenseType>
            {
                ExpenseTypeHelper.CreateExpenseTypeModel(1, "Food"),
                ExpenseTypeHelper.CreateExpenseTypeModel(2, "Energy")
            };
            var now                = DateTime.Now;
            var oneMonthAgo        = DateTime.Now.AddMonths(-1);
            var twoMonthsAgo       = DateTime.Now.AddMonths(-2);
            var nowName            = DateTimeFormatHelper.GetMonthNameAndYear(now);
            var oneMonthAgoName    = DateTimeFormatHelper.GetMonthNameAndYear(oneMonthAgo);
            var twoMonthsAgoName   = DateTimeFormatHelper.GetMonthNameAndYear(twoMonthsAgo);
            var threeMonthsAgoName = DateTimeFormatHelper.GetMonthNameAndYear(DateTime.Now.AddMonths(-3));
            var expenses           = new List <Expense>();
            var incomes            = new List <Income>();
            var savings            = new List <Saving>();

            var service = SetupExpenseService(account, typeEntities, expenses, incomes, savings);

            // Act

            var result = service.GetExpenseSummary(1, null);

            // Assert

            Assert.False(result.HasCurrentBudgetPlan);
            Assert.False(result.HasExpenses);

            Assert.Equal(0, result.TotalExpensesOver12Months);
            Assert.Equal(0, result.AverageExpenses);
            Assert.Equal(0, result.AverageIncomes);
            Assert.Equal(0, result.AverageSavings);

            Assert.Equal(13, result.DetailedExpensesOver12Months.Count);
            Assert.Equal(0, result.DetailedExpensesOver12Months[nowName].ExpenseValue);
            Assert.Equal(0, result.DetailedExpensesOver12Months[oneMonthAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedExpensesOver12Months[twoMonthsAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedExpensesOver12Months[threeMonthsAgoName].ExpenseValue);

            Assert.Equal(7, result.DetailedMovementsOver6Months.Count);
            Assert.Equal(0, result.DetailedMovementsOver6Months[nowName].ExpenseValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[oneMonthAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[twoMonthsAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[nowName].IncomeValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[oneMonthAgoName].IncomeValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[twoMonthsAgoName].IncomeValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].IncomeValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[nowName].SavingValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[oneMonthAgoName].SavingValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[twoMonthsAgoName].SavingValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].SavingValue);

            Assert.Equal(2, result.ExpensesByCategory.Count);

            var c1 = result.ExpensesByCategory.Single(x => x.CategoryId == 1);

            Assert.Equal(0, c1.AverageCostOver12Months);
            Assert.Equal(0, c1.CostCurrentMonth);
            Assert.Equal(0, c1.CostOver12Month);
            Assert.Equal(0, c1.CostPlannedMonthly);
            Assert.Equal(0, c1.CostPreviousMonth);
            Assert.Equal(13, c1.ExpensesByMonth.Count);
            Assert.Equal(0, c1.ExpensesByMonth[nowName].CategoryExpenses);
            Assert.Equal(0, c1.ExpensesByMonth[oneMonthAgoName].CategoryExpenses);
            Assert.Equal(0, c1.ExpensesByMonth[twoMonthsAgoName].CategoryExpenses);
            Assert.Equal(0, c1.ExpensesByMonth[threeMonthsAgoName].CategoryExpenses);

            var c2 = result.ExpensesByCategory.Single(x => x.CategoryId == 2);

            Assert.Equal(0, c2.AverageCostOver12Months);
            Assert.Equal(0, c2.CostCurrentMonth);
            Assert.Equal(0, c2.CostOver12Month);
            Assert.Equal(0, c2.CostPlannedMonthly);
            Assert.Equal(0, c2.CostPreviousMonth);
            Assert.Equal(13, c2.ExpensesByMonth.Count);
            Assert.Equal(0, c2.ExpensesByMonth[nowName].CategoryExpenses);
            Assert.Equal(0, c2.ExpensesByMonth[oneMonthAgoName].CategoryExpenses);
            Assert.Equal(0, c2.ExpensesByMonth[twoMonthsAgoName].CategoryExpenses);
            Assert.Equal(0, c2.ExpensesByMonth[threeMonthsAgoName].CategoryExpenses);
        }
        public ExpenseSummary GetExpenseSummary(int accountId, BudgetPlanDetails budgetPlan)
        {
            var account = _bankAccountRepository.GetById(accountId, x => x.Bank, x => x.Currency);

            if (account == null)
            {
                throw new ArgumentException("Account can't be null.");
            }

            var today = DateTime.Now;
            var over12MonthsInterval = new Interval(today, DateTimeUnitEnums.Years, 1);
            var over6MonthsInterval  = new Interval(today, DateTimeUnitEnums.Months, 6);
            var currentMonthInterval = new Interval(today, today);
            var previousInterval     = new Interval(today, DateTimeUnitEnums.Months, 1);

            var categories = _ExpenseTypeRepository.GetList2().GroupBy(x => x.Id).ToDictionary(x => x.Key, y => y.Single());

            var over12MonthsNames = over12MonthsInterval.GetIntervalsByMonth();
            var currentMonthName  = currentMonthInterval.GetSingleMonthName();

            // Retrieve both current month expenses and over 12 months expenses
            var expenses = GetExpenses(new PFM.Services.DTOs.SearchParameters.ExpenseGetListSearchParameters
            {
                AccountId = accountId,
                StartDate = over12MonthsInterval.StartDate,
                EndDate   = currentMonthInterval.EndDate
            });

            // Reset the start date to the first movement (First day of the same month)
            over12MonthsInterval.StartDate = DateTimeFormatHelper.GetFirstDayOfMonth(
                expenses.Any() ?
                expenses.OrderBy(x => x.DateExpense).First().DateExpense :
                today);

            // Count the number of months in the interval
            var nbMonthInterval = over12MonthsInterval.Count(DateTimeUnitEnums.Months);

            if (nbMonthInterval == 0)
            {
                nbMonthInterval = 1; // No expenses -> no division by zero
            }
            // Get current budget plan if it exists
            var budgetPlanByCategory =
                budgetPlan?.ExpenseTypes.GroupBy(x => x.ExpenseType.Id).ToDictionary(x => x.Key, y => y.Single().ExpectedValue)
                ?? categories.ToDictionary(x => x.Key, y => (decimal)0.00);

            var expensesByCategories = expenses.Any()
                ? expenses.GroupBy(x => x.ExpenseTypeId).ToDictionary(x => x.Key, y => y.ToList())
                : categories.ToDictionary(x => x.Key, y => new List <ExpenseList>());

            var expensesByCategory = new List <ExpenseSummaryByCategory>();

            foreach (var exp in expensesByCategories)
            {
                var category              = categories[exp.Key];
                var expensesCurrentMonth  = exp.Value.Where(x => currentMonthInterval.IsBetween(x.DateExpense)).ToList();
                var expensesPreviousMonth = exp.Value.Where(x => previousInterval.IsBetween(x.DateExpense)).ToList();
                var expensesOver12Months  = exp.Value.Where(x => over12MonthsInterval.IsBetween(x.DateExpense)).ToList();

                // ReSharper disable once UseObjectOrCollectionInitializer
                var expenseSummary = new ExpenseSummaryByCategory();
                expenseSummary.CurrencySymbol          = account.Currency.Symbol;
                expenseSummary.CategoryId              = category.Id;
                expenseSummary.CategoryName            = category.Name;
                expenseSummary.CategoryColor           = category.GraphColor;
                expenseSummary.CostCurrentMonth        = expensesCurrentMonth.Sum(x => x.Cost);
                expenseSummary.CostPreviousMonth       = expensesPreviousMonth.Sum(x => x.Cost);
                expenseSummary.CostPlannedMonthly      = budgetPlanByCategory.ContainsKey(exp.Key) ? budgetPlanByCategory[exp.Key] : 0;
                expenseSummary.CostOver12Month         = expensesOver12Months.Sum(x => x.Cost);
                expenseSummary.AverageCostOver12Months = expenseSummary.CostOver12Month / nbMonthInterval;

                // Retrieve the expenses per months (details and summary)
                foreach (var month in over12MonthsNames)
                {
                    var interval   = month.Value;
                    var expByMonth = exp.Value.Where(x => interval.IsBetween(x.DateExpense)).ToList();

                    expenseSummary.Expenses.Add(month.Key, expByMonth);
                    expenseSummary.ExpensesByMonth.Add(month.Key, new ExpenseSummaryByCategoryAndByMonth(expByMonth.Sum(x => x.Cost)));
                }
                expenseSummary.Expenses.Add(currentMonthName, expensesCurrentMonth);
                expenseSummary.ExpensesByMonth.Add(currentMonthName, new ExpenseSummaryByCategoryAndByMonth(expensesCurrentMonth.Sum(x => x.Cost)));

                expensesByCategory.Add(expenseSummary);
            }

            var totalExpensesOver12Months = expenses.Where(x => over12MonthsInterval.IsBetween(x.DateExpense)).Sum(x => x.Cost);

            // Get actual/expected expenses by month for last 12 Months
            var budgetPlanExpenses           = budgetPlanByCategory.Values.Sum(x => x);
            var detailedExpensesOver12Months = new Dictionary <string, ExpenseSummaryByMonth>();

            foreach (var month in over12MonthsNames)
            {
                var interval   = month.Value;
                var expByMonth = expenses.Where(x => interval.IsBetween(x.DateExpense)).Sum(x => x.Cost);
                detailedExpensesOver12Months.Add(month.Key, new ExpenseSummaryByMonth()
                {
                    ExpenseValue         = expByMonth,
                    ExpenseExpectedValue = budgetPlanExpenses
                });
            }
            detailedExpensesOver12Months.Add(currentMonthName, new ExpenseSummaryByMonth()
            {
                ExpenseValue         = expenses.Where(x => currentMonthInterval.IsBetween(x.DateExpense)).Sum(x => x.Cost),
                ExpenseExpectedValue = budgetPlanExpenses
            });

            var incomes = _incomeRepository.GetList2().Where(x => x.AccountId == accountId && x.DateIncome >= over12MonthsInterval.StartDate && x.DateIncome < currentMonthInterval.EndDate).ToList();
            var savings = _savingRepository.GetList2().Where(x => x.AccountId == accountId && x.DateSaving >= over12MonthsInterval.StartDate && x.DateSaving < currentMonthInterval.EndDate).ToList();

            // Get the incomes/expenses/savings by month for last 6 months
            var over6MonthsNames             = over6MonthsInterval.GetIntervalsByMonth();
            var detailedMovementsOver6Months = new Dictionary <string, ExpenseSummaryByMonth>();

            foreach (var month in over6MonthsNames)
            {
                var interval      = month.Value;
                var incomeByMonth = incomes.Where(x => interval.IsBetween(x.DateIncome)).Sum(x => x.Cost);
                var savingByMonth = savings.Where(x => interval.IsBetween(x.DateSaving)).Sum(x => x.Amount);
                detailedMovementsOver6Months.Add(month.Key, new ExpenseSummaryByMonth()
                {
                    ExpenseValue = detailedExpensesOver12Months[month.Key].ExpenseValue,
                    IncomeValue  = incomeByMonth,
                    SavingValue  = savingByMonth
                });
            }
            detailedMovementsOver6Months.Add(currentMonthName, new ExpenseSummaryByMonth()
            {
                ExpenseValue = detailedExpensesOver12Months[currentMonthName].ExpenseValue,
                IncomeValue  = incomes.Where(x => currentMonthInterval.IsBetween(x.DateIncome)).Sum(x => x.Cost),
                SavingValue  = savings.Where(x => currentMonthInterval.IsBetween(x.DateSaving)).Sum(x => x.Amount)
            });

            var ExpenseSummary = new ExpenseSummary()
            {
                Account                      = Mapper.Map <AccountDetails>(account),
                ExpensesByCategory           = expensesByCategory.OrderByDescending(x => x.CostCurrentMonth).ToList(),
                LabelCurrentMonth            = DateTimeFormatHelper.GetMonthNameAndYear(today),
                LabelPreviousMonth           = DateTimeFormatHelper.GetMonthNameAndYear(today.AddMonths(-1)),
                BudgetPlanName               = budgetPlan != null ? budgetPlan.Name : string.Empty,
                AccountName                  = account.Name,
                DisplayDashboard             = true,
                CurrencySymbol               = account.Currency.Symbol,
                HasCurrentBudgetPlan         = budgetPlan != null,
                HasExpenses                  = expenses.Any(),
                HasCategories                = categories.Any(),
                TotalExpensesOver12Months    = totalExpensesOver12Months,
                DetailedExpensesOver12Months = detailedExpensesOver12Months,
                DetailedMovementsOver6Months = detailedMovementsOver6Months,
                CurrentMonthTotalExpense     = expenses.Where(x => currentMonthInterval.IsBetween(x.DateExpense)).Sum(x => x.Cost),
                AverageExpenses              = expenses.Where(x => over12MonthsInterval.IsBetween(x.DateExpense)).Sum(x => x.Cost) / nbMonthInterval,
                AverageIncomes               = incomes.Where(x => over12MonthsInterval.IsBetween(x.DateIncome)).Sum(x => x.Cost) / nbMonthInterval,
                AverageSavings               = savings.Where(x => over12MonthsInterval.IsBetween(x.DateSaving)).Sum(x => x.Amount) / nbMonthInterval
            };

            return(ExpenseSummary);
        }
Esempio n. 3
0
        public void WithExpensesIncomesAndSavings_Test()
        {
            // Arrange

            var account      = AccountHelper.CreateAccountModel(1);
            var typeEntities = new List <ExpenseType>
            {
                ExpenseTypeHelper.CreateExpenseTypeModel(1, "Food"),
                ExpenseTypeHelper.CreateExpenseTypeModel(2, "Energy")
            };
            var i                  = 1;
            var now                = DateTime.Now;
            var oneMonthAgo        = DateTime.Now.AddMonths(-1);
            var twoMonthsAgo       = DateTime.Now.AddMonths(-2);
            var nowName            = DateTimeFormatHelper.GetMonthNameAndYear(now);
            var oneMonthAgoName    = DateTimeFormatHelper.GetMonthNameAndYear(oneMonthAgo);
            var twoMonthsAgoName   = DateTimeFormatHelper.GetMonthNameAndYear(twoMonthsAgo);
            var threeMonthsAgoName = DateTimeFormatHelper.GetMonthNameAndYear(DateTime.Now.AddMonths(-3));
            var expenses           = new List <Expense>()
            {
                ExpenseHelper.CreateExpenseModel(i++, now, 100, 1),
                ExpenseHelper.CreateExpenseModel(i++, now, 200, 2),
                ExpenseHelper.CreateExpenseModel(i++, now, 300, 2),
                ExpenseHelper.CreateExpenseModel(i++, oneMonthAgo, 200, 1),
                ExpenseHelper.CreateExpenseModel(i++, oneMonthAgo.AddDays(-1), 100, 2),
                ExpenseHelper.CreateExpenseModel(i++, oneMonthAgo.AddDays(-2), 150, 2),
                ExpenseHelper.CreateExpenseModel(i++, twoMonthsAgo, 300, 2),
                ExpenseHelper.CreateExpenseModel(i++, twoMonthsAgo.AddDays(-2), 100, 1),
                ExpenseHelper.CreateExpenseModel(i, twoMonthsAgo.AddDays(-1), 600, 2)
            };
            var incomes = new List <Income>()
            {
                IncomeHelper.CreateIncomeModel(1, now, 1000, 1),
                IncomeHelper.CreateIncomeModel(2, now.AddDays(-1), 300, 1),
                IncomeHelper.CreateIncomeModel(3, oneMonthAgo, 1200, 1),
                IncomeHelper.CreateIncomeModel(4, twoMonthsAgo, 1400, 1)
            };
            var savings = new List <Saving>()
            {
                SavingHelper.CreateSavingModel(1, now, 500, 1),
                SavingHelper.CreateSavingModel(2, oneMonthAgo, 700, 1),
                SavingHelper.CreateSavingModel(3, twoMonthsAgo, 600, 1)
            };

            var service = SetupExpenseService(account, typeEntities, expenses, incomes, savings);

            // Act

            var result = service.GetExpenseSummary(1, null);

            // Assert
            Assert.True(result.HasExpenses);
            Assert.False(result.HasCurrentBudgetPlan);

            Assert.Equal(1450, result.TotalExpensesOver12Months);
            Assert.Equal(725, result.AverageExpenses);
            Assert.Equal(1300, result.AverageIncomes);
            Assert.Equal(650, result.AverageSavings);

            Assert.Equal(13, result.DetailedExpensesOver12Months.Count);
            Assert.Equal(600, result.DetailedExpensesOver12Months[nowName].ExpenseValue);
            Assert.Equal(450, result.DetailedExpensesOver12Months[oneMonthAgoName].ExpenseValue);
            Assert.Equal(1000, result.DetailedExpensesOver12Months[twoMonthsAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedExpensesOver12Months[threeMonthsAgoName].ExpenseValue);

            Assert.Equal(7, result.DetailedMovementsOver6Months.Count);
            Assert.Equal(600, result.DetailedMovementsOver6Months[nowName].ExpenseValue);
            Assert.Equal(450, result.DetailedMovementsOver6Months[oneMonthAgoName].ExpenseValue);
            Assert.Equal(1000, result.DetailedMovementsOver6Months[twoMonthsAgoName].ExpenseValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].ExpenseValue);
            Assert.Equal(1300, result.DetailedMovementsOver6Months[nowName].IncomeValue);
            Assert.Equal(1200, result.DetailedMovementsOver6Months[oneMonthAgoName].IncomeValue);
            Assert.Equal(1400, result.DetailedMovementsOver6Months[twoMonthsAgoName].IncomeValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].IncomeValue);
            Assert.Equal(500, result.DetailedMovementsOver6Months[nowName].SavingValue);
            Assert.Equal(700, result.DetailedMovementsOver6Months[oneMonthAgoName].SavingValue);
            Assert.Equal(600, result.DetailedMovementsOver6Months[twoMonthsAgoName].SavingValue);
            Assert.Equal(0, result.DetailedMovementsOver6Months[threeMonthsAgoName].SavingValue);
        }