diff --git a/backend/app/services/garmin_connect_sync.py b/backend/app/services/garmin_connect_sync.py index 483e5a2..ccd62fe 100644 --- a/backend/app/services/garmin_connect_sync.py +++ b/backend/app/services/garmin_connect_sync.py @@ -325,40 +325,23 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db, logger.warning("Failed to upsert health_metrics for %s: %s", day_str, exc) db.rollback() - # Fetch current VO2 max once (slow-changing — only update today's row) + # Fetch VO2 max from training status (slow-changing — store against measurement date) today_str = date.today().isoformat() - ts_data = _safe(garmin.get_training_status, today_str) - logger.info("training_status raw response: %s", ts_data) - sb_data = _safe(garmin.get_stats_and_body, today_str) - logger.info("stats_and_body raw response: %s", sb_data) + ts_data = _safe(garmin.get_training_status, today_str) fa_data = _safe(garmin.get_fitnessage_data, today_str) vo2 = None - # Try training status first - if ts_data and not vo2: - for key in ("vo2MaxPreciseValue", "vo2Max", "latestVO2Max"): - v = ts_data.get(key) - if v and isinstance(v, (int, float)) and float(v) > 0: - vo2 = float(v) - break - if not vo2 and isinstance(ts_data.get("mostRecentVO2Max"), dict): - v = ts_data["mostRecentVO2Max"].get("generic") or ts_data["mostRecentVO2Max"].get("value") - if v and float(v) > 0: - vo2 = float(v) - # Try stats_and_body - if sb_data and not vo2: - for key in ("vo2MaxPreciseValue", "vo2Max"): - v = sb_data.get(key) - if v and isinstance(v, (int, float)) and float(v) > 0: - vo2 = float(v) - break + vo2_date = today_str + generic = (ts_data or {}).get("mostRecentVO2Max", {}).get("generic") or {} + v = generic.get("vo2MaxPreciseValue") or generic.get("vo2MaxValue") + if v and float(v) > 0: + vo2 = float(v) + vo2_date = generic.get("calendarDate") or today_str fa_age = None if fa_data: fa_age = fa_data.get("fitnessAge") or fa_data.get("achievableFitnessAge") - logger.info("parsed vo2=%s fitness_age=%s", vo2, fa_age) - if vo2: try: fa_row = {"vo2max": vo2} @@ -370,8 +353,9 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db, VALUES (:user_id, :day, {", ".join(f":{c}" for c in fa_cols)}) ON CONFLICT (user_id, date) DO UPDATE SET {", ".join(f"{c} = EXCLUDED.{c}" for c in fa_cols)} - """), {"user_id": user_id, "day": today_str, **fa_row}) + """), {"user_id": user_id, "day": vo2_date, **fa_row}) db.commit() + logger.info("Stored VO2 max %.1f for %s", vo2, vo2_date) except Exception as exc: logger.warning("Failed to upsert VO2 max: %s", exc) db.rollback()