diff --git a/app.py b/app.py index 7d6925b..512d903 100644 --- a/app.py +++ b/app.py @@ -8,6 +8,7 @@ from urllib.request import urlopen from pathlib import Path from influxdb_client import InfluxDBClient from datetime import datetime, timedelta +from collections import defaultdict app = Flask(__name__) @@ -184,14 +185,16 @@ def get_balance_color(balance): return "green" -def get_balance_history(days=30): +def get_balance_comparison(): + if not all([ INFLUX_URL, INFLUX_ORG, INFLUX_BUCKET, INFLUX_TOKEN ]): - return [] + return {} + client = InfluxDBClient( url=INFLUX_URL, token=INFLUX_TOKEN, @@ -200,24 +203,103 @@ def get_balance_history(days=30): query = f''' from(bucket: "{INFLUX_BUCKET}") - |> range(start: -{days}d) + |> range(start: -180d) |> filter(fn: (r) => r._measurement == "Kontostand") |> filter(fn: (r) => r._field == "value") ''' result = client.query_api().query(query) - history = [] + raw_data = [] for table in result: for record in table.records: - history.append({ - "date": record.get_time().strftime("%d.%m"), + raw_data.append({ + "time": record.get_time(), "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("/") def index(): @@ -238,8 +320,8 @@ def index(): balance ) - balance_history = get_balance_history() - + balance_history = get_balance_comparison() + print(balance_history) return render_template( "index.html", year=year, diff --git a/static/style.css b/static/style.css index f654179..10849ac 100644 --- a/static/style.css +++ b/static/style.css @@ -383,4 +383,10 @@ text-decoration: underline; line-height: 1.6; margin-bottom: 20px; +} +.chart-card { + + grid-column: 1 / -1; + + min-height: 550px; } \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index dfcc47d..3b08b44 100644 --- a/templates/index.html +++ b/templates/index.html @@ -114,10 +114,10 @@

-
+

- Kontostand letzte 30 Tage + Kontostandvergleich

@@ -257,8 +257,25 @@ Hintergasse © 2026 const history = {{ balance_history|tojson }}; -const labels = history.map(item => item.date); -const values = history.map(item => item.value); +const labels = Array.from( + {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( document.getElementById("balanceChart"), @@ -266,35 +283,79 @@ new Chart( type: "line", data: { + labels: labels, - datasets: [{ - label: "Kontostand (€)", - data: values, - tension: 0.3 - }] + datasets: [ + + { + 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: { + responsive: true, + interaction: { + mode: "index", + intersect: false + }, + plugins: { legend: { - display: false + display: true } }, scales: { + + x: { + title: { + display: true, + text: "Tag seit dem 15." + } + }, + y: { - beginAtZero: false + beginAtZero: false, + title: { + display: true, + text: "Kontostand (€)" + } } } } } ); - - - - - + \ No newline at end of file