Files
finplan/main.py

195 lines
6.3 KiB
Python

# 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, get_comp_set_options
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()
get_comp_set_options(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
# if we are comparing...(compare_to will be 0 / None to start with, and then COMP will be None
COMP=get_comp_set_data(finance_data['compare_to'])
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-auto', '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-auto', 'Mark_reno_date' ) )
DISP.append(r)
# Row 2
r=[]
r.append( FP_VAR( 'D # days leave', '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', 'col-auto' ) )
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'],
request.form['compare_to']
)
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 = 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
#
##########