Fix VO2 max extraction: values nested under entry['generic'] not top-level
Build and push images / validate (push) Successful in 2s
Build and push images / build-backend (push) Successful in 5s
Build and push images / build-worker (push) Successful in 5s
Build and push images / build-frontend (push) Successful in 5s

The maxmet/daily range query returns entries shaped as:
  {"generic": {"calendarDate": "...", "vo2MaxPreciseValue": 42.7, ...}, ...}

The extractor was looking at the top level of each entry, finding nothing, and
falling through to the single-point training_status fallback every time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 23:18:04 +01:00
parent 093aa67e58
commit 70c7e5c0a8
2 changed files with 22 additions and 23 deletions
+11 -13
View File
@@ -342,17 +342,16 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
len(mm_raw) if isinstance(mm_raw, (list, dict)) else "n/a")
if isinstance(mm_raw, list):
mm_entries = mm_raw
if mm_entries and isinstance(mm_entries[0], dict):
logger.info("maxmet first entry keys: %s", list(mm_entries[0].keys()))
logger.info("maxmet first entry: %s", mm_entries[0])
except Exception as exc:
logger.info("maxmet history fetch failed: %s", exc)
# Check whether the range query yielded any usable vo2max values
# Each entry has the vo2max data nested under entry["generic"]
def _extract_generic(entry):
return (entry.get("generic") or {}) if isinstance(entry, dict) else {}
valid_from_range = any(
(entry.get("vo2MaxPreciseValue") or entry.get("vo2MaxValue") or 0)
for entry in mm_entries
if isinstance(entry, dict)
(_extract_generic(e).get("vo2MaxPreciseValue") or _extract_generic(e).get("vo2MaxValue") or 0)
for e in mm_entries
)
# Always fall back to training_status when the range query had no valid data
@@ -362,17 +361,16 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
v = generic.get("vo2MaxPreciseValue") or generic.get("vo2MaxValue")
logger.info("training_status vo2max=%s at %s", v, generic.get("calendarDate"))
if v and float(v) > 0:
mm_entries = [{"calendarDate": generic.get("calendarDate") or today_str,
"vo2MaxPreciseValue": float(v)}]
mm_entries = [{"generic": {"calendarDate": generic.get("calendarDate") or today_str,
"vo2MaxPreciseValue": float(v)}}]
stored = 0
for entry in mm_entries:
if not isinstance(entry, dict):
continue
v = entry.get("vo2MaxPreciseValue") or entry.get("vo2MaxValue")
generic = _extract_generic(entry)
v = generic.get("vo2MaxPreciseValue") or generic.get("vo2MaxValue")
if not v or float(v) <= 0:
continue
entry_date = entry.get("calendarDate") or today_str
entry_date = generic.get("calendarDate") or today_str
try:
fa_row = {"vo2max": float(v)}
if fa_age and entry_date == today_str:
@@ -345,11 +345,13 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
except Exception as exc:
logger.info("maxmet history fetch failed: %s", exc)
# Check whether the range query yielded any usable vo2max values
# Each entry has the vo2max data nested under entry["generic"]
def _extract_generic(entry):
return (entry.get("generic") or {}) if isinstance(entry, dict) else {}
valid_from_range = any(
(entry.get("vo2MaxPreciseValue") or entry.get("vo2MaxValue") or 0)
for entry in mm_entries
if isinstance(entry, dict)
(_extract_generic(e).get("vo2MaxPreciseValue") or _extract_generic(e).get("vo2MaxValue") or 0)
for e in mm_entries
)
# Always fall back to training_status when the range query had no valid data
@@ -359,17 +361,16 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
v = generic.get("vo2MaxPreciseValue") or generic.get("vo2MaxValue")
logger.info("training_status vo2max=%s at %s", v, generic.get("calendarDate"))
if v and float(v) > 0:
mm_entries = [{"calendarDate": generic.get("calendarDate") or today_str,
"vo2MaxPreciseValue": float(v)}]
mm_entries = [{"generic": {"calendarDate": generic.get("calendarDate") or today_str,
"vo2MaxPreciseValue": float(v)}}]
stored = 0
for entry in mm_entries:
if not isinstance(entry, dict):
continue
v = entry.get("vo2MaxPreciseValue") or entry.get("vo2MaxValue")
generic = _extract_generic(entry)
v = generic.get("vo2MaxPreciseValue") or generic.get("vo2MaxValue")
if not v or float(v) <= 0:
continue
entry_date = entry.get("calendarDate") or today_str
entry_date = generic.get("calendarDate") or today_str
try:
fa_row = {"vo2max": float(v)}
if fa_age and entry_date == today_str: