Graph hinzugefügt
This commit is contained in:
parent
b65125fcf4
commit
43641057f2
3 changed files with 174 additions and 25 deletions
100
app.py
100
app.py
|
|
@ -8,6 +8,7 @@ from urllib.request import urlopen
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from influxdb_client import InfluxDBClient
|
from influxdb_client import InfluxDBClient
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
@ -184,14 +185,16 @@ def get_balance_color(balance):
|
||||||
return "green"
|
return "green"
|
||||||
|
|
||||||
|
|
||||||
def get_balance_history(days=30):
|
def get_balance_comparison():
|
||||||
|
|
||||||
if not all([
|
if not all([
|
||||||
INFLUX_URL,
|
INFLUX_URL,
|
||||||
INFLUX_ORG,
|
INFLUX_ORG,
|
||||||
INFLUX_BUCKET,
|
INFLUX_BUCKET,
|
||||||
INFLUX_TOKEN
|
INFLUX_TOKEN
|
||||||
]):
|
]):
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
client = InfluxDBClient(
|
client = InfluxDBClient(
|
||||||
url=INFLUX_URL,
|
url=INFLUX_URL,
|
||||||
token=INFLUX_TOKEN,
|
token=INFLUX_TOKEN,
|
||||||
|
|
@ -200,24 +203,103 @@ def get_balance_history(days=30):
|
||||||
|
|
||||||
query = f'''
|
query = f'''
|
||||||
from(bucket: "{INFLUX_BUCKET}")
|
from(bucket: "{INFLUX_BUCKET}")
|
||||||
|> range(start: -{days}d)
|
|> range(start: -180d)
|
||||||
|> filter(fn: (r) => r._measurement == "Kontostand")
|
|> filter(fn: (r) => r._measurement == "Kontostand")
|
||||||
|> filter(fn: (r) => r._field == "value")
|
|> filter(fn: (r) => r._field == "value")
|
||||||
'''
|
'''
|
||||||
|
|
||||||
result = client.query_api().query(query)
|
result = client.query_api().query(query)
|
||||||
|
|
||||||
history = []
|
raw_data = []
|
||||||
|
|
||||||
for table in result:
|
for table in result:
|
||||||
for record in table.records:
|
for record in table.records:
|
||||||
|
|
||||||
history.append({
|
raw_data.append({
|
||||||
"date": record.get_time().strftime("%d.%m"),
|
"time": record.get_time(),
|
||||||
"value": round(record.get_value(), 2)
|
"value": round(record.get_value(), 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
return history
|
raw_data.sort(
|
||||||
|
key=lambda x: x["time"]
|
||||||
|
)
|
||||||
|
|
||||||
|
periods = defaultdict(dict)
|
||||||
|
|
||||||
|
for item in raw_data:
|
||||||
|
|
||||||
|
dt = item["time"]
|
||||||
|
|
||||||
|
if dt.day >= 15:
|
||||||
|
|
||||||
|
period_start = datetime(
|
||||||
|
dt.year,
|
||||||
|
dt.month,
|
||||||
|
15
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
if dt.month == 1:
|
||||||
|
|
||||||
|
period_start = datetime(
|
||||||
|
dt.year - 1,
|
||||||
|
12,
|
||||||
|
15
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
period_start = datetime(
|
||||||
|
dt.year,
|
||||||
|
dt.month - 1,
|
||||||
|
15
|
||||||
|
)
|
||||||
|
|
||||||
|
day_index = (
|
||||||
|
dt.date() -
|
||||||
|
period_start.date()
|
||||||
|
).days + 1
|
||||||
|
|
||||||
|
periods[period_start][day_index] = item["value"]
|
||||||
|
|
||||||
|
sorted_periods = sorted(
|
||||||
|
periods.keys(),
|
||||||
|
reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
|
result_data = {}
|
||||||
|
|
||||||
|
names = [
|
||||||
|
"current",
|
||||||
|
"period_1",
|
||||||
|
"period_2",
|
||||||
|
"period_3",
|
||||||
|
"period_4"
|
||||||
|
]
|
||||||
|
|
||||||
|
for idx, period in enumerate(sorted_periods[:5]):
|
||||||
|
|
||||||
|
data = []
|
||||||
|
|
||||||
|
days = periods[period]
|
||||||
|
|
||||||
|
last_value = None
|
||||||
|
|
||||||
|
for day in range(1, 32):
|
||||||
|
|
||||||
|
if day in days:
|
||||||
|
last_value = days[day]
|
||||||
|
|
||||||
|
if last_value is not None:
|
||||||
|
data.append({
|
||||||
|
"day": day,
|
||||||
|
"value": last_value
|
||||||
|
})
|
||||||
|
|
||||||
|
result_data[names[idx]] = data
|
||||||
|
|
||||||
|
return result_data
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
|
|
||||||
|
|
@ -238,8 +320,8 @@ def index():
|
||||||
balance
|
balance
|
||||||
)
|
)
|
||||||
|
|
||||||
balance_history = get_balance_history()
|
balance_history = get_balance_comparison()
|
||||||
|
print(balance_history)
|
||||||
return render_template(
|
return render_template(
|
||||||
"index.html",
|
"index.html",
|
||||||
year=year,
|
year=year,
|
||||||
|
|
|
||||||
|
|
@ -384,3 +384,9 @@ text-decoration: underline;
|
||||||
|
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
.chart-card {
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
|
||||||
|
min-height: 550px;
|
||||||
|
}
|
||||||
|
|
@ -114,10 +114,10 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card chart-card">
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
Kontostand letzte 30 Tage
|
Kontostandvergleich
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<canvas id="balanceChart"></canvas>
|
<canvas id="balanceChart"></canvas>
|
||||||
|
|
@ -257,8 +257,25 @@ Hintergasse © 2026
|
||||||
|
|
||||||
const history = {{ balance_history|tojson }};
|
const history = {{ balance_history|tojson }};
|
||||||
|
|
||||||
const labels = history.map(item => item.date);
|
const labels = Array.from(
|
||||||
const values = history.map(item => item.value);
|
{length: 31},
|
||||||
|
(_, i) => i + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
function getSeries(periodName) {
|
||||||
|
|
||||||
|
const values = new Array(31).fill(null);
|
||||||
|
|
||||||
|
if (!history[periodName]) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
history[periodName].forEach(item => {
|
||||||
|
values[item.day - 1] = item.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
new Chart(
|
new Chart(
|
||||||
document.getElementById("balanceChart"),
|
document.getElementById("balanceChart"),
|
||||||
|
|
@ -266,27 +283,75 @@ new Chart(
|
||||||
type: "line",
|
type: "line",
|
||||||
|
|
||||||
data: {
|
data: {
|
||||||
|
|
||||||
labels: labels,
|
labels: labels,
|
||||||
|
|
||||||
datasets: [{
|
datasets: [
|
||||||
label: "Kontostand (€)",
|
|
||||||
data: values,
|
{
|
||||||
tension: 0.3
|
label: "Aktuell",
|
||||||
}]
|
data: getSeries("current"),
|
||||||
|
tension: 0.3,
|
||||||
|
borderWidth: 4
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "-1 Monat",
|
||||||
|
data: getSeries("period_1"),
|
||||||
|
tension: 0.3
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "-2 Monate",
|
||||||
|
data: getSeries("period_2"),
|
||||||
|
tension: 0.3
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "-3 Monate",
|
||||||
|
data: getSeries("period_3"),
|
||||||
|
tension: 0.3
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "-4 Monate",
|
||||||
|
data: getSeries("period_4"),
|
||||||
|
tension: 0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
|
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
|
||||||
|
interaction: {
|
||||||
|
mode: "index",
|
||||||
|
intersect: false
|
||||||
|
},
|
||||||
|
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
display: false
|
display: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
scales: {
|
scales: {
|
||||||
|
|
||||||
|
x: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Tag seit dem 15."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
y: {
|
y: {
|
||||||
beginAtZero: false
|
beginAtZero: false,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Kontostand (€)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +359,3 @@ new Chart(
|
||||||
);
|
);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue