public decimal FutureValue(DateTime futureDate, decimal?netPay) { try { Logger.Instance.Calculation($"FutureValue"); var payperiods = PayPeriodsTilDue(futureDate); var date = DateTime.Today; var billManager = new BillManager(); var billsFromDb = billManager.GetAllBills(); var bills = new Dictionary <string, string> { { "currentDate", DateTime.Today.ToShortDateString() }, { "endDate", DateTime.Today.Day <= 14 ? new DateTime(date.Year, date.Month, 15).ToShortDateString() : new DateTime(date.Year, date.Month, LastDayOfMonth(date).Day).ToShortDateString() }, { "periodCosts", "0" }, { "totalCosts", "0" }, { "totalSavings", "0" } }; foreach (var bill in billsFromDb) { bills.Add(bill.Name, bill.DueDate.ToShortDateString()); } for (var i = 0; i < payperiods; i++) { bills = UpdateBillDueDates(bills); bills = UpdateTotalCosts(bills); SetCurrentAndEndDate(bills); decimal?savings = Convert.ToDecimal(bills["totalSavings"]); var periodCosts = Convert.ToDecimal(bills["periodCosts"]); savings += netPay - periodCosts; bills["totalSavings"] = savings.ToString(); } //var cost = Convert.ToDecimal(bills["periodCosts"]); var save = Convert.ToDecimal(bills["totalSavings"]); Logger.Instance.Calculation($"FutureValue({futureDate:d}, {netPay}) returned {save}"); return(save); } catch (Exception e) { throw e; } }
// GET: Bills public ActionResult Index() { try { Logger.Instance.DataFlow("Index"); BillViewModel billVM = new BillViewModel(); billVM.Bills = _billManager.GetAllBills(); billVM.Metrics = _billManager.GetBillMetrics(); return(View(billVM)); } catch (Exception e) { Logger.Instance.Error(e); return(View(new BillViewModel())); } }
public decimal DiscretionarySpendingByDateRange(DateTime begin, DateTime end) { try { Logger.Instance.Calculation($"DiscretionarySpendingByDateRange"); var transactionManager = new TransactionManager(); var transactions = transactionManager.GetTransactionsBetweenDates(begin, end); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var isBill = false; var ret = 0m; foreach (var transaction in transactions) { foreach (var bill in bills) { // If the bill name matches the transaction payee, count the transaction as a bill (mandatory expense) if (bill.Name.Equals(transaction.Payee)) { isBill = true; Logger.Instance.Calculation($"{transaction.Amount}: {transaction.Payee} transaction is a bill"); } else { Logger.Instance.Calculation($"{transaction.Amount}: {transaction.Payee} transaction is not a bill"); } } // If transaction is not a bill, add to discretionary spending total if (isBill) { continue; } ret += transaction.Amount; Logger.Instance.Calculation($"{transaction.Amount} added to discretionary spending total"); } Logger.Instance.Calculation($"{ret} total discretionary spending from {begin:d} to {end:d}"); return(ret); } catch (Exception e) { Logger.Instance.Error(e); return(0.0m); } }
private Dictionary <string, string> UpdateTotalCosts(Dictionary <string, string> billsDictionary) { try { Logger.Instance.Calculation($"UpdateTotalCosts"); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var currentDate = Convert.ToDateTime(billsDictionary["currentDate"]); var endDate = Convert.ToDateTime(billsDictionary["endDate"]); var expenses = 0.0m; billsDictionary["periodCosts"] = "0"; foreach (var bill in billsDictionary) { if (bill.Key == "currentDate" || bill.Key == "endDate" || bill.Key == "periodCosts" || bill.Key == "totalSavings" || bill.Key == "totalCosts") { continue; } var dueDate = Convert.ToDateTime(bill.Value); if (!(dueDate >= currentDate && dueDate <= endDate)) { continue; } expenses += bills.Where(b => b.Name == bill.Key).Select(b => b.AmountDue).FirstOrDefault(); Logger.Instance.Calculation($"{expenses} added to {bill.Key}"); } var billCosts = Convert.ToDecimal(billsDictionary["totalCosts"]); billsDictionary["totalCosts"] = (expenses + billCosts).ToString(CultureInfo.InvariantCulture); Logger.Instance.Calculation($"{expenses + billCosts} added to total costs (expenses: {expenses} + bill costs: {billCosts})"); billsDictionary["periodCosts"] = expenses.ToString(CultureInfo.InvariantCulture); Logger.Instance.Calculation($"expenses: {expenses} added to period costs"); return(billsDictionary); } catch (Exception e) { Logger.Instance.Error(e); return(null); } }
public Dictionary <string, decimal> GetPaycheckContributionsDict() { try { var accountManager = new AccountManager(); var accounts = accountManager.GetAllAccounts(); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var accountContribution = new Dictionary <string, decimal>(); //Zeros out all accounts req paycheck contributions foreach (var account in accounts) { account.PaycheckContribution = 0.0m;; } // update suggested paycheck contributions for bills foreach (var bill in bills) { var billTotal = bill.AmountDue; Logger.Instance.Calculation($"{billTotal} due on {bill.DueDate} for {bill.Name}"); // get the account assigned to the bill bill.Account = accounts.FirstOrDefault(a => a.Id == bill.AccountId); if (bill.Account != null && bill.Account.ExcludeFromSurplus) { continue; } //TODO: Needs to account for all pay frequencies //TODO: Suggested contribution assumes payday twice a month. need to update to include other options if (bill.Account == null) { continue; } var contribution = 0.0m; switch (bill.PaymentFrequency) { case FrequencyEnum.Annually: contribution = billTotal / 24; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.SemiAnnually: contribution = billTotal / 12; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.Quarterly: contribution = billTotal / 6; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.SemiMonthly: // every 2 months contribution = billTotal / 4; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.Monthly: contribution = billTotal / 2; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.Weekly: contribution = billTotal * 2; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.BiWeekly: contribution = billTotal; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; case FrequencyEnum.Daily: break; default: contribution = billTotal / 2; if (accountContribution.ContainsKey(bill.Account.Name)) { accountContribution[bill.Account.Name] += contribution; } else { accountContribution.Add(bill.Account.Name, contribution); } Logger.Instance.Calculation($"{Math.Round(contribution, 2)} added to {bill.Account.Name}.SuggestedContribution"); break; } } return(accountContribution); } catch (Exception e) { Console.WriteLine(e); throw; } }
/// <summary> /// Updates database Bills.DueDate if the previous due date has passed /// </summary> public void UpdateBillDueDates() { try { Logger.Instance.Calculation($"UpdateBillDueDates"); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var beginDate = DateTime.Today; foreach (var bill in bills) { if (bill.DueDate.Date > beginDate) { continue; } var frequency = bill.PaymentFrequency; var dueDate = bill.DueDate; var newDueDate = dueDate; /* Updates bill due date to the current due date * while loop handles due date updates, regardless of how out of date they are */ while (newDueDate < beginDate) { switch (frequency) { case FrequencyEnum.Daily: newDueDate = newDueDate.AddDays(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Weekly: newDueDate = newDueDate.AddDays(7); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.BiWeekly: newDueDate = newDueDate.AddDays(14); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Monthly: newDueDate = newDueDate.AddMonths(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.SemiMonthly: newDueDate = newDueDate.AddDays(15); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Quarterly: newDueDate = newDueDate.AddMonths(3); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.SemiAnnually: newDueDate = newDueDate.AddMonths(6); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Annually: newDueDate = newDueDate.AddYears(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; default: throw new ArgumentOutOfRangeException(); } } bill.DueDate = newDueDate; _db.Entry(bill).State = EntityState.Modified; Logger.Instance.Calculation($"{bill.Name} due date of {dueDate:d} updated to {newDueDate:d}"); if (!AddNewExpenseToDb(bill)) { return; } } _db.SaveChanges(); } catch (Exception e) { Logger.Instance.Error(e); } }
//TODO: Improve date range handling /// <summary> /// Returns summation of bills within the date range of the begin and end parameters /// </summary> /// <param name="begin">start date of the date range</param> /// <param name="end">end date of the date range</param> /// <param name="onlyMandatory">sumates only mandatory expenses</param> /// <returns></returns> public decimal ExpensesByDateRange(DateTime begin, DateTime end, bool onlyMandatory = false) { try { Logger.Instance.Calculation($"Expenses by DateRange"); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var expenses = 0m; foreach (var bill in bills) { //if (bill.DueDate.Date < beginDate) continue; var frequency = bill.PaymentFrequency; var dueDate = bill.DueDate; var newDueDate = dueDate; Logger.Instance.Calculation($"{bill.Name} original due date is {dueDate:d}"); //TODO: Fix semi-monthly bills being added 3 times (31st, 16th, 1st) while (newDueDate >= begin) { switch (frequency) { case FrequencyEnum.Daily: newDueDate = newDueDate.AddDays(-1); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.Weekly: newDueDate = newDueDate.AddDays(-7); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.BiWeekly: newDueDate = newDueDate.AddDays(-14); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.Monthly: newDueDate = newDueDate.AddMonths(-1); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.SemiMonthly: newDueDate = newDueDate.AddDays(-15); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.Quarterly: newDueDate = newDueDate.AddMonths(-3); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.SemiAnnually: newDueDate = newDueDate.AddMonths(-6); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; case FrequencyEnum.Annually: newDueDate = newDueDate.AddYears(-1); Logger.Instance.Calculation($"{bill.Name} new due date is {newDueDate:d}"); break; default: throw new ArgumentOutOfRangeException(); } // adds expense only if the bill due date falls within the date range if (newDueDate < begin || newDueDate >= end) { continue; } expenses += bill.AmountDue; Logger.Instance.Calculation($"Expenses: {expenses} added to {bill.Name}.AmountDue"); } } return(expenses); } catch (Exception e) { Logger.Instance.Error(e); return(0.0m); } }
/// <summary> /// Returns Dictionary with due dates for all bills for calculating all expenses within a timeframe. Used for calculating future savings /// </summary> /// <param name="billsDictionary"></param> /// <returns></returns> private Dictionary <string, string> UpdateBillDueDates(Dictionary <string, string> billsDictionary) { try { Logger.Instance.Calculation($"UpdateBillDueDates"); var billManager = new BillManager(); var bills = billManager.GetAllBills(); var beginDate = Convert.ToDateTime(billsDictionary["currentDate"]); foreach (var bill in bills) { if (bill.DueDate.Date > beginDate) { continue; } var frequency = bill.PaymentFrequency; var dueDate = bill.DueDate; var newDueDate = dueDate; Logger.Instance.Calculation($"{bill.Name} due date {dueDate:d}"); while (newDueDate < beginDate) { switch (frequency) { case FrequencyEnum.Daily: newDueDate = newDueDate.AddDays(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Weekly: newDueDate = newDueDate.AddDays(7); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.BiWeekly: newDueDate = newDueDate.AddDays(14); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Monthly: newDueDate = newDueDate.AddMonths(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.SemiMonthly: newDueDate = newDueDate.AddDays(15); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Quarterly: newDueDate = newDueDate.AddMonths(3); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.SemiAnnually: newDueDate = newDueDate.AddMonths(6); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; case FrequencyEnum.Annually: newDueDate = newDueDate.AddYears(1); Logger.Instance.Calculation($"New due date {newDueDate:d}"); break; default: throw new ArgumentOutOfRangeException(); } billsDictionary[bill.Name] = newDueDate.ToShortDateString(); Logger.Instance.Calculation($"Set due date {newDueDate:d}"); } } return(billsDictionary); } catch (Exception e) { Logger.Instance.Error(e); return(null); } }