diff --git a/TODO b/TODO index 4ad186b..653cd77 100644 --- a/TODO +++ b/TODO @@ -5,9 +5,11 @@ For bills: * estimate future bills/growth: [DONE] - calculate pragmatic min/avg/max/simple [DONE] - need to handle future only bills - - remove bills from Living_Expenses (carefully - but by hand) + [DONE] - remove bills from Living_Expenses - fold future bills into calc so they are processed on the day of the bill - - inflation can then be put to a more realistic quarterly figure + ==> need to factor in future bills based on events (such as health/phone when I quit), car when I settle it... + [DONE] ==> and remove hard-coded future costs (like Ioniq rego/ins) when we do above + - inflation can then be put to a more realistic quarterly figure, and fix up Int Rate, again * might need to be able to mark a specific bill as an outlier - so we ignore the data somehow (think Gas is messing with my bills) - and even electricity, water, etc. for when we were away in Europe but mostly gas/elec diff --git a/calc.py b/calc.py index 1d2b7c5..4523ffe 100644 --- a/calc.py +++ b/calc.py @@ -5,6 +5,23 @@ from defines import END_YEAR # GLOBAL CONSTANTS LEASE = 0 +def bill_amount_today(day, bill_data): + amt=0 + day_str = day.strftime("%Y-%m-%d") + for b in bill_data: + # there may be more than one bill on this day, keep add amount and keep going in loop + if b['bill_date'] == day_str: + amt += b['amount'] + # bills are desc order so if the bill is before the day we are after then stop looking + if b['bill_date'] < day_str: + if amt: + print( f"bill_amt_today for {day_str} has amt={amt}" ) + return amt + #failsafe, doubt this even can occur with bills older than today + if amt: + print( f"bill_amt_today for {day} has amt={amt}" ) + return amt + def add_annotation(finance, dt, total, delta, text): # dont add an annotation for small changes (jic) tm = dt.timestamp() * 1000 @@ -15,7 +32,7 @@ def add_annotation(finance, dt, total, delta, text): finance['annotations'].append( { 'label': text, 'x': tm, 'y': total } ) return -def calculate_savings_depletion(finance): +def calculate_savings_depletion(finance, bill_data): # Extract all the financial data from the database D_Salary = finance['D_Salary'] D_Num_fortnights_pay = finance['D_Num_fortnights_pay'] @@ -93,6 +110,17 @@ def calculate_savings_depletion(finance): current_date = datetime.today() end_date = datetime(END_YEAR, 4, 15) + # TODO: need to refactor Living_Expenses to exclude bills + total=0 + yr=str(current_date.year) + for b in bill_data: + if yr in b['bill_date']: + total += b['amount'] + + print( f"this yr={current_date.year} - total={total}" ) + Living_Expenses -= total + print( f"LE is now={Living_Expenses}" ) + # Calculate daily living expenses daily_living_expenses = Living_Expenses / 365 @@ -134,6 +162,9 @@ def calculate_savings_depletion(finance): # Subtract daily living expenses current_savings -= daily_living_expenses + # TODO: need to see if a date matches a bill's date, if so subtract bill amount + current_savings -= bill_amount_today( current_date, bill_data ) + # Calculate daily interest but apply at the end of the month monthly_interest += current_savings * daily_interest_rate @@ -191,6 +222,7 @@ def calculate_savings_depletion(finance): current_savings += monthly_interest #print(f"{current_date}: interest paid - ${monthly_interest}") monthly_interest = 0 + # monthly increase living expenses by a monthly inflation multiplier Living_Expenses += (Inflation/100.0)/12 * Living_Expenses daily_living_expenses = Living_Expenses / 365 @@ -213,20 +245,20 @@ def calculate_savings_depletion(finance): # Anniversary of Car purchase/balloon so potentially insurance/rego # when I quit, the if we haven't paid the car outright, then need to add rego, but not insurance # if we pay-out the car, then add insurace and rego - if current_date.month == car_balloon_date.month and current_date.day == car_balloon_date.day: - # staying with the lease (0), if I have quit, then pay monthly rego only up to lease date, but full cost after car balloon date - if Ioniq6_future == LEASE: - if current_date.year >= car_balloon_date.year: - current_savings -= (ioniq6_ins + ioniq6_rego) - add_annotation(finance, current_date, current_savings, -(ioniq6_ins+ioniq6_rego), "IONIQ 6 ins/rego" ) - # if we buy car outright, then as long as this anniversary is after buyout date, pay ins and rego - elif current_date.year >= car_buyout_date.year: - current_savings -= (ioniq6_ins + ioniq6_rego) - add_annotation(finance, current_date, current_savings, -(ioniq6_ins+ioniq6_rego), "IONIQ 6 ins/rego" ) +# if current_date.month == car_balloon_date.month and current_date.day == car_balloon_date.day: +# # staying with the lease (0), if I have quit, then pay monthly rego only up to lease date, but full cost after car balloon date +# if Ioniq6_future == LEASE: +# if current_date.year >= car_balloon_date.year: +# current_savings -= (ioniq6_ins + ioniq6_rego) +# add_annotation(finance, current_date, current_savings, -(ioniq6_ins+ioniq6_rego), "IONIQ 6 ins/rego" ) +# # if we buy car outright, then as long as this anniversary is after buyout date, pay ins and rego +# elif current_date.year >= car_buyout_date.year: +# current_savings -= (ioniq6_ins + ioniq6_rego) +# add_annotation(finance, current_date, current_savings, -(ioniq6_ins+ioniq6_rego), "IONIQ 6 ins/rego" ) - if current_date.date() == overseas_trip_date.date(): - current_savings -= Overseas_trip - add_annotation(finance, current_date, current_savings, -Overseas_trip, "O/S trip") +# if current_date.date() == overseas_trip_date.date(): +# current_savings -= Overseas_trip +# add_annotation(finance, current_date, current_savings, -Overseas_trip, "O/S trip") if current_date.date() == mich_present_date.date(): current_savings -= Mich_present diff --git a/db.py b/db.py index 1f12c61..bcc2152 100644 --- a/db.py +++ b/db.py @@ -271,12 +271,17 @@ def get_comp_set_options(finance): conn.close() return -def get_bill_data(): +def get_bill_data(order_by): conn = connect_db(True) cur = conn.cursor() - cur.execute('''SELECT bd.id, bt.id as bill_type_id, bt.name, bd.amount, bd.bill_date, bd.estimated - FROM bill_type bt, bill_data bd - where bt.id = bd.bill_type order by bt.name, bd.bill_date desc''') + if order_by == "order_by_date_only": + cur.execute('''SELECT bd.id, bt.id as bill_type_id, bt.name, bd.amount, bd.bill_date, bd.estimated + FROM bill_type bt, bill_data bd + where bt.id = bd.bill_type order by bd.bill_date desc''') + else: + cur.execute('''SELECT bd.id, bt.id as bill_type_id, bt.name, bd.amount, bd.bill_date, bd.estimated + FROM bill_type bt, bill_data bd + where bt.id = bd.bill_type order by bt.name, bd.bill_date desc''') bd = cur.fetchall() conn.close() return bd diff --git a/main.py b/main.py index 080516e..d504e40 100644 --- a/main.py +++ b/main.py @@ -25,7 +25,8 @@ init_db() def index(): finance_data = get_finance_data() get_comp_set_options(finance_data) - depletion_date, savings_per_fortnight, final_savings = calculate_savings_depletion(finance_data) + bill_data = get_bill_data("order_by_date_only") + depletion_date, savings_per_fortnight, final_savings = calculate_savings_depletion(finance_data, bill_data) BUDGET=get_budget_data(finance_data) if depletion_date: @@ -143,13 +144,13 @@ def update(): @app.route('/bills') def DisplayBillData(): - bill_data = get_bill_data() + bill_data = get_bill_data("order_by_bill_type_then_date") bill_types = get_bill_types() bill_freqs = get_bill_freqs() bill_ui = get_bill_ui() bill_info=process_bill_data(bill_data, bill_types, bill_freqs) total=calc_future_totals(bill_info, bill_types) - bill_data = get_bill_data() + bill_data = get_bill_data("order_by_bill_type_then_date") return render_template('bills.html', bill_data=bill_data, bill_types=bill_types, bill_freqs=bill_freqs, bill_ui=bill_ui, this_year=datetime.today().year, END_YEAR=END_YEAR, total=total ) @app.route('/newbilltype', methods=['POST'])