Compare commits
5 Commits
7bab6eabdd
...
cf104b5a56
| Author | SHA1 | Date | |
|---|---|---|---|
| cf104b5a56 | |||
| 98fa17acd7 | |||
| 6403ca7775 | |||
| adac3eceeb | |||
| 27048a450f |
14
TODO
Normal file
14
TODO
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
For bills, there is too much to guess, need to ask:
|
||||||
|
frequency:
|
||||||
|
then I could work out growth rate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
41
bills.py
Normal file
41
bills.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from db import get_bill_data, get_bill_types, set_bill_type_growth
|
||||||
|
|
||||||
|
def derive_bill_data():
|
||||||
|
bd=get_bill_data()
|
||||||
|
bt=get_bill_types()
|
||||||
|
water_id = None
|
||||||
|
for t in bt:
|
||||||
|
if t['name'] == "Water":
|
||||||
|
water_id = t['id']
|
||||||
|
|
||||||
|
if not water_id:
|
||||||
|
return
|
||||||
|
total={}
|
||||||
|
total[water_id]={}
|
||||||
|
for yr in [2022, 2023, 2024]:
|
||||||
|
print( f"water_id={water_id}")
|
||||||
|
total[water_id][yr] = 0
|
||||||
|
for b in bd:
|
||||||
|
if b['bill_type_id'] == water_id and str(yr) in b['bill_date']:
|
||||||
|
total[water_id][yr] += b['amount']
|
||||||
|
print( f"{yr} => {b['bill_date']} -- {b['amount']}" )
|
||||||
|
print( f"total for water in {yr} is {total[water_id][yr]}" )
|
||||||
|
|
||||||
|
# once we have all yr totals:
|
||||||
|
growth = {}
|
||||||
|
growth[water_id] = {}
|
||||||
|
max_growth = {}
|
||||||
|
avg_growth = {}
|
||||||
|
max_growth[water_id] = 0
|
||||||
|
avg_growth[water_id] = 0
|
||||||
|
count = 0
|
||||||
|
for yr in [2023, 2024]:
|
||||||
|
growth[water_id][yr] = (total[water_id][yr] - total[water_id][yr-1]) / total[water_id][yr-1] * 100
|
||||||
|
avg_growth[water_id] += growth[water_id][yr]
|
||||||
|
count += 1
|
||||||
|
if growth[water_id][yr] > max_growth[water_id]:
|
||||||
|
max_growth[water_id] = growth[water_id][yr]
|
||||||
|
print( f"growth from {yr} to {yr-1} = {growth}%")
|
||||||
|
print( f"Max growth was: {max_growth[water_id]}" )
|
||||||
|
print( f"Avg growth is: {avg_growth[water_id]/count}" )
|
||||||
|
set_bill_type_growth( water_id, avg_growth[water_id]/count )
|
||||||
41
db.py
41
db.py
@@ -85,6 +85,14 @@ def init_db():
|
|||||||
)''')
|
)''')
|
||||||
|
|
||||||
cur.execute('''CREATE TABLE IF NOT EXISTS bill_type (
|
cur.execute('''CREATE TABLE IF NOT EXISTS bill_type (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
freq INTEGER,
|
||||||
|
name STRING,
|
||||||
|
ann_growth REAL,
|
||||||
|
FOREIGN KEY(freq) REFERENCES bill_freq(id)
|
||||||
|
)''')
|
||||||
|
|
||||||
|
cur.execute('''CREATE TABLE IF NOT EXISTS bill_freq (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name STRING
|
name STRING
|
||||||
)''')
|
)''')
|
||||||
@@ -113,6 +121,9 @@ def init_db():
|
|||||||
Inflation, Mich_present, Overseas_trip, Mark_reno, D_leave_owed_in_days, D_TLS_shares, M_TLS_shares, D_CBA_shares, TLS_price, CBA_price, Overseas_trip_date, Mark_reno_date, Car_buyout_date, Sell_shares, compare_to, Ioniq6_future)
|
Inflation, Mich_present, Overseas_trip, Mark_reno, D_leave_owed_in_days, D_TLS_shares, M_TLS_shares, D_CBA_shares, TLS_price, CBA_price, Overseas_trip_date, Mark_reno_date, Car_buyout_date, Sell_shares, compare_to, Ioniq6_future)
|
||||||
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' )" )
|
||||||
|
cur.execute( "INSERT INTO bill_freq values ( 2, 'Quarterly' )" )
|
||||||
|
cur.execute( "INSERT INTO bill_freq values ( 3, 'Monthly' )" )
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
@@ -248,7 +259,7 @@ def get_comp_set_options(finance):
|
|||||||
def get_bill_data():
|
def get_bill_data():
|
||||||
conn = connect_db(True)
|
conn = connect_db(True)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute('SELECT bd.id, bt.id as bill_type_id, bt.name, bd.amount, bd.bill_date FROM bill_type bt, bill_data bd where bt.id = bd.bill_type order by bt.name, bd.bill_date')
|
cur.execute('SELECT bd.id, bt.id as bill_type_id, bt.name, bd.amount, bd.bill_date FROM bill_type bt, bill_data bd where bt.id = bd.bill_type order by bt.name, bd.bill_date desc')
|
||||||
bd = cur.fetchall()
|
bd = cur.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return bd
|
return bd
|
||||||
@@ -256,11 +267,20 @@ def get_bill_data():
|
|||||||
def get_bill_types():
|
def get_bill_types():
|
||||||
conn = connect_db(True)
|
conn = connect_db(True)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute('SELECT id, name FROM bill_type order by name')
|
cur.execute('SELECT * FROM bill_type order by name')
|
||||||
bt = cur.fetchall()
|
bt = cur.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return bt
|
return bt
|
||||||
|
|
||||||
|
def get_bill_freqs():
|
||||||
|
conn = connect_db(True)
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute('SELECT * FROM bill_freq order by name')
|
||||||
|
bf = cur.fetchall()
|
||||||
|
conn.close()
|
||||||
|
return bf
|
||||||
|
|
||||||
|
|
||||||
def new_bill( name, amount, bill_date ):
|
def new_bill( name, amount, bill_date ):
|
||||||
conn = connect_db(False)
|
conn = connect_db(False)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
@@ -277,18 +297,19 @@ def update_bill_data( id, name, amount, bill_date ):
|
|||||||
conn.close()
|
conn.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
def insert_bill_type( bt ):
|
def insert_bill_type( bt, fq ):
|
||||||
conn = connect_db(False)
|
conn = connect_db(False)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute( f"insert into bill_type ( 'name' ) values ( '{bt}' )" )
|
print( f"fq={fq}" )
|
||||||
|
cur.execute( f"insert into bill_type ( 'name', 'freq', 'ann_growth' ) values ( '{bt}', {fq}, 0 )" )
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
def update_bill_type(id, bill_type):
|
def update_bill_type(id, bill_type, freq):
|
||||||
conn = connect_db(False)
|
conn = connect_db(False)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute( f"update bill_type set name ='{bill_type}' where id = {id}" )
|
cur.execute( f"update bill_type set name ='{bill_type}', freq={freq} where id = {id}" )
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return
|
return
|
||||||
@@ -308,3 +329,11 @@ def delete_bill_type( id ):
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def set_bill_type_growth( id, g ):
|
||||||
|
conn = connect_db(False)
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute( f"update bill_type set ann_growth ='{g}' where id = {id}" )
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return
|
||||||
|
|||||||
11
main.py
11
main.py
@@ -1,9 +1,10 @@
|
|||||||
# main.py
|
# main.py
|
||||||
from flask import Flask, render_template, request, redirect, url_for, Response, jsonify
|
from flask import Flask, render_template, request, redirect, url_for, Response, jsonify
|
||||||
from calc import calculate_savings_depletion
|
from calc import calculate_savings_depletion
|
||||||
from db import init_db, get_finance_data, update_finance, get_budget_data, insert_cset, get_comp_set_data, get_comp_set_options
|
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_data, new_bill, update_bill_data, delete_bill
|
||||||
from db import get_bill_types, insert_bill_type, update_bill_type, delete_bill_type
|
from db import get_bill_types, insert_bill_type, update_bill_type, delete_bill_type
|
||||||
|
from bills import derive_bill_data
|
||||||
from collections import defaultdict, Counter
|
from collections import defaultdict, Counter
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import csv
|
import csv
|
||||||
@@ -142,19 +143,21 @@ def update():
|
|||||||
def DisplayBillData():
|
def DisplayBillData():
|
||||||
bill_data = get_bill_data()
|
bill_data = get_bill_data()
|
||||||
bill_types = get_bill_types()
|
bill_types = get_bill_types()
|
||||||
|
bill_freqs = get_bill_freqs()
|
||||||
now=datetime.today().strftime('%Y-%m-%d')
|
now=datetime.today().strftime('%Y-%m-%d')
|
||||||
return render_template('bills.html', now=now, bill_data=bill_data, bill_types=bill_types )
|
derive_bill_data()
|
||||||
|
return render_template('bills.html', now=now, bill_data=bill_data, bill_types=bill_types, bill_freqs=bill_freqs )
|
||||||
|
|
||||||
@app.route('/newbilltype', methods=['POST'])
|
@app.route('/newbilltype', methods=['POST'])
|
||||||
def InsertBillType():
|
def InsertBillType():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
insert_bill_type( data['bill_type'] )
|
insert_bill_type( data['bill_type'], data['freq'] )
|
||||||
return "200"
|
return "200"
|
||||||
|
|
||||||
@app.route('/updatebilltype', methods=['POST'])
|
@app.route('/updatebilltype', methods=['POST'])
|
||||||
def UpdateBillType():
|
def UpdateBillType():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
update_bill_type( data['id'], data['bill_type'] )
|
update_bill_type( data['id'], data['bill_type'], data['freq'] )
|
||||||
return "200"
|
return "200"
|
||||||
|
|
||||||
@app.route('/newbill', methods=['POST'])
|
@app.route('/newbill', methods=['POST'])
|
||||||
|
|||||||
@@ -18,15 +18,57 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="containerfluid row">
|
<div class="pt-2 containerfluid row">
|
||||||
<h3 align="center">Bill Details (go to <a href="/">Finance Tracker</a>)</h3>
|
<h3 align="center">Bill Details (go to <a href="/">Finance Tracker</a>)</h3>
|
||||||
|
|
||||||
<div class="col-6">
|
<div class="mt-4 col-6">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<button id="new-bill-data-button" class="px-0 offset-6 col-2 btn btn-success" onCLick="StartNewBillData()"><span class="bi bi-plus-lg"> New Bill</span></button>
|
<button id="new-bill-type-button" class="mb-3 px-0 offset-2 col-2 btn btn-success" onCLick="StartNewBillType()"><span class="bi bi-plus-lg"> New Bill Type</span></button>
|
||||||
|
<div class="new-bill-type-class px-0 col-2 d-none"> <input type="text" class="form-control text-end float-end border border-primary" id="new-bill-type-name"></div>
|
||||||
|
<div class="new-bill-type-class px-0 col-2 d-none"><select id="new-bill-type-freq" class="form-select text-center">
|
||||||
|
{% for bf in bill_freqs %}
|
||||||
|
<option value={{bf.id}}>{{bf.name}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button id="save-bill-type" class="new-bill-type-class px-0 col-1 btn btn-success d-none" onClick="NewBillType()"><span class="bi bi-floppy"></span> Save</button>
|
||||||
|
<button id="canc-bill-type" class="new-bill-type-class px-0 col-1 btn btn-danger d-none" onClick="CancelNewBillType()"><span class="bi bi-trash3"> Cancel</span></button>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="px-0 col-2"><label class="form-control text-center border-0 fw-bold bg-light rounded-0">Name</ ></div>
|
||||||
|
<div class="px-0 col-2"><label class="form-control text-center border-0 fw-bold bg-light rounded-0">Frequency</ ></div>
|
||||||
|
<div class="px-0 col-2"><label class="form-control text-center border-0 fw-bold bg-light rounded-0">Annual Growth Est</ ></div>
|
||||||
|
<div class="px-0 col-2"><label class="form-control text-center border-0 fw-bold bg-light rounded-0">Actions</ ></div>
|
||||||
|
</div>
|
||||||
|
{% for bt in bill_types %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="px-0 col-2"><input type="text" class="bill-type-{{bt.id}} form-control text-center bg-white" id="bill-type-name-{{bt.id}}" value="{{ bt.name }}" disabled> </div>
|
||||||
|
<!-- bind Enter to save this bill-type -->
|
||||||
|
<script>$("#bill-type-name-{{bt.id}}").keyup(function(event){ if(event.which == 13){ $('#bill-type-save-{{bt.id}}').click(); } event.preventDefault(); });</script>
|
||||||
|
<div class="px-0 col-2"><select id="bill-type-freq-{{bt.id}}" class="bill-type-{{bt.id}} form-select text-center bg-white" disabled>
|
||||||
|
{% for bf in bill_freqs %}
|
||||||
|
<option value={{bf.id}}>{{bf.name}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<script>console.log( 'set freq to {{bt.freq}}' ); $('#bill-type-freq-{{bt.id}}').val( {{bt.freq}} );</script>
|
||||||
|
<div class="px-0 col-2"><input type="text" class="form-control text-center" id="bill-type-grow-{{bt.id}}" value="{{'%.2f'|format(bt.ann_growth)}}%" disabled> </div>
|
||||||
|
<button id="bill-type-chg-{{bt.id}}" class="px-0 col-1 btn btn-success" onClick="StartUpdateBillType( {{bt.id}} )">Change</button>
|
||||||
|
<button id="bill-type-del-{{bt.id}}" class="px-0 col-1 btn btn-danger" onClick="DelBillType({{bt.id}})"><span class="bi bi-trash3"> Delete</button>
|
||||||
|
<button id="bill-type-save-{{bt.id}}" class="px-0 col-1 btn btn-success d-none" onClick="UpdateBillType( {{bt.id}} )">Save</button>
|
||||||
|
<button id="bill-type-canc-{{bt.id}}" class="px-0 col-1 btn btn-danger d-none" onClick="CancelUpdateBillType({{bt.id}}, '{{bt.name}}')"><span class="bi bi-trash3"> Cancel</button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- right-hand-side, bill types (e.g. gas, phone, etc.) -->
|
||||||
|
|
||||||
|
<div class="pt-4 col-6">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<button id="new-bill-data-button" class="mb-3 px-0 offset-6 col-2 btn btn-success" onCLick="StartNewBillData()"><span class="bi bi-plus-lg"> New Bill</span></button>
|
||||||
<div class="new-bill-data-class px-0 col-2 d-none"> <select id="new-bill-data-type" class="form-select text-end float-end border border-primary">
|
<div class="new-bill-data-class px-0 col-2 d-none"> <select id="new-bill-data-type" class="form-select text-end float-end border border-primary">
|
||||||
{% for el in bill_types %}
|
{% for bt in bill_types %}
|
||||||
<option value={{el.id}}>{{el.name}}</option>
|
<option value={{bt.id}}>{{bt.name}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,54 +78,48 @@
|
|||||||
<span class="bi bi-floppy"></span> Save </button>
|
<span class="bi bi-floppy"></span> Save </button>
|
||||||
<button class="new-bill-data-class px-0 col-1 btn btn-danger d-none" onClick="CancelNewBill()" ><span class="bi bi-trash3"> Cancel</span> </button>
|
<button class="new-bill-data-class px-0 col-1 btn btn-danger d-none" onClick="CancelNewBill()" ><span class="bi bi-trash3"> Cancel</span> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="px-0 col-2"> <label class="form-control text-center border-0">Name</ > </div>
|
|
||||||
<div class="px-0 col-2"> <label class="form-control text-center border-0">Date</ > </div>
|
|
||||||
<div class="px-0 col-2"> <label class="form-control text-center border-0">Amount</ > </div>
|
|
||||||
</div>
|
|
||||||
{% for el in bill_data %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="px-0 col-2"> <input type="text" class="form-control text-center bg-white" id="bill-data-type-{{el.id}}" value="{{ el.name }}" disabled> </div>
|
|
||||||
<div class="px-0 col-2"> <input type="date" class="form-control text-center bg-white" id="bill-data-date-{{el.id}}" value="{{ el.bill_date }}" disabled> </div>
|
|
||||||
<div class="px-0 col-2"> <input type="number" class="form-control text-center bg-white" id="bill-data-amount-{{el.id}}" value="{{ el.amount }}" disabled> </div>
|
|
||||||
<button id="bill-data-chg-{{el.id}}" class="px-0 col-1 btn btn-success" onClick="StartUpdateBill( {{el.id}} )">Change</button>
|
|
||||||
<button id="bill-data-del-{{el.id}}" class="px-0 col-1 btn btn-danger" onClick="DeleteBill( {{el.id }} )"><span class="bi bi-trash3"> Delete
|
|
||||||
<button id="bill-data-save-{{el.id}}" class="px-0 col-1 btn btn-success d-none" onClick="UpdateBill( {{el.id}} )">Save</button>
|
|
||||||
<button id="bill-data-canc-{{el.id}}" class="px-0 col-1 btn btn-danger d-none"
|
|
||||||
onClick="CancelUpdateBill({{el.id}}, '{{el.name}}', '{{el.bill_date}}', '{{el.amount}}')"> <span class="bi bi-trash3"> Cancel</button>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- right-hand-side, bill types (e.g. gas, phone, etc.) -->
|
<!-- create tabbed view for each bill type -->
|
||||||
<div class="col-6">
|
<nav id="bills-nav" class="nav nav-tabs">
|
||||||
<div class="row align-items-center">
|
{% for bt in bill_types %}
|
||||||
<button id="new-bill-type-button" class="px-0 offset-2 col-2 btn btn-success" onCLick="StartNewBillType()"><span class="bi bi-plus-lg"> New Bill Type</span></button>
|
<button class="nav-link" id="tab-{{bt.name}}" data-bs-toggle="tab" data-bs-target="#tab-{{bt.id}}" type="button" role="tab" aria-controls="tab1" aria-selected="true">{{bt.name}}</button>
|
||||||
<div class="new-bill-type-class px-0 col-2 d-none"> <input type="text" class="form-control text-end float-end border border-primary" id="new-bill-type-name"></div>
|
|
||||||
<button id="save-bill-type" class="new-bill-type-class px-0 col-1 btn btn-success d-none" onClick="NewBillType()"><span class="bi bi-floppy"></span> Save</button>
|
|
||||||
<button id="canc-bill-type" class="new-bill-type-class px-0 col-1 btn btn-danger d-none" onClick="CancelNewBillType()"><span class="bi bi-trash3"> Cancel</span></button>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="px-0 col-2"><label class="form-control text-center border-0">Name</ ></div>
|
|
||||||
<div class="px-0 col-2"><label class="form-control text-center border-0">Frequency</ ></div>
|
|
||||||
<div class="px-0 col-2"><label class="form-control text-center border-0">Annual Growth Est</ ></div>
|
|
||||||
</div>
|
|
||||||
{% for el in bill_types %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="px-0 col-2"><input type="text" class="bill-type-name form-control text-center bg-white" id="bill-type-name-{{el.id}}" value="{{ el.name }}" disabled> </div>
|
|
||||||
<!-- bind Enter to save this bill-type -->
|
|
||||||
<script>$("#bill-type-name-{{el.id}}").keyup(function(event){ if(event.which == 13){ $('#bill-type-save-{{el.id}}').click(); } event.preventDefault(); });</script>
|
|
||||||
<div class="px-0 col-2"><input type="text" class="bill-type-{{el.id}} form-control text-center bg-white" id="bill-type-freq-{{el.id}}" value="not yet" disabled> </div>
|
|
||||||
<div class="px-0 col-2"><input type="text" class="bill-type-{{el.id}} form-control text-center bg-white" id="bill-type-grow-{{el.id}}" value="not yet" disabled> </div>
|
|
||||||
<button id="bill-type-chg-{{el.id}}" class="px-0 col-1 btn btn-success" onClick="StartUpdateBillType( {{el.id}} )">Change</button>
|
|
||||||
<button id="bill-type-del-{{el.id}}" class="px-0 col-1 btn btn-danger" onClick="DelBillType({{el.id}})"><span class="bi bi-trash3"> Delete</button>
|
|
||||||
<button id="bill-type-save-{{el.id}}" class="px-0 col-1 btn btn-success d-none" onClick="UpdateBillType( {{el.id}} )">Save</button>
|
|
||||||
<button id="bill-type-canc-{{el.id}}" class="px-0 col-1 btn btn-danger d-none" onClick="CancelUpdateBillType({{el.id}}, '{{el.name}}')"><span class="bi bi-trash3"> Cancel</button>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</nav>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
{% for bt in bill_types %}
|
||||||
|
{% if loop.first %}
|
||||||
|
<div id="tab-{{bt.id}}" class="tab-pane active">
|
||||||
|
{% else %}
|
||||||
|
<div id="tab-{{bt.id}}" class="tab-pane">
|
||||||
|
{% endif %}
|
||||||
|
{% for bd in bill_data %}
|
||||||
|
{% if loop.first %}
|
||||||
|
<div class="row pt-2">
|
||||||
|
<div class="p-0 col-2"> <label class="form-control text-center border-0 fw-bold bg-light rounded-0">Name</ > </div>
|
||||||
|
<div class="p-0 col-2"> <label class="form-control text-center border-0 fw-bold bg-light rounded-0">Date</ > </div>
|
||||||
|
<div class="p-0 col-2"> <label class="form-control text-center border-0 fw-bold bg-light rounded-0">Amount</ > </div>
|
||||||
|
<div class="px-0 col-2"><label class="form-control text-center border-0 fw-bold bg-light rounded-0">Actions</ ></div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if bd.bill_type_id == bt.id %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="px-0 col-2"> <input type="text" class="form-control text-center bg-white" id="bill-data-type-{{bd.id}}" value="{{ bd.name }}" disabled> </div>
|
||||||
|
<div class="px-0 col-2"> <input type="date" class="form-control text-center bg-white" id="bill-data-date-{{bd.id}}" value="{{ bd.bill_date }}" disabled> </div>
|
||||||
|
<div class="px-0 col-2"> <input type="number" class="form-control text-center bg-white" id="bill-data-amount-{{bd.id}}" value="{{ bd.amount }}" disabled> </div>
|
||||||
|
<button id="bill-data-chg-{{bd.id}}" class="px-0 col-1 btn btn-success" onClick="StartUpdateBill( {{bd.id}} )">Change</button>
|
||||||
|
<button id="bill-data-del-{{bd.id}}" class="px-0 col-1 btn btn-danger" onClick="DeleteBill( {{bd.id }} )"><span class="bi bi-trash3"> Delete
|
||||||
|
<button id="bill-data-save-{{bd.id}}" class="px-0 col-1 btn btn-success d-none" onClick="UpdateBill( {{bd.id}} )">Save</button>
|
||||||
|
<button id="bill-data-canc-{{bd.id}}" class="px-0 col-1 btn btn-danger d-none"
|
||||||
|
onClick="CancelUpdateBill({{bd.id}}, '{{bd.name}}', '{{bd.bill_date}}', '{{bd.amount}}')"> <span class="bi bi-trash3"> Cancel</button>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function StartNewBillData()
|
function StartNewBillData()
|
||||||
{
|
{
|
||||||
@@ -177,12 +213,14 @@
|
|||||||
$('.new-bill-type-class').addClass('d-none')
|
$('.new-bill-type-class').addClass('d-none')
|
||||||
$('#new-bill-type-button').removeClass('d-none')
|
$('#new-bill-type-button').removeClass('d-none')
|
||||||
$('#new-bill-type-name').val('')
|
$('#new-bill-type-name').val('')
|
||||||
|
// reset select to first option
|
||||||
|
$('#new-bill-type-freq').val( $('#new-bill-type-freq option:first').attr('value') )
|
||||||
}
|
}
|
||||||
|
|
||||||
function NewBillType()
|
function NewBillType()
|
||||||
{
|
{
|
||||||
$.ajax( { type: 'POST', url: '/newbilltype',
|
$.ajax( { type: 'POST', url: '/newbilltype',
|
||||||
contentType: 'application/json', data: JSON.stringify( { 'bill_type': $('#new-bill-type-name').val() } ),
|
contentType: 'application/json', data: JSON.stringify( { 'bill_type': $('#new-bill-type-name').val(), 'freq': $('#new-bill-type-freq').val() } ),
|
||||||
success: function() { window.location='bills' } } )
|
success: function() { window.location='bills' } } )
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,11 +228,11 @@
|
|||||||
{
|
{
|
||||||
val=$('#bill-type-name-'+id).val()
|
val=$('#bill-type-name-'+id).val()
|
||||||
|
|
||||||
// "disable" the freq & growth
|
// "enable" fields for edits
|
||||||
$('.bill-type-'+id).addClass('bg-light text-secondary').removeClass('bg-white')
|
$('.bill-type-'+id).prop('disabled', false)
|
||||||
|
|
||||||
// "enable" name for edits
|
// put focus into name field
|
||||||
$('#bill-type-name-'+id).prop('disabled', false).focus()
|
$('#bill-type-name-'+id).focus()
|
||||||
|
|
||||||
// move cursor to the end after 'focus()' above
|
// move cursor to the end after 'focus()' above
|
||||||
$('#bill-type-name-'+id).val('').val( val )
|
$('#bill-type-name-'+id).val('').val( val )
|
||||||
@@ -209,7 +247,7 @@
|
|||||||
function UpdateBillType(id)
|
function UpdateBillType(id)
|
||||||
{
|
{
|
||||||
$.ajax( { type: 'POST', url: '/updatebilltype',
|
$.ajax( { type: 'POST', url: '/updatebilltype',
|
||||||
contentType: 'application/json', data: JSON.stringify( { 'id': id, 'bill_type': $('#bill-type-name-'+id).val() } ),
|
contentType: 'application/json', data: JSON.stringify( { 'id': id, 'bill_type': $('#bill-type-name-'+id).val(), 'freq': $('#bill-type-freq-'+id).val() } ),
|
||||||
success: function() { window.location='bills' } } )
|
success: function() { window.location='bills' } } )
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,6 +279,11 @@
|
|||||||
$("#new-bill-type-name").keyup(function(event){ if(event.which == 13){ $("#save-bill-type").click(); } event.preventDefault(); });
|
$("#new-bill-type-name").keyup(function(event){ if(event.which == 13){ $("#save-bill-type").click(); } event.preventDefault(); });
|
||||||
|
|
||||||
// note we also dynamically bound each bill-type-name to save on Enter when we create them in a loop
|
// note we also dynamically bound each bill-type-name to save on Enter when we create them in a loop
|
||||||
|
|
||||||
|
// force something to be active
|
||||||
|
$('#bills-nav .nav-link').first().addClass('active');
|
||||||
|
// now go back to last tab, as per something I dont know yet :)
|
||||||
|
$('#tab-Water').tab('show');
|
||||||
} )
|
} )
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user