From 45fb506a5e0f31e584cfdbeb004328e3c730bef2 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 20 Apr 2026 12:57:47 +0200 Subject: [PATCH] fix: update sleep debt chart payload to ensure accurate date handling and current debt representation - 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. --- backend/data_layer/recovery_chart_payloads.py | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/backend/data_layer/recovery_chart_payloads.py b/backend/data_layer/recovery_chart_payloads.py index 6959d7a..d4d0f6c 100644 --- a/backend/data_layer/recovery_chart_payloads.py +++ b/backend/data_layer/recovery_chart_payloads.py @@ -6,7 +6,7 @@ Ausgelagert aus routers/charts.py (Issue 53 / Layer 1). from __future__ import annotations -from datetime import datetime, timedelta +from datetime import date, datetime, timedelta from typing import Any, Dict, Optional, Set 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 = [] - debt_values = [] + labels: list[str] = [] + debt_values: list[float] = [] for r in visible: rd = r.get("date") 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)) + # 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 { "chart_type": "line", "data": { @@ -360,13 +377,14 @@ def build_sleep_debt_chart_payload(profile_id: str, days: int) -> Dict[str, Any] "metadata": serialize_dates( { "confidence": calculate_confidence(len(visible), days, "general"), - "data_points": len(visible), + "data_points": len(labels), "current_debt_hours": round(float(current_debt), 1), "sleep_debt_target_hours_per_night": SLEEP_DEBT_TARGET_HOURS_DEFAULT, "rolling_window_days": SLEEP_DEBT_ROLLING_WINDOW_DAYS, "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 " - "(jeder Punkt = Fensterende an dem Datum). Ziel aktuell nicht in den Profileinstellungen änderbar.", + f"{SLEEP_DEBT_TARGET_HOURS_DEFAULT} h/Nacht im rollierenden {SLEEP_DEBT_ROLLING_WINDOW_DAYS}-Tage-Fenster. " + "Zwischenpunkte: Fensterende = Datum der jeweiligen Schlaf-Zeile; " + "letzter Punkt ist auf «heute» bzw. KPI-Wert gesetzt, damit Kurve und Kachel übereinstimmen.", } ), }