diff --git a/backend/data_layer/__init__.py b/backend/data_layer/__init__.py index 70db142..aade0d1 100644 --- a/backend/data_layer/__init__.py +++ b/backend/data_layer/__init__.py @@ -45,6 +45,7 @@ __all__ = [ 'serialize_dates', # Body Metrics + 'get_latest_weight_data', 'get_weight_trend_data', 'get_body_composition_data', 'get_circumference_summary_data', diff --git a/backend/data_layer/body_metrics.py b/backend/data_layer/body_metrics.py index 8b267a5..ce6237c 100644 --- a/backend/data_layer/body_metrics.py +++ b/backend/data_layer/body_metrics.py @@ -4,6 +4,7 @@ Body Metrics Data Layer Provides structured data for body composition and measurements. Functions: + - get_latest_weight_data(): Most recent weight entry - get_weight_trend_data(): Weight trend with slope and direction - get_body_composition_data(): Body fat percentage and lean mass - get_circumference_summary_data(): Latest circumference measurements @@ -21,6 +22,51 @@ from db import get_db, get_cursor, r2d from data_layer.utils import calculate_confidence, safe_float +def get_latest_weight_data( + profile_id: str +) -> Dict: + """ + Get most recent weight entry. + + Args: + profile_id: User profile ID + + Returns: + { + "weight": float, # kg + "date": date, + "confidence": str + } + + Migration from Phase 0b: + OLD: get_latest_weight() returned formatted string "85.0 kg" + NEW: Returns structured data {"weight": 85.0, "date": ...} + """ + with get_db() as conn: + cur = get_cursor(conn) + cur.execute( + """SELECT weight, date FROM weight_log + WHERE profile_id=%s + ORDER BY date DESC + LIMIT 1""", + (profile_id,) + ) + row = cur.fetchone() + + if not row: + return { + "weight": 0.0, + "date": None, + "confidence": "insufficient" + } + + return { + "weight": safe_float(row['weight']), + "date": row['date'], + "confidence": "high" + } + + def get_weight_trend_data( profile_id: str, days: int = 28 diff --git a/backend/placeholder_resolver.py b/backend/placeholder_resolver.py index 1ae94db..4e72961 100644 --- a/backend/placeholder_resolver.py +++ b/backend/placeholder_resolver.py @@ -14,6 +14,7 @@ from db import get_db, get_cursor, r2d # Phase 0c: Import data layer from data_layer.body_metrics import ( + get_latest_weight_data, get_weight_trend_data, get_body_composition_data, get_circumference_summary_data @@ -51,15 +52,18 @@ def get_profile_data(profile_id: str) -> Dict: def get_latest_weight(profile_id: str) -> Optional[str]: - """Get latest weight entry.""" - with get_db() as conn: - cur = get_cursor(conn) - cur.execute( - "SELECT weight FROM weight_log WHERE profile_id=%s ORDER BY date DESC LIMIT 1", - (profile_id,) - ) - row = cur.fetchone() - return f"{row['weight']:.1f} kg" if row else "nicht verfügbar" + """ + Get latest weight entry. + + Phase 0c: Refactored to use data_layer.body_metrics.get_latest_weight_data() + This function now only FORMATS the data for AI consumption. + """ + data = get_latest_weight_data(profile_id) + + if data['confidence'] == 'insufficient': + return "nicht verfügbar" + + return f"{data['weight']:.1f} kg" def get_weight_trend(profile_id: str, days: int = 28) -> str: @@ -129,22 +133,19 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str: def get_caliper_summary(profile_id: str) -> str: - """Get latest caliper measurements summary.""" - with get_db() as conn: - cur = get_cursor(conn) - cur.execute( - """SELECT body_fat_pct, sf_method, date FROM caliper_log - WHERE profile_id=%s AND body_fat_pct IS NOT NULL - ORDER BY date DESC LIMIT 1""", - (profile_id,) - ) - row = r2d(cur.fetchone()) if cur.rowcount > 0 else None + """ + Get latest caliper measurements summary. - if not row: - return "keine Caliper-Messungen" + Phase 0c: Refactored to use data_layer.body_metrics.get_body_composition_data() + This function now only FORMATS the data for AI consumption. + """ + data = get_body_composition_data(profile_id) - method = row.get('sf_method', 'unbekannt') - return f"{row['body_fat_pct']:.1f}% ({method} am {row['date']})" + if data['confidence'] == 'insufficient': + return "keine Caliper-Messungen" + + method = data.get('method', 'unbekannt') + return f"{data['body_fat_pct']:.1f}% ({method} am {data['date']})" def get_circ_summary(profile_id: str) -> str: