comparison now works as required

This commit is contained in:
2025-02-13 21:51:39 +11:00
parent 14de3f1790
commit 1272d3a786
4 changed files with 66 additions and 48 deletions

View File

@@ -22,6 +22,6 @@
2025-11-12,410660.56,2026-10-14,337111.91,2027-10-13,238202.3,2028-10-11,191045.16,2029-10-10,137624.31,2030-10-09,55704.53,,,,,,,Overseas_trip_date,2025-06-01 2025-11-12,410660.56,2026-10-14,337111.91,2027-10-13,238202.3,2028-10-11,191045.16,2029-10-10,137624.31,2030-10-09,55704.53,,,,,,,Overseas_trip_date,2025-06-01
2025-11-26,406370.89,2026-10-28,322702.74,2027-10-27,234658.94,2028-10-25,187361.11,2029-10-24,133793.99,2030-10-23,51722.12,,,,,,,Mark_reno_date,2025-09-01 2025-11-26,406370.89,2026-10-28,322702.74,2027-10-27,234658.94,2028-10-25,187361.11,2029-10-24,133793.99,2030-10-23,51722.12,,,,,,,Mark_reno_date,2025-09-01
2025-12-10,381758.47,2026-11-11,319692.08,2027-11-10,232115.41,2028-11-08,184475.65,2029-11-07,130534.62,2030-11-06,47961.98,,,,,,,Sell_shares,6 2025-12-10,381758.47,2026-11-11,319692.08,2027-11-10,232115.41,2028-11-08,184475.65,2029-11-07,130534.62,2030-11-06,47961.98,,,,,,,Sell_shares,6
2025-12-24,377458.1,2026-11-25,270448.27,2027-11-24,228560.53,2028-11-22,180779.63,2029-11-21,126691.85,2030-11-20,43966.63,,,,,, 2025-12-24,377458.1,2026-11-25,270448.27,2027-11-24,228560.53,2028-11-22,180779.63,2029-11-21,126691.85,2030-11-20,43966.63,,,,,,CBA,0
,,2026-12-09,268232.01,2027-12-08,225946.99,2028-12-06,177828.21,2029-12-05,123371.23,2030-12-04,40153.28,,,,,, ,,2026-12-09,268232.01,2027-12-08,225946.99,2028-12-06,177828.21,2029-12-05,123371.23,2030-12-04,40153.28,,,,,,TLS,0
,,2026-12-23,264801.78,2027-12-22,222380.56,2028-12-20,174120.17,2029-12-19,119515.97,2030-12-18,36144.95,,,,,, ,,2026-12-23,264801.78,2027-12-22,222380.56,2028-12-20,174120.17,2029-12-19,119515.97,2030-12-18,36144.95,,,,,,
1 2025-Date,2025-Value,2026-Date,2026-Value,2027-Date,2027-Value,2028-Date,2028-Value,2029-Date,2029-Value,2030-Date,2030-Value,2031-Date,2031-Value
22 2025-11-12,410660.56,2026-10-14,337111.91,2027-10-13,238202.3,2028-10-11,191045.16,2029-10-10,137624.31,2030-10-09,55704.53,,,,,,,Overseas_trip_date,2025-06-01
23 2025-11-26,406370.89,2026-10-28,322702.74,2027-10-27,234658.94,2028-10-25,187361.11,2029-10-24,133793.99,2030-10-23,51722.12,,,,,,,Mark_reno_date,2025-09-01
24 2025-12-10,381758.47,2026-11-11,319692.08,2027-11-10,232115.41,2028-11-08,184475.65,2029-11-07,130534.62,2030-11-06,47961.98,,,,,,,Sell_shares,6
25 2025-12-24,377458.1,2026-11-25,270448.27,2027-11-24,228560.53,2028-11-22,180779.63,2029-11-21,126691.85,2030-11-20,43966.63,,,,,, 2025-12-24,377458.1,2026-11-25,270448.27,2027-11-24,228560.53,2028-11-22,180779.63,2029-11-21,126691.85,2030-11-20,43966.63,,,,,,CBA,0
26 ,,2026-12-09,268232.01,2027-12-08,225946.99,2028-12-06,177828.21,2029-12-05,123371.23,2030-12-04,40153.28,,,,,, ,,2026-12-09,268232.01,2027-12-08,225946.99,2028-12-06,177828.21,2029-12-05,123371.23,2030-12-04,40153.28,,,,,,TLS,0
27 ,,2026-12-23,264801.78,2027-12-22,222380.56,2028-12-20,174120.17,2029-12-19,119515.97,2030-12-18,36144.95,,,,,,

