Compare commits
3 Commits
c49520af7a
...
4389045ed5
| Author | SHA1 | Date | |
|---|---|---|---|
| 4389045ed5 | |||
| b69ec82510 | |||
| 2bd39ab24c |
34
TODO
34
TODO
@@ -1,33 +1,11 @@
|
||||
UI:
|
||||
* use key_dates to highlight when I quit, when we own car
|
||||
|
||||
For bills:
|
||||
Future bills:
|
||||
* longer-term: make the moment we quit / own car trigger new bill creation, and remove hard-coded logic on costs - just use bill_data created
|
||||
- this will then cover handling different bill_types or growth models
|
||||
[DONE] * calc quit date based on finance data
|
||||
[DONE] * calc date of car lease end or buyout
|
||||
* use this to populate bill estimates, so this allows totals / year and simplifies calc.py
|
||||
|
||||
* 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)
|
||||
* 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
|
||||
|
||||
LONGER/HARDER:
|
||||
* need to work out 'first bill' and 'last bill' to auto-fill missing bills based on
|
||||
-- all missing bills follow varying growth models & its by choice -- therefore I need this in DB
|
||||
- ANN: flat, min, avg, max, manual
|
||||
- QTR: flat, qtrly seasonal: min/avg/max/manual, qtrly simple: min/avg/max/manual, annual: min/avg/max/manual
|
||||
- MON: flat, monthly: min/avg/max/manual, annual: min/avg/max/manual
|
||||
-- use this logic to add missing bills (date):
|
||||
-- ANN: missing annual bill, find date based on MM-DD and add new year - given we start with first_bill anyway, will only be used for future bill predictions
|
||||
-- QTR: missing quarterly bill, find date based on MM-DD and ??? - can have missing bilsl in first year
|
||||
-- MON: missing monthly bills, find date based on DD and put in each missing month
|
||||
-- use this logic to add missing bills (amount):
|
||||
-- ANN: future only, so add ann_growth (based on drop-down) for each future year
|
||||
-- QTR: add growth (based on drop-down) for each future year
|
||||
-- MON: add growth (based on drop-down) for each future year
|
||||
|
||||
MUCH LONGER/HARDER:
|
||||
potentially for each bill_type, there are unique extras - e.g. THIS feels too hard:
|
||||
water has 2 fixed charges (water & sewerage) and then a consumption charge (per ML)
|
||||
elec has 1 fixe charge (daily) and then consumption (per kwh) BUT, also daily solar rate
|
||||
gas has fixed charge and consumption
|
||||
internet, kayo is monthly fixed (but can go up sometimes)
|
||||
eweka is annual fixed
|
||||
phone is messier again.
|
||||
|
||||
3
bills.py
3
bills.py
@@ -291,7 +291,7 @@ def get_growth_value( bt, bill_type ):
|
||||
# and I didn't want to input 12 of them at the same price), and it always
|
||||
# occurs for future bills
|
||||
################################################################################
|
||||
def process_bill_data(bd, bt, bf):
|
||||
def process_bill_data(bd, bt, bf, key_dates):
|
||||
# this maps a bill id to a freq id (e.g. bill #34 - has a frequency of #2 (which might be quarterly)
|
||||
bt_id_freq = {row["id"]: row["freq"] for row in bt}
|
||||
bt_id_ann_growth_avg = {row["id"]: row["ann_growth_avg"] for row in bt}
|
||||
@@ -495,3 +495,4 @@ def calc_future_totals(bill_info, bill_types):
|
||||
# had to round to 2 decimal here to get sensible totals
|
||||
total[bt['id']][yr] = round( total[bt['id']][yr], 2 )
|
||||
return total
|
||||
|
||||
|
||||
40
calc.py
40
calc.py
@@ -5,6 +5,15 @@ from defines import END_YEAR
|
||||
# GLOBAL CONSTANTS
|
||||
LEASE = 0
|
||||
|
||||
# Dates that don't change
|
||||
car_balloon_date = datetime(2026, 11, 15)
|
||||
new_fin_year_25 = datetime(2025, 7, 1)
|
||||
new_fin_year_26 = datetime(2026, 7, 1)
|
||||
end_date = datetime(END_YEAR, 4, 15)
|
||||
school_fees_date = datetime(2025, 12, 5)
|
||||
mich_present_date = datetime(2026,10,15)
|
||||
first_pay_date = datetime(2025,1,8)
|
||||
|
||||
def bill_amount_today(finance, day, bill_data, bt_id_name, total ):
|
||||
amt=0
|
||||
day_str = day.strftime("%Y-%m-%d")
|
||||
@@ -100,8 +109,6 @@ def calculate_savings_depletion(finance, bill_data, bill_type):
|
||||
D_has_quit = False
|
||||
D_quit_year = 0
|
||||
claim_tax_on_leave = False
|
||||
new_fin_year_25 = datetime(2025, 7, 1)
|
||||
new_fin_year_26 = datetime(2026, 7, 1)
|
||||
|
||||
# Constants for interest calculations
|
||||
annual_interest_rate = Interest_Rate / 100.0
|
||||
@@ -109,7 +116,6 @@ def calculate_savings_depletion(finance, bill_data, bill_type):
|
||||
|
||||
# main loop range -- start from now, and simulate till D is 60 (April 2031)
|
||||
current_date = datetime.today()
|
||||
end_date = datetime(END_YEAR, 4, 15)
|
||||
|
||||
# work out which bill_types relate to future bills
|
||||
for bt in bill_type:
|
||||
@@ -151,11 +157,6 @@ def calculate_savings_depletion(finance, bill_data, bill_type):
|
||||
depletion_date = None
|
||||
savings_per_fortnight = []
|
||||
|
||||
# significant dates that are non-changeable
|
||||
school_fees_date = datetime(2025, 12, 5)
|
||||
car_balloon_date = datetime(2026, 11, 15)
|
||||
mich_present_date = datetime(2026,10,15)
|
||||
|
||||
# significant dates - but who knows when? :)
|
||||
overseas_trip_date = datetime.strptime( finance['Overseas_trip_date'], "%Y-%m-%d")
|
||||
mark_reno_date = datetime.strptime( finance['Mark_reno_date'], "%Y-%m-%d")
|
||||
@@ -360,3 +361,26 @@ def calculate_savings_depletion(finance, bill_data, bill_type):
|
||||
|
||||
return depletion_date, savings_per_fortnight, current_savings
|
||||
|
||||
################################################################################
|
||||
# work out the date D quits and when we own the car, so we can then use it to
|
||||
# handle future bills
|
||||
################################################################################
|
||||
def calc_key_dates( finance ):
|
||||
key_dates={}
|
||||
now = datetime.today()
|
||||
# this will be 0 to 13 days - how far into this fortnights pay cycle are we now
|
||||
days_in_pay_fortnight= ( now - first_pay_date ).days % 14
|
||||
|
||||
# add 1 less fortnight than we continue to work, then add rest of pay cycle (14-days_in_pay_fortnight)
|
||||
key_dates['D_quit_date'] = (now+timedelta(weeks=2*(finance['D_Num_fortnights_pay']-1))+timedelta(days=(14-days_in_pay_fortnight))).strftime('%Y-%m-%d')
|
||||
|
||||
# use lease date
|
||||
if finance['Ioniq6_future'] == LEASE:
|
||||
key_dates['D_hyundai_owned'] = car_balloon_date.strftime('%Y-%m-%d')
|
||||
# use buyout date
|
||||
else:
|
||||
key_dates['D_hyundai_owned'] = finance['Car_buyout_date']
|
||||
|
||||
print( f"kd={key_dates}" )
|
||||
return key_dates
|
||||
|
||||
|
||||
12
main.py
12
main.py
@@ -1,6 +1,6 @@
|
||||
# main.py
|
||||
from flask import Flask, render_template, request, redirect, url_for, Response, jsonify
|
||||
from calc import calculate_savings_depletion
|
||||
from calc import calculate_savings_depletion, calc_key_dates
|
||||
from db import init_db, get_finance_data, update_finance, get_budget_data, insert_cset, get_comp_set_data, get_comp_set_options, get_bill_freqs
|
||||
from db import get_bill_data, new_bill, update_bill_data, delete_bill
|
||||
from db import get_bill_ui, save_ui
|
||||
@@ -145,14 +145,20 @@ def update():
|
||||
|
||||
@app.route('/bills')
|
||||
def DisplayBillData():
|
||||
finance_data = get_finance_data()
|
||||
# work out when D quits, when car is owned
|
||||
key_dates = calc_key_dates( finance_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)
|
||||
# take bill data, AND work out estimated future bills - process this into the bill_info array,
|
||||
bill_info=process_bill_data(bill_data, bill_types, bill_freqs, key_dates)
|
||||
# get an array of the total costs of bills each year - purely cosmetic (using bill_info)
|
||||
total=calc_future_totals(bill_info, bill_types)
|
||||
# update/re-get bill_data now that new estimated bills have been added
|
||||
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 )
|
||||
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, key_dates=key_dates )
|
||||
|
||||
@app.route('/newbilltype', methods=['POST'])
|
||||
def InsertBillType():
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="row mt-4 highcharts-dark" id="container" style="width:100%; height:400px;"></div>
|
||||
<div class="row mt-4 highcharts-dark" id="container" style="width:100%; height:800px;"></div>
|
||||
<script type="text/javascript">
|
||||
// make these global so we can also use them in the /save route (via modal)
|
||||
const savingsData = JSON.parse('{{ savings | tojson }}');
|
||||
|
||||
Reference in New Issue
Block a user