Change approach with Qtr bills, all are simple based on last qtr - when we have normal Qtr bills (freq 'Quarterly') we just use last qtrs data for growth much easier. For GAS, we have the 'Quaterly (forced)' freq. which uses the forced/calc. amount per qtr for growth, its good enough for Gas bills - which dont always have 4 bills a year

This commit is contained in:
2025-08-31 16:32:00 +10:00
parent c74383f89e
commit 3a5b77f12d
2 changed files with 39 additions and 15 deletions

View File

@@ -140,7 +140,7 @@ def new_estimated_bill( bill_info, yr, bill_type, amt, new_date ):
bill['bill_date']=new_date bill['bill_date']=new_date
bill['amount']=amt bill['amount']=amt
bill['estimated']=1 bill['estimated']=1
# need this for find_previous_bill to work but only need the above 3 fields # need to insert(0,) to add this "newest" bill to start of the data for {yr} so that find_previous_bill can work - only need the above 3 fields
bill_info[bill_type]['year'][yr].insert(0,bill) bill_info[bill_type]['year'][yr].insert(0,bill)
if bill_info[bill_type]['num_ann_bills'] == 4: if bill_info[bill_type]['num_ann_bills'] == 4:
@@ -190,16 +190,35 @@ def add_missing_quarter_bills_in_yr( bill_type, bill_info, yr ):
else: else:
r=range(1,5) r=range(1,5)
for q in r: for q in r:
# amt is total of last year's qtr bill proportion if 'forced' in bill_info[bill_type]['freq']:
amt = bill_info[bill_type]['qtr'][yr-1][q]*(1+bill_info[bill_type]['growth']/100) actually_add_estimated_new_quarter_bill_forced(bill_type, bill_info, yr, q)
# just make new bills first of last month of a qtr (good as any date for GAS, they move anyway) else:
new_date = f'{yr}-{q*3:02d}-01' actually_add_estimated_new_quarter_bill(bill_type, bill_info, yr, q)
# SANITY CHECK: we might be adding a bill estimate we already have (due to stupid gas bills /qtrly code) return
if yr in bill_info[bill_type]['year']:
for b in bill_info[bill_type]['year'][yr]: ################################################################################
if b['bill_date'] == new_date: # func take a qtr in a year, finds equiv from previous year, calcs new based on
return # it (same 'day' with amt * growth)
new_estimated_bill( bill_info, yr, bill_type, amt, new_date ) ################################################################################
def actually_add_estimated_new_quarter_bill( bill_type, bill_info, yr, q ):
# amt is total of last year's qtr bill (NOTE: use 4-q, bills are in desc order)
last_yrs_bill_in_this_q = bill_info[bill_type]['year'][yr-1][4-q]
amt = last_yrs_bill_in_this_q['amount']*(1+bill_info[bill_type]['growth']/100)
# make new qtr bill same 'day' (mm-dd) as last year, just chg (yr)
mmdd=last_yrs_bill_in_this_q['bill_date'][5:]
new_date = f'{yr}-{mmdd}'
new_estimated_bill( bill_info, yr, bill_type, amt, new_date )
return
def actually_add_estimated_new_quarter_bill_forced( bill_type, bill_info, yr, q ):
print( f"Being asked to add a FORCED qtr bill for {yr}-q{q} - likely a GAS bill, as its the only one, *sigh*" )
last_yrs_qtr_amount = bill_info[bill_type]['qtr'][yr-1][q]
print( f"amt is based on forced qtr amount for last year: {last_yrs_qtr_amount}" )
amt=last_yrs_qtr_amount*(1+bill_info[bill_type]['growth']/100)
new_date = f'{yr}-{q*3:02d}-01'
new_estimated_bill( bill_info, yr, bill_type, amt, new_date )
return return
# missing monthly bills, find date based on DD and put in each missing month # missing monthly bills, find date based on DD and put in each missing month
@@ -281,6 +300,8 @@ def process_bill_data(bd, bt, bf):
# this maps freq to bills per annum (e.g. id=2 to 4 bills per annum) # this maps freq to bills per annum (e.g. id=2 to 4 bills per annum)
bf_id_num = {row["id"]: row["num_bills_per_annum"] for row in bf} bf_id_num = {row["id"]: row["num_bills_per_annum"] for row in bf}
# and allows me a way to see if the bill is quarterly but also fixed or seasonal
bf_id_name = {row["id"]: row["name"] for row in bf}
# want to proces all bill data into easier to maniuplate structure, so make # want to proces all bill data into easier to maniuplate structure, so make
# a bill_info[bill_id] with first_bill, last_bill, [yr] with matching bills to process # a bill_info[bill_id] with first_bill, last_bill, [yr] with matching bills to process
@@ -292,6 +313,7 @@ def process_bill_data(bd, bt, bf):
# new bill type # new bill type
if not bill_type in bill_info: if not bill_type in bill_info:
bill_info[bill_type]={} bill_info[bill_type]={}
bill_info[bill_type]['freq'] = bf_id_name[bt_id_freq[bill_type]]
bill_info[bill_type]['growth'] = get_growth_value( bt, bill_type ) bill_info[bill_type]['growth'] = get_growth_value( bt, bill_type )
bill_info[bill_type]['num_ann_bills'] = bf_id_num[bt_id_freq[bill_type]] bill_info[bill_type]['num_ann_bills'] = bf_id_num[bt_id_freq[bill_type]]
bill_info[bill_type]['first_bill']={} bill_info[bill_type]['first_bill']={}
@@ -310,7 +332,7 @@ def process_bill_data(bd, bt, bf):
bill_info[bill_type]['first_bill_year']=int(bill['bill_date'][:4]) bill_info[bill_type]['first_bill_year']=int(bill['bill_date'][:4])
if not 'last_real_bill_year' in bill_info[bill_type] and not bill['estimated']: if not 'last_real_bill_year' in bill_info[bill_type] and not bill['estimated']:
bill_info[bill_type]['last_real_bill_year']=int(bill['bill_date'][:4]) bill_info[bill_type]['last_real_bill_year']=int(bill['bill_date'][:4])
# add this bill to list for this year # append this bill to list for this year
bill_info[bill_type]['year'][yr].append(bill) bill_info[bill_type]['year'][yr].append(bill)
# now process the bill_info from yr of first bill to yr of last bill # now process the bill_info from yr of first bill to yr of last bill
@@ -464,8 +486,10 @@ def calc_future_totals(bill_info, bill_types):
for bt in bill_types: for bt in bill_types:
total[bt['id']]={} total[bt['id']]={}
for yr in range( now_yr, END_YEAR+1): for yr in range( now_yr, END_YEAR+1):
total[bt['id']][yr]=0 total[bt['id']][yr]=0.0
if bt['id'] in bill_info and yr in bill_info[bt['id']]['year']: if bt['id'] in bill_info and yr in bill_info[bt['id']]['year']:
for b in bill_info[bt['id']]['year'][yr]: for b in bill_info[bt['id']]['year'][yr]:
total[bt['id']][yr] += b['amount'] total[bt['id']][yr] += b['amount']
# had to round to 2 decimal here to get sensible totals
total[bt['id']][yr] = round( total[bt['id']][yr], 2 )
return total return total