8
README
View File

@@ -1,12 +1,4 @@
TODO: TODO:
* compare feature
[done] -- decided this is best supported by removing export to CSV function, and instead offering export to comparisons database (with a user-defined name)
[done] -- then maintain DB of "sets" of comparisons
[done] -- then can allow graph compare of current data to 1 (or more) exported comparions set
-- and show differences in graph including visually of any var changes in legend / or with tooltips
- specifically legend is not working
- tooltip (for legend?) not working
- highlighting differences in vars at top (maybe via colour of label? and a tooltip?)
* make save button create a comparison set to use * make save button create a comparison set to use
(also consider how to clean / re-create db initial values from code -- easily could just drop/recreate per table, and only drop finance, not csets) (also consider how to clean / re-create db initial values from code -- easily could just drop/recreate per table, and only drop finance, not csets)
* then delete export button * then delete export button

8
db.py
View File

@@ -62,7 +62,9 @@ def init_db():
CBA_price REAL, CBA_price REAL,
Overseas_trip_date STRING, Overseas_trip_date STRING,
Mark_reno_date STRING, Mark_reno_date STRING,
Sell_shares INTEGER Sell_shares INTEGER,
CBA INTEGER,
TLS INTEGER
)''') )''')
cur.execute('''CREATE TABLE IF NOT EXISTS comparison_savings_data ( cur.execute('''CREATE TABLE IF NOT EXISTS comparison_savings_data (
@@ -153,13 +155,13 @@ def insert_cset( data ):
name, D_Salary, D_Num_fortnights_pay, School_Fees, Car_loan_via_pay, name, D_Salary, D_Num_fortnights_pay, School_Fees, Car_loan_via_pay,
Car_loan, Car_balloon, Living_Expenses, Savings, Interest_Rate, Inflation, Mich_present, Car_loan, Car_balloon, Living_Expenses, Savings, Interest_Rate, Inflation, Mich_present,
Overseas_trip, Mark_reno, D_leave_owed_in_days, D_TLS_shares, M_TLS_shares, D_CBA_shares, 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, Sell_shares TLS_price, CBA_price, Overseas_trip_date, Mark_reno_date, Sell_shares, CBA, TLS
) )
VALUES ( VALUES (
:name, :D_Salary, :D_Num_fortnights_pay, :School_Fees, :Car_loan_via_pay, :name, :D_Salary, :D_Num_fortnights_pay, :School_Fees, :Car_loan_via_pay,
:Car_loan, :Car_balloon, :Living_Expenses, :Savings, :Interest_Rate, :Inflation, :Mich_present, :Car_loan, :Car_balloon, :Living_Expenses, :Savings, :Interest_Rate, :Inflation, :Mich_present,
:Overseas_trip, :Mark_reno, :D_leave_owed_in_days, :D_TLS_shares, :M_TLS_shares, :D_CBA_shares, :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, :Sell_shares :TLS_price, :CBA_price, :Overseas_trip_date, :Mark_reno_date, :Sell_shares, :CBA, :TLS
) )
''', data['vars']) ''', data['vars'])
cset_id = cur.lastrowid cset_id = cur.lastrowid

View File

