# main.py from flask import Flask, render_template, request, redirect, url_for, Response from calc import calculate_savings_depletion from db import init_db, get_finance_data, update_finance, get_budget_data, get_comp_set_data from collections import defaultdict from datetime import datetime import csv import io from disp import FP_VAR app = Flask(__name__) # Initialize the database init_db() @app.route('/') def index(): finance_data = get_finance_data() depletion_date, savings_per_fortnight, final_savings = calculate_savings_depletion(finance_data) BUDGET=get_budget_data(finance_data) if depletion_date: depletion_date=depletion_date.date(); # just show date #HARDCODE HACK: finance_data['comp_set']=1 # we are comparing... if finance_data['comp_set'] >= 1: COMP=get_comp_set_data(finance_data['comp_set']) DISP=[] # Row 1 r=[] r.append( FP_VAR( 'D Salary', 'D_Salary' ) ) r.append( FP_VAR( 'Savings', 'Savings' ) ) r.append( FP_VAR( 'Car Loan via Pay', 'Car_loan_via_pay', 'readonly' ) ) r.append( FP_VAR( 'Living Expenses', 'Living_Expenses' ) ) r.append( FP_VAR( 'Overseas Trip', 'Overseas_trip', 'date', 'col-4', 'Overseas_trip_date' ) ) DISP.append(r) # Row 2 r=[] r.append( FP_VAR( 'D # Fortnights pay', 'D_Num_fortnights_pay' ) ) r.append( FP_VAR( 'Interest Rate', 'Interest_Rate' ) ) r.append( FP_VAR( 'Car Loan', 'Car_loan', 'readonly' ) ) r.append( FP_VAR( 'Inflation', 'Inflation' ) ) r.append( FP_VAR( 'Reno Costs', 'Mark_reno', 'date', 'col-4', 'Mark_reno_date' ) ) DISP.append(r) # Row 2 r=[] r.append( FP_VAR( 'D leave owed (in days)', 'D_leave_owed_in_days' ) ) r.append( FP_VAR( 'M TLS amount', 'M_TLS_shares' ) ) r.append( FP_VAR( 'Car Balloon', 'Car_balloon', 'readonly' ) ) DISP.append(r) # Row 3 r=[] r.append( FP_VAR( 'D CBA amount', 'D_CBA_shares' ) ) r.append( FP_VAR( 'D TLS amount', 'D_TLS_shares' ) ) r.append( FP_VAR( 'Mich Present', 'Mich_present', 'readonly' ) ) r.append( FP_VAR( 'Sell Shares for:', 'Sell_shares', 'select', 'offset-2 col-2' ) ) DISP.append(r) # Row 4 r=[] r.append( FP_VAR( 'CBA price', 'CBA_price' ) ) r.append( FP_VAR( 'TLS price', 'TLS_price' ) ) r.append( FP_VAR( 'School Fees', 'School_Fees', 'readonly' ) ) r.append( FP_VAR( 'FINAL # of CBA', 'CBA', 'readonly' ) ) r.append( FP_VAR( 'FINAL # of TLS', 'TLS', 'readonly' ) ) DISP.append(r) return render_template('index.html', finance=finance_data, depletion_date=depletion_date, savings=savings_per_fortnight, BUDGET=BUDGET, COMP=COMP, DISP=DISP) @app.route('/update', methods=['POST']) def update(): finance_data = ( request.form['D_Salary'], request.form['D_Num_fortnights_pay'], request.form['School_Fees'], request.form['Car_loan_via_pay'], request.form['Car_loan'], request.form['Car_balloon'], request.form['Living_Expenses'], request.form['Savings'], request.form['Interest_Rate'], request.form['Inflation'], request.form['Mich_present'], request.form['Overseas_trip'], request.form['Mark_reno'], request.form['D_leave_owed_in_days'], request.form['D_TLS_shares'], request.form['M_TLS_shares'], request.form['D_CBA_shares'], request.form['TLS_price'], request.form['CBA_price'], request.form['Overseas_trip_date'], request.form['Mark_reno_date'], request.form['Sell_shares'], ) update_finance(finance_data) return redirect(url_for('index')) @app.route("/download_csv", methods=["GET"]) def download_csv(): finance_data = get_finance_data() depletion_date, savings_per_fortnight, final_savings, TLS, CBA = calculate_savings_depletion(finance_data) BUDGET=get_budget_data(finance_data) # Group data by year data_by_year = defaultdict(list) for date_str, amount in savings_per_fortnight: year = date_str.split("-")[0] # Extract the year from the date data_by_year[year].append((date_str, amount)) # Determine the maximum number of entries for any year max_entries_per_year = max(len(entries) for entries in data_by_year.values()) # Sort years for column ordering years = sorted(data_by_year.keys()) # get finance data into a list for spitting out during csv last column dump fd_lst = list(finance_data.items()) fd_lst[0]=('Variable', 'Value') # Create an in-memory output file output = io.StringIO() # Create a CSV writer object writer = csv.writer(output) # Write header: each year gets two columns (Date, Value) header = [] for year in years: header.extend([f"{year}-Date", f"{year}-Value"]) writer.writerow(header) # Write the data rows cnt=0 for i in range(max_entries_per_year): row = [] for year in years: # Add date and value if they exist for the current index if i < len(data_by_year[year]): date, value = data_by_year[year][i] row.extend([date, value]) else: row.extend(["", ""]) # If no data for this year, leave blank cells # spacer row.extend([""]) # now add budget data if cnt < len(BUDGET): row.extend( BUDGET[cnt] ) else: row.extend(["", ""]) # If no data for this year, leave blank cells # spacer row.extend([""]) # now add reference data if cnt < len(fd_lst): row.extend(fd_lst[cnt]) writer.writerow(row) cnt += 1 csv_data = output.getvalue() # Create a Flask Response object, with CSV mime type and downloadable as a file return Response( csv_data, mimetype="text/csv", headers={"Content-disposition": "attachment; filename=finance_data.csv"} ) # Main program if __name__ == '__main__': app.run(debug=True) ########## # # How to cross-check, so we get paid: 4762.29 + 1962.56 per fortnight or: $174846.1 AFTER TAX # take $20k for Cam, and $20k for Mich for schools last year, $10k for Cam pres, take $72k for living, take $8k in furniture. # We went from 250 to 300k (more or less), so about right # to note: transfers to Cam/Mich - $850 # ##########