4
db.py
View File

@@ -133,8 +133,8 @@ def init_db():
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(4762.29, 10, 24000, 620, 2412, 45824.68, 83738.74, 80000, 424875.26, 4.75, 2.4, 10000, 50000, 10000, 76.85, 1000, 750, 1111, 4.52, 163.32, '2025-06-01', '2025-09-01', '2025-02-20', 4, 0, 0)) (4762.29, 10, 24000, 620, 2412, 45824.68, 83738.74, 80000, 424875.26, 4.75, 2.4, 10000, 50000, 10000, 76.85, 1000, 750, 1111, 4.52, 163.32, '2025-06-01', '2025-09-01', '2025-02-20', 4, 0, 0))
cur.execute( "INSERT INTO bill_freq values ( 1, 'Annual', 1 )" ) cur.execute( "INSERT INTO bill_freq values ( 1, 'Annual', 1 )" )
cur.execute( "INSERT INTO bill_freq values ( 2, 'Quarterly (seasonal)', 4 )" ) cur.execute( "INSERT INTO bill_freq values ( 2, 'Quarterly', 4 )" )
cur.execute( "INSERT INTO bill_freq values ( 3, 'Quarterly (fixed)', 4 )" ) cur.execute( "INSERT INTO bill_freq values ( 3, 'Quarterly (forced)', 4 )" )
cur.execute( "INSERT INTO bill_freq values ( 4, 'Monthly', 12 )" ) cur.execute( "INSERT INTO bill_freq values ( 4, 'Monthly', 12 )" )
# start with no specific Tab/bill_type to show, and dont show_estimated # start with no specific Tab/bill_type to show, and dont show_estimated
cur.execute( "INSERT INTO bill_ui values ( 1, null, 0 )" ) cur.execute( "INSERT INTO bill_ui values ( 1, null, 0 )" )