diff --git a/BUGS b/BUGS index f2830c4..e69de29 100644 --- a/BUGS +++ b/BUGS @@ -1,2 +0,0 @@ -delete internet bill from 2023, and it grows 2023 even though 2022 price == 2024 price -- want to fix this, so I can have ONLY those dates where prices change and fill in the rest diff --git a/bills.py b/bills.py index 0c5e226..6b3ac14 100644 --- a/bills.py +++ b/bills.py @@ -1,18 +1,36 @@ from db import get_bill_data, get_bill_types, get_bill_freqs, set_bill_type_growth, new_bill from defines import END_YEAR +import datetime # give a bill dat in format YYYY-MM-DD, return quarter (1-4) def qtr(d): m = int(d[5:7]) return ( (m-1)//3 + 1 ) +def find_next_bill( bill_type, bill_info, bill_date ): + wanted_year = int(bill_date[:4]) + wanted_mm = int(bill_date[5:7]) + # if we want a bill after our last year, just return None + if int(wanted_year) > int(bill_info[bill_type]['last_bill_year']): + return None + + for yr in range( wanted_year, bill_info[bill_type]['last_bill_year']+1 ): + # start with bills in the year wanted (if any) + if yr in bill_info[bill_type]['year']: + for bill in bill_info[bill_type]['year'][yr][::-1]: + bill_mm = int(bill['bill_date'][5:7]) + # if bill is in this year but later OR its a later year, return this bill + if (wanted_year == yr and bill_mm > wanted_mm) or wanted_year < yr: + return bill + # failsafe + return None + + def find_previous_bill( bill_type, bill_info, bill_date ): -# print( f"{bill_type}: find_previous_bill -> {bill_date}" ) wanted_year = int(bill_date[:4]) wanted_mm = int(bill_date[5:7]) # if we don't have a bill before this date, no way to set price if int(wanted_year) < int(bill_info[bill_type]['first_bill_year']): -# print(f"{bill_type}: find_previous_bill - failed. wanted_year={wanted_year} is older than our first_bill={bill_info[bill_type]['first_bill_year']}" ) return None # start loop from bill_date, go backwards and find which one it is (same year, should be month-based) @@ -21,6 +39,7 @@ def find_previous_bill( bill_type, bill_info, bill_date ): if wanted_year == int(bill_info[bill_type]['first_bill_year']): # range of this year with -1, does not return anything, so force this year. yr_range=[ wanted_year ] + for yr in yr_range: # start with bills in the year wanted (if any) # must include 'estimated' bills to deal with growth of future years @@ -28,18 +47,16 @@ def find_previous_bill( bill_type, bill_info, bill_date ): # okay, we have the previous billing year, and we wanted one for a year in the future, # just return the last one in this year as its the most recent if wanted_year > yr: -# print("should be return last of {yr} - date={bill_info[bill_type]['year'][yr][-1]['bill_date']}" ) return bill_info[bill_type]['year'][yr][-1] else: # lets go through the newest to oldest of these bills - for bill in bill_info[bill_type]['year'][wanted_year][::-1]: + for bill in bill_info[bill_type]['year'][yr][::-1]: bill_mm = int(bill['bill_date'][5:7]) # reversing the bills, means we start with the 'most recent' in this year to the oldest # if the month we want is after the bill, we are done if wanted_mm > bill_mm: return bill -# print(f"{bill_type}: find_previous_bill - failed. Seems our first bill = {bill_info[bill_type]['first_bill']['bill_date']} is in same year, but after wanted month={wanted_mm}, so no base to rely on" ) return None @@ -95,17 +112,20 @@ def add_missing_monthly_bills_in_yr( bill_type, bill_info, yr ): break if not bill_found: pb=find_previous_bill( bill_type, bill_info, new_date ) + nb=find_next_bill( bill_type, bill_info, new_date ) if not pb: print("Failed to find previous_bill, can't calculate missing bill - returning" ) return amt = pb['amount'] - # if this month is the same as the last bill month and as per above - # we don't have a bill for this date, then add annual grotwh - if i == int(lb_mm): - print(f"its month: {i} - time to add growth: {bill_info[bill_type]['growth']}" ) - amt += amt * bill_info[bill_type]['growth']/100 - bill_info[bill_type]['last_bill_amount']=amt + # if there is no next bill then use growth, otherwise, I am only putting in real bills + # where changes occur, so keep the pb amount 'unchanged' + if not nb: + # if this month is the same as the last bill month and as per above + # we don't have a bill for this date, then add annual grotwh + if i == int(lb_mm): + amt += amt * bill_info[bill_type]['growth']/100 + bill_info[bill_type]['last_bill_amount']=amt # last param is estimated (and this is an estimate for a future bill / not real) new_bill( bill_type, amt, new_date, 1 ) if not yr in bill_info[bill_type]['year']: @@ -163,25 +183,15 @@ def process_bill_data(bd, bt, bf): # due to sql sorting, this first instance is the last bill bill_info[bill_type]['last_bill']=bill bill_info[bill_type]['last_bill_year']=int(bill['bill_date'][:4]) - if not bill['estimated']: - print( f"this bill is real, its the first so consider it the last bill paid - date is: {int(bill['bill_date'][:4])}" ) - bill_info[bill_type]['last_real_bill_year']=int(bill['bill_date'][:4]) bill_info[bill_type]['year']={} - bill_info[bill_type]['year_real']={} if not yr in bill_info[bill_type]['year']: bill_info[bill_type]['year'][yr]=[] - bill_info[bill_type]['year_real'][yr]=[] # keep updating last to this matching bill bill_info[bill_type]['first_bill']=bill 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']: - print( f"{bill_type}: seems we dont have a last_real_bill_year, set it to: {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 bill_info[bill_type]['year'][yr].append(bill) - if not bill['estimated']: - bill_info[bill_type]['year_real'][yr].append(bill) # now process the bill_info from yr of first bill to yr of last bill for bill_type in bill_info: @@ -206,7 +216,6 @@ def process_bill_data(bd, bt, bf): # add_missing_bills_for_yr -- wrapper to call right func based on bill freq ################################################################################ def add_missing_bills_for_yr( bill_type, bill_info, yr ): - print(f"{bill_type}: add_missing_bills_for_yr( {bill_type}, bill_info, {yr} )") num = bill_info[bill_type]['num_ann_bills'] if num == 1: add_missing_annual_bill_in_yr( bill_type, bill_info, yr ) @@ -217,26 +226,16 @@ def add_missing_bills_for_yr( bill_type, bill_info, yr ): return def derive_ann_growth( bill_type, bill_info ): - print(f"{bill_type}: Derive annual growth on bill_type: {bill_type} - fby={bill_info[bill_type]['first_bill_year']}, lby={bill_info[bill_type]['last_real_bill_year']} " ) - + # just do up to now so we stop earlier than looking at other estimated (just an optimisation) + now_yr = datetime.date.today().year total={} - for yr in range( bill_info[bill_type]['first_bill_year'], bill_info[bill_type]['last_real_bill_year']+1): - # for monthly bills, 1 or 12 bills is enough to work with - if bill_info[bill_type]['num_ann_bills'] == 12: - if len(bill_info[bill_type]['year_real'][yr]) != 1 and len(bill_info[bill_type]['year_real'][yr]) != 12: - continue; - # okay annual or quarterly bills, only total them if we have all of them for the year - elif len(bill_info[bill_type]['year_real'][yr]) != bill_info[bill_type]['num_ann_bills']: + for yr in range( bill_info[bill_type]['first_bill_year'], now_yr+1): + # if not enough bills in this year (or none), then try next year (first year might have not enough bills) + if yr not in bill_info[bill_type]['year'] or len(bill_info[bill_type]['year'][yr]) != bill_info[bill_type]['num_ann_bills']: continue; - # for monthlys add totals regardless (we only process total if there is 12 or 1 further below). Other bill_types, only total if there is all bills for year - if bill_info[bill_type]['num_ann_bills'] != 12 and len(bill_info[bill_type]['year_real'][yr]) != bill_info[bill_type]['num_ann_bills']: - continue total[yr] = 0 for b in bill_info[bill_type]['year'][yr]: - # ignore estimated bills, only use real bills to calc growth stats - if b['estimated']: - continue total[yr] += b['amount'] # once we have all yr totals: @@ -246,7 +245,7 @@ def derive_ann_growth( bill_type, bill_info ): max_growth = 0 count = 0 # start from year after first bill, so we can see annual growth from the following year onwards - for yr in range( bill_info[bill_type]['first_bill_year']+1, bill_info[bill_type]['last_bill_year']+1): + for yr in range( bill_info[bill_type]['first_bill_year']+1, now_yr+1): # if full data sets for consecutive years, work out annual growth stats if yr-1 in total and yr in total: growth = (total[yr] - total[yr-1]) / total[yr-1] * 100 @@ -257,9 +256,6 @@ def derive_ann_growth( bill_type, bill_info ): if growth > max_growth: max_growth = growth if count: - print( f"{bill_type}: Min growth was: {min_growth}" ) - print( f"{bill_type}: Avg growth is: {avg_growth/count}" ) - print( f"{bill_type}: Max growth was: {max_growth}" ) set_bill_type_growth( bill_type, min_growth, avg_growth/count, max_growth ) else: # failsafe (just in case fill bills failed to add enough bills to average out)