@@ -3,8 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Finance Form</title> <title>Finance Form</title>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/annotations.js"></script> <script src="https://code.highcharts.com/modules/annotations.js"></script>
@@ -21,24 +23,43 @@
{% for r in DISP %} {% for r in DISP %}
<div class="row align-items-center"> <div class="row align-items-center">
{% for el in r %} {% for el in r %}
{% if COMP and COMP['vars'][el.varname] != finance[el.varname] %}
{% set extra=" text-primary" %}
{% else %}
{% set extra="" %}
{% endif %}
<div class="{{el.cl}}"> <div class="{{el.cl}}">
<div class="input-group"> <div class="input-group">
<label for="{{el.varname}}"
{% if el.display=="select" %} {% if el.display=="select" %}
<label for="{{el.varname}}" class="col-form-label me-2 text-end float-end">{{el.label}}</label> {% if COMP and COMP['vars'][el.varname] != finance[el.varname] %}
<select class="form-select border border-primary text-primary" id="{{el.varname}}" name="{{el.varname}}" style="width: 120px;" onchange="this.form.submit()"> data-bs-toggle="tooltip" title="Comparison was: {{COMP['vars'][el.varname]}}"
{% endif %}
class="col-form-label me-2 text-end float-end {{extra}}">{{el.label}}
</label>
<select class="form-select border border-primary text-primary" id="{{el.varname}}" name="{{el.varname}}" style="width: 120px;"
onchange="this.form.submit()">
<option value="0">Never</option> <option value="0">Never</option>
{% for el in range( 1,7 ) %} {% for el in range( 1,7 ) %}
<option value="{{el}}">{{el}} years</option> <option value="{{el}}">{{el}} years</option>
{% endfor %} {% endfor %}
</select> </select>
{% elif el.display=="date" %} {% elif el.display=="date" %}
<label for="{{el.varname}}" class="col-form-label me-2 text-end float-end">{{el.label}}</label> {% if COMP and COMP['vars'][el.varname] != finance[el.varname] %}
data-bs-toggle="tooltip" title="Comparison was: {{COMP['vars'][el.varname]}}"
{% endif %}
class="col-form-label me-2 text-end float-end {{extra}}">{{el.label}}
</label>
<input type="number" step="any" class="form-control text-end float-end border border-primary" onchange="this.form.submit()" style="max-width: 120px;" <input type="number" step="any" class="form-control text-end float-end border border-primary" onchange="this.form.submit()" style="max-width: 120px;"
id="{{el.varname}}" name="{{el.varname}}" value="{{ finance[el.varname] }}" {{el.display}}> id="{{el.varname}}" name="{{el.varname}}" value="{{ finance[el.varname] }}" {{el.display}}>
<input type="date" class="form-control text-end float-end border border-primary" id="{{el.datevarname}}" style="max-width: 150px;" <input type="date" class="form-control text-end float-end border border-primary" id="{{el.datevarname}}" style="max-width: 150px;"
name="{{el.datevarname}}" value="{{ finance[el.datevarname] }}" onchange="this.form.submit()"> name="{{el.datevarname}}" value="{{ finance[el.datevarname] }}" onchange="this.form.submit()">
{% else %} {% else %}
<label for="{{el.varname}}" class="col-form-label me-2 text-end float-end">{{el.label}}</label> {% if COMP and COMP['vars'][el.varname] != finance[el.varname] %}
data-bs-toggle="tooltip" title="Comparison was: {{COMP['vars'][el.varname]}}"
{% endif %}
class="col-form-label me-2 text-end float-end {{extra}}">{{el.label}}
</label>
{% if el.display== "readonly" %} {% if el.display== "readonly" %}
{% set bg="bg-light" %} {% set bg="bg-light" %}
{% set bd="" %} {% set bd="" %}
@@ -99,7 +120,8 @@
<div class="alert alert-success">Super kicks in!!!</div> <div class="alert alert-success">Super kicks in!!!</div>
{% endif %} {% endif %}
{% if COMP %} {% if COMP %}
<div class="alert alert-info">Note: value in blue<br>above is value we<br>should have been<br>at when comparing<br> to saved values</div> <div style="width:168px" class="alert alert-info">Note: The blue $ figure above is the final value of compared to set. Hover over blue labels above to see what compared to value was</div>
{% endif %} {% endif %}
</div> </div>
<div class="col-auto"> <div class="col-auto">
@@ -146,6 +168,9 @@
window.onload = function() { window.onload = function() {
$('#Sell_shares').val( {{finance['Sell_shares']}} ) $('#Sell_shares').val( {{finance['Sell_shares']}} )
$('#compare_to').val( {{finance['compare_to']}} ) $('#compare_to').val( {{finance['compare_to']}} )
var tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle='tooltip']"))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl) })
}; };
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
@@ -157,14 +182,12 @@
const compChartData = compSavingsData.map(entry => [new Date(entry[0]).getTime(), parseFloat(entry[1])]); const compChartData = compSavingsData.map(entry => [new Date(entry[0]).getTime(), parseFloat(entry[1])]);
{% endif %} {% endif %}
// Get the legend name and vars for the tooltip // Get the legend name and vars for the tooltip
const legendName = 'Savings'; const legendName = 'Savings';
const vars = JSON.parse('{{ finance | tojson }}'); const vars = JSON.parse('{{ finance | tojson }}');
// Tooltip content from vars // Tooltip content from vars
const tooltipContent = Object.entries(vars).map(([key, value]) => `${key}: ${value}`).join('<br>'); const tooltipContent = Object.entries(vars).map(([key, value]) => `${key}: ${value}`).join('<br>');
console.log(tooltipContent)
// Calculate plot bands for each year with alternating background colors // Calculate plot bands for each year with alternating background colors
const plotBands = []; const plotBands = [];
@@ -194,6 +217,8 @@
}); });
const annotations = []; const annotations = [];
// the al, x, offset are used to make the altenrate annotations be on slightly different vertical offsets (size is based on $'s)
// al alternates every 2 annotations left / right (so 2 left, then 2 right), x is just used to also move the label more left/right to get the connecting line
var offset=13 var offset=13
var al='left' var al='left'
var x=-130 var x=-130
@@ -218,7 +243,7 @@
}); });
if( offset == 150 ) { offset=100 } else { offset=150 } if( offset == 150 ) { offset=100 } else { offset=150 }
if( done == 2 ) { if( done == 2 ) {
if( al=='right' ) { console.log('change to left'); al='left'; x=-130 } else { console.log('change to right'); al='right'; x=130 } if( al=='right' ) { al='left'; x=-130 } else { al='right'; x=130 }
done=0 done=0
} }
done++ done++
@@ -236,13 +261,12 @@
plotBands: plotBands // Alternating background for years plotBands: plotBands // Alternating background for years
}, },
yAxis: { title: { text: 'Amount ($)' } }, yAxis: { title: { text: 'Amount ($)' } },
legend: { labelFormatter: function () { return `<span title="${tooltipContent}">${legendName}</span>`; } },
tooltip: { pointFormat: '{point.x:%Y-%m-%d}: <b>{point.y:.2f}</b>' }, tooltip: { pointFormat: '{point.x:%Y-%m-%d}: <b>{point.y:.2f}</b>' },
annotations: annotations, // Add annotations annotations: annotations, // Add annotations
series: [ series: [
{ name: legendName, data: chartData, marker: { radius: 2 } } { name: "Savings", data: chartData, marker: { radius: 2 } }
{% if COMP %} {% if COMP %}
,{ name: "TEST", data: compChartData, marker: { radius: 2 } } ,{ name: "{{COMP['vars']['name']}}", data: compChartData, marker: { radius: 2 } }
{% endif %} {% endif %}
] ]
}); });