fix: update sleep debt chart payload to ensure accurate date handling and current debt representation
All checks were successful
Deploy Development / deploy (push) Successful in 1m0s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 17s

- Modified the `build_sleep_debt_chart_payload` function to correctly handle date types, ensuring only valid dates are processed.
- Enhanced the logic to append today's date and current debt value to the chart data if the last recorded date is earlier than today, aligning the chart with KPI metrics.
- Updated metadata calculations to reflect the correct number of data points based on labels, improving the accuracy of the recovery chart payload.
This commit is contained in:
Lars 2026-04-20 12:57:47 +02:00
parent 6c962bf6e5
commit 45fb506a5e

View File

@ -6,7 +6,7 @@ Ausgelagert aus routers/charts.py (Issue 53 / Layer 1).
from __future__ import annotations from __future__ import annotations
from datetime import datetime, timedelta from datetime import date, datetime, timedelta
from typing import Any, Dict, Optional, Set from typing import Any, Dict, Optional, Set
from db import get_db, get_cursor from db import get_db, get_cursor
@ -333,14 +333,31 @@ def build_sleep_debt_chart_payload(profile_id: str, days: int) -> Dict[str, Any]
}, },
} }
labels = [] labels: list[str] = []
debt_values = [] debt_values: list[float] = []
for r in visible: for r in visible:
rd = r.get("date") rd = r.get("date")
end_d = rd.date() if isinstance(rd, datetime) else rd end_d = rd.date() if isinstance(rd, datetime) else rd
labels.append(end_d.isoformat() if hasattr(end_d, "isoformat") else str(end_d)) if not isinstance(end_d, date):
continue
labels.append(end_d.isoformat())
debt_values.append(sleep_debt_sum_hours_in_window(all_rows, end_d)) debt_values.append(sleep_debt_sum_hours_in_window(all_rows, end_d))
# KPI nutzt immer Fensterende = heute; die Kurve endete bisher am Datum der letzten Schlaf-Zeile
# (z. B. gestern) → anderes 14-Tage-Fenster. Letzter Punkt = exakt KPI-Wert, Datum = heute.
today = datetime.now().date()
if labels and debt_values:
try:
last_d = date.fromisoformat(labels[-1])
except (TypeError, ValueError):
last_d = None
if last_d is not None:
if last_d < today:
labels.append(today.isoformat())
debt_values.append(float(current_debt))
elif last_d == today:
debt_values[-1] = float(current_debt)
return { return {
"chart_type": "line", "chart_type": "line",
"data": { "data": {
@ -360,13 +377,14 @@ def build_sleep_debt_chart_payload(profile_id: str, days: int) -> Dict[str, Any]
"metadata": serialize_dates( "metadata": serialize_dates(
{ {
"confidence": calculate_confidence(len(visible), days, "general"), "confidence": calculate_confidence(len(visible), days, "general"),
"data_points": len(visible), "data_points": len(labels),
"current_debt_hours": round(float(current_debt), 1), "current_debt_hours": round(float(current_debt), 1),
"sleep_debt_target_hours_per_night": SLEEP_DEBT_TARGET_HOURS_DEFAULT, "sleep_debt_target_hours_per_night": SLEEP_DEBT_TARGET_HOURS_DEFAULT,
"rolling_window_days": SLEEP_DEBT_ROLLING_WINDOW_DAYS, "rolling_window_days": SLEEP_DEBT_ROLLING_WINDOW_DAYS,
"note": "Gleiche Formel wie KPI: Summe der nächtlichen Defizite vs. " "note": "Gleiche Formel wie KPI: Summe der nächtlichen Defizite vs. "
f"{SLEEP_DEBT_TARGET_HOURS_DEFAULT} h/Nacht im rollierenden {SLEEP_DEBT_ROLLING_WINDOW_DAYS}-Tage-Fenster " f"{SLEEP_DEBT_TARGET_HOURS_DEFAULT} h/Nacht im rollierenden {SLEEP_DEBT_ROLLING_WINDOW_DAYS}-Tage-Fenster. "
"(jeder Punkt = Fensterende an dem Datum). Ziel aktuell nicht in den Profileinstellungen änderbar.", "Zwischenpunkte: Fensterende = Datum der jeweiligen Schlaf-Zeile; "
"letzter Punkt ist auf «heute» bzw. KPI-Wert gesetzt, damit Kurve und Kachel übereinstimmen.",
} }
), ),
} }