#!/usr/bin/python3 import datetime from decimal import * from settings import DATA from prettytable import PrettyTable TWOPLACES = Decimal(10) ** -2 def daterange(start_date, end_date): for n in range(int ((end_date - start_date).days)): yield start_date + datetime.timedelta(n) class PayPeriod: def __init__(self, calculate=False): self.bills = [] self.expenses = DATA.get('expenses') self.delta = None self.beginning = None self.end = None self.total_bills = None self.money_left = None self.total_expenses = None if calculate: self.calculate_budget() def lookup_bills(self): if not self.beginning or not self.end: self.current_pay_period() bill_data = DATA.get('bills') for day in daterange(self.beginning, self.end): x = bill_data.get(day.day) if x: for bill in x: self.bills.append(bill) def pay_period_delta(self): period = DATA.get('pay_period') if not period: raise Error unit = period.get('unit') value = period.get('value') if unit == 'week': self.delta = datetime.timedelta(weeks=value) elif unit == 'day': self.delta = datetime.timedelta(days=value) elif unit == 'month': self.delta = value else: raise Error def current_pay_period(self): self.find_pay_period(datetime.date.today()) def next_pay_period(self): if self.delta == None: self.pay_period_delta() next_period = PayPeriod() next_period.find_pay_period(datetime.date.today() + self.delta) next_period.calculate_budget() return next_period def find_pay_period(self, date): if self.delta == None: self.pay_period_delta() pay_date_str = DATA.get('pay_date') if not pay_date_str: raise Error pay_period = DATA.get('pay_period') if not pay_period: raise Error pay_date_list = pay_date_str.split('/') pay_date = datetime.date(int(pay_date_list[0]), int(pay_date_list[1]), int(pay_date_list[2])) beginning = pay_date end = pay_date while date > end: beginning = end end += self.delta self.beginning = beginning self.end = end def calculate_budget(self): if not self.bills: self.lookup_bills() self.total_bills = Decimal(0) for bill in self.bills: self.total_bills += bill.get('amt') self.total_expenses = Decimal(0) for expense in self.expenses: self.total_expenses += expense.get('amt') self.money_left = DATA.get("pay_amount") - self.total_bills - self.total_expenses def print_budget(self): if not self.total_bills: self.calculate_budget() print("\nBills") print("***************************") bills_table = PrettyTable(["Description", "Amount"]) bills_table.align["Amount"] = "r" for bill in self.bills: bills_table.add_row([bill.get('desc'), bill.get('amt').quantize(TWOPLACES)]) bills_table.add_row(["----------", "-----"]) bills_table.add_row(["Total", self.total_bills.quantize(TWOPLACES)]) print(bills_table) print("\nExpenses") print("***************************") expenses_table = PrettyTable(["Description", "Amount"]) expenses_table.align["Amount"] = "r" for expense in self.expenses: expenses_table.add_row([expense.get('desc'), expense.get('amt').quantize(TWOPLACES)]) expenses_table.add_row(["----------", "-----"]) expenses_table.add_row(["Total", self.total_expenses.quantize(TWOPLACES)]) print(expenses_table) print("\nTotals") print("***************************") print("Expenses Total: " + str(self.total_expenses.quantize(TWOPLACES))) print("Money After Bills + Expenses: " + str(self.money_left.quantize(TWOPLACES))) next_period = self.next_pay_period() money_left_next = next_period.money_left print("Money After Bills + Expenses Next: " + str(money_left_next.quantize(TWOPLACES))) if money_left_next <= 0: print("Not enough money left next paycheck!! Expenses being rolled together!") self.expenses += next_period.expenses self.calculate_budget() self.money_left = self.money_left + money_left_next + next_period.total_expenses print("Money left after combining: " + str(self.money_left.quantize(TWOPLACES))) print("\nPercent Expenses") print("***************************") total_perc_expenses = Decimal(0) perc_expenses = PrettyTable(["Description", "Amount"]) perc_expenses.align["Amount"] = "r" for perc_expense in DATA.get("perc_expenses", []): amt = perc_expense.get('perc') * self.money_left total_perc_expenses += amt perc_expenses.add_row([perc_expense.get('desc'), amt.quantize(TWOPLACES)]) perc_expenses.add_row(["----------", "-----"]) perc_expenses.add_row(["Total", total_perc_expenses.quantize(TWOPLACES)]) print(perc_expenses) money_left_perc = self.money_left - total_perc_expenses print("\nAllowances") print("***************************") allowance_table = PrettyTable(["Description", "Amount"]) allowance_table.align["Amount"] = "r" for allowance in DATA.get("allowances", []): amt = allowance.get('perc') * money_left_perc allowance_table.add_row([allowance.get('desc'), amt.quantize(TWOPLACES)]) print(allowance_table) pay_period = PayPeriod() pay_period.print_budget()