public static BudgetPlanDetails CreateBudgetPlanEditModel(List <ExpenseTypeList> expenditureTypes) { var model = new BudgetPlanDetails() { ExpenseTypes = new List <BudgetPlanExpenseType>() }; foreach (var expenditureType in expenditureTypes) { model.ExpenseTypes.Add(new BudgetPlanExpenseType() { ExpenseType = expenditureType, ExpectedValue = 100 }); } return(model); }
/// <summary> /// Create a budget plan. /// </summary> /// <param name="budgetPlanDetails"></param> /// <param name="accountId"></param> public void CreateBudgetPlan(BudgetPlanDetails budgetPlanDetails, int accountId) { var budgetPlan = Mapper.Map <BudgetPlan>(budgetPlanDetails); _budgetPlanRepository.Create(budgetPlan); foreach (var ExpenseType in budgetPlanDetails.ExpenseTypes) { var plannedExpense = new BudgetByExpenseType { Budget = ExpenseType.ExpectedValue, ExpenseTypeId = ExpenseType.ExpenseType.Id, BudgetPlanId = budgetPlan.Id, AccountId = accountId }; // Account ID is defined at BudgetByExpenseType time because at first, I wanted to plan budget through several accounts. // It might evolve later so for now, I keep it here, independently from BudgetByExpenseType. _budgetByExpenseTypeRepository.Create(plannedExpense); } }
/// <summary> /// Edit a budget plan. /// </summary> /// <param name="budgetPlanDetails"></param> /// <param name="accountId"></param> public void EditBudgetPlan(BudgetPlanDetails budgetPlanDetails, int accountId) { var budgetPlan = _budgetPlanRepository.GetById(budgetPlanDetails.Id); budgetPlan.Name = budgetPlanDetails.Name; budgetPlan.ExpectedIncomes = budgetPlanDetails.ExpectedIncomes; budgetPlan.ExpectedSavings = budgetPlanDetails.ExpectedSavings; _budgetPlanRepository.Update(budgetPlan); var existingBudgetPlanExpenses = _budgetByExpenseTypeRepository.GetList2(x => x.ExpenseType) .Where(x => x.BudgetPlanId == budgetPlanDetails.Id); foreach (var budgetExpenseType in budgetPlanDetails.ExpenseTypes) { var existingBudgetExpenseType = existingBudgetPlanExpenses.SingleOrDefault(x => x.ExpenseType.Id == budgetExpenseType.ExpenseType.Id); if (existingBudgetExpenseType == null) { // Add var plannedExpense = new BudgetByExpenseType() { Budget = budgetExpenseType.ExpectedValue, ExpenseTypeId = budgetExpenseType.ExpenseType.Id, BudgetPlanId = budgetPlanDetails.Id, AccountId = accountId }; _budgetByExpenseTypeRepository.Create(plannedExpense); } else { // Update existingBudgetExpenseType.Budget = budgetExpenseType.ExpectedValue; _budgetByExpenseTypeRepository.Update(existingBudgetExpenseType); } } }
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); }
public BudgetPlanDetails BuildBudgetPlan(int accountId, int?budgetPlanId = null) { var currencySymbol = _bankAccountRepository.GetById(accountId, x => x.Currency).Currency.Symbol; var today = DateTime.Now; var over12MonthsInterval = new Interval(today, DateTimeUnitEnums.Years, 1); var previousInterval = new Interval(today, DateTimeUnitEnums.Months, 1); var firstOfNextMonth = DateTimeFormatHelper.GetFirstDayOfMonth(today.AddMonths(1)); // Retrieve the categories var categories = _ExpenseTypeRepository.GetList2().GroupBy(x => x.Id).ToDictionary(x => x.Key, y => y.Single()); // Retrieve the expenses over the last 12 months (excluding current month) var expensesOver12Months = _ExpenseRepository.GetByParameters(new ExpenseGetListSearchParameters() { AccountId = accountId, StartDate = over12MonthsInterval.StartDate, EndDate = over12MonthsInterval.EndDate }); // Group by category the expenses over the last 12 months var expensesOver12MonthsByCategory = expensesOver12Months.GroupBy(x => x.ExpenseTypeId).ToDictionary(x => x.Key, y => y.ToList()); over12MonthsInterval.StartDate = DateTimeFormatHelper.GetFirstDayOfMonth( expensesOver12Months.Any() ? expensesOver12Months.OrderBy(x => x.DateExpense).First().DateExpense : today); var nbMonthInterval = over12MonthsInterval.Count(DateTimeUnitEnums.Months); if (nbMonthInterval == 0) { nbMonthInterval = 1; // No expenses -> no division by zero } // Retrieve the expenses last months and group by category var lastMonthExpenses = expensesOver12Months.Where(x => previousInterval.IsBetween(x.DateExpense)).ToList(); var lastMonthExpensesByCategory = lastMonthExpenses.GroupBy(x => x.ExpenseTypeId).ToDictionary(x => x.Key, y => y.ToList()); // Get the current Budget Plan for the account. If none, returns a default of cost of 0.00 var currentBudgetPlan = GetCurrent(accountId); var currentBudgetPlanByCategory = currentBudgetPlan?.ExpenseTypes .GroupBy(x => x.ExpenseType.Id) .ToDictionary(x => x.Key, y => y.Single().ExpectedValue); // Get the existing Budget Plan for the provided ID. If none, returns a default of cost of 0.00 var existingBudgetPlan = budgetPlanId.HasValue ? GetById(budgetPlanId.Value) : null; var existingBudgetPlanByCategory = existingBudgetPlan?.ExpenseTypes.GroupBy(x => x.ExpenseType.Id).ToDictionary(x => x.Key, y => y.Single().ExpectedValue); BudgetPlanDetails budgetPlan = null; if (existingBudgetPlan != null) { budgetPlan = new BudgetPlanDetails() { Id = existingBudgetPlan.Id, Name = existingBudgetPlan.Name, ExpenseTypes = new List <BudgetPlanExpenseType>(), CurrencySymbol = currencySymbol, StartDate = existingBudgetPlan.StartDate, EndDate = existingBudgetPlan.EndDate, PlannedStartDate = firstOfNextMonth, HasCurrentBudgetPlan = currentBudgetPlan != null, BudgetPlanName = currentBudgetPlan?.Name }; } else { budgetPlan = new BudgetPlanDetails() { ExpenseTypes = new List <BudgetPlanExpenseType>(), CurrencySymbol = currencySymbol, HasCurrentBudgetPlan = currentBudgetPlan != null, BudgetPlanName = currentBudgetPlan?.Name }; } foreach (var category in categories) { var expectedValue = 0.00M; var currentBudgetPlanValue = 0.00M; if (currentBudgetPlan != null) { currentBudgetPlanValue = currentBudgetPlanByCategory.ContainsKey(category.Key) ? currentBudgetPlanByCategory[category.Key] : 0.00M; } if (existingBudgetPlan != null) { expectedValue = existingBudgetPlanByCategory.ContainsKey(category.Key) ? existingBudgetPlanByCategory[category.Key] : 0.00M; } else if (currentBudgetPlan != null) { expectedValue = currentBudgetPlanValue; } var previousMonthValue = lastMonthExpensesByCategory.ContainsKey(category.Key) ? lastMonthExpensesByCategory[category.Key].Sum(x => x.Cost) : 0.00M; var averageMonthValue = expensesOver12MonthsByCategory.ContainsKey(category.Key) ? expensesOver12MonthsByCategory[category.Key].Sum(x => x.Cost) : 0.00M; var mappedCategory = Mapper.Map <ExpenseTypeList>(category.Value); var budgetPlanByCategory = new BudgetPlanExpenseType { CurrencySymbol = budgetPlan.CurrencySymbol, ExpenseType = mappedCategory, ExpectedValue = expectedValue, PreviousMonthValue = previousMonthValue, CurrentBudgetPlanValue = currentBudgetPlanValue, AverageMonthValue = averageMonthValue / nbMonthInterval }; budgetPlan.ExpenseTypes.Add(budgetPlanByCategory); } budgetPlan.ExpensePreviousMonthValue = lastMonthExpenses.Sum(x => x.Cost); budgetPlan.ExpenseAverageMonthValue = expensesOver12Months.Sum(x => x.Cost) / nbMonthInterval; budgetPlan.ExpenseCurrentBudgetPlanValue = currentBudgetPlan?.ExpenseTypes.Sum(x => x.ExpectedValue); var incomes = _incomeRepository.GetList2().Where(x => x.AccountId == accountId).ToList(); budgetPlan.IncomeCurrentBudgetPlanValue = currentBudgetPlan?.ExpectedIncomes; budgetPlan.IncomePreviousMonthValue = incomes.Where(x => previousInterval.IsBetween(x.DateIncome)).Sum(x => x.Cost); budgetPlan.IncomeAverageMonthValue = incomes.Where(x => over12MonthsInterval.IsBetween(x.DateIncome)).Sum(x => x.Cost) / nbMonthInterval; budgetPlan.ExpectedIncomes = existingBudgetPlan?.ExpectedIncomes ?? budgetPlan.IncomePreviousMonthValue; var savings = _savingRepository.GetList2().Where(x => x.AccountId == accountId).ToList(); budgetPlan.SavingCurrentBudgetPlanValue = currentBudgetPlan?.ExpectedSavings; budgetPlan.SavingPreviousMonthValue = savings.Where(x => previousInterval.IsBetween(x.DateSaving)).Sum(x => x.Amount); budgetPlan.SavingAverageMonthValue = savings.Where(x => over12MonthsInterval.IsBetween(x.DateSaving)).Sum(x => x.Amount) / nbMonthInterval; budgetPlan.ExpectedSavings = existingBudgetPlan?.ExpectedSavings ?? budgetPlan.SavingPreviousMonthValue; return(budgetPlan); }
public ExpenseSummary GetExpenseSummary(int accountId, [FromBody] BudgetPlanDetails budgetPlan) { return(_ExpenseService.GetExpenseSummary(accountId, budgetPlan)); }
public void Edit(int accountId, [FromBody] BudgetPlanDetails budgetPlanDetails) { _BudgetPlanService.EditBudgetPlan(budgetPlanDetails, accountId); }
public void Create(int accountId, [FromBody] BudgetPlanDetails budgetPlanDetails) { _BudgetPlanService.CreateBudgetPlan(budgetPlanDetails, accountId); }