fix: reconstruct missing placeholders + fix SQL column names
Added missing placeholders: - caliper_summary, circ_summary (body measurements) - goal_weight, goal_bf_pct (goals from profile) - nutrition_days (count of nutrition entries) - protein_ziel_low/high (calculated from weight) Fixed SQL errors: - protein → protein_g - fat → fat_g - carb → carbs_g Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f4d1fd4de1
commit
0f2b85c6de
|
|
@ -79,9 +79,19 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str:
|
|||
with get_db() as conn:
|
||||
cur = get_cursor(conn)
|
||||
cutoff = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
|
||||
|
||||
# Map field names to actual column names
|
||||
field_map = {
|
||||
'protein': 'protein_g',
|
||||
'fat': 'fat_g',
|
||||
'carb': 'carbs_g',
|
||||
'kcal': 'kcal'
|
||||
}
|
||||
db_field = field_map.get(field, field)
|
||||
|
||||
cur.execute(
|
||||
f"""SELECT AVG({field}) as avg FROM nutrition_log
|
||||
WHERE profile_id=%s AND date >= %s AND {field} IS NOT NULL""",
|
||||
f"""SELECT AVG({db_field}) as avg FROM nutrition_log
|
||||
WHERE profile_id=%s AND date >= %s AND {db_field} IS NOT NULL""",
|
||||
(profile_id, cutoff)
|
||||
)
|
||||
row = cur.fetchone()
|
||||
|
|
@ -93,6 +103,105 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str:
|
|||
return "nicht verfügbar"
|
||||
|
||||
|
||||
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 bf_jpl, bf_katch, date FROM caliper_log
|
||||
WHERE profile_id=%s AND bf_jpl IS NOT NULL
|
||||
ORDER BY date DESC LIMIT 1""",
|
||||
(profile_id,)
|
||||
)
|
||||
row = r2d(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
|
||||
if not row:
|
||||
return "keine Caliper-Messungen"
|
||||
|
||||
return f"JPL: {row['bf_jpl']:.1f}% (Katch: {row['bf_katch']:.1f}% am {row['date']})"
|
||||
|
||||
|
||||
def get_circ_summary(profile_id: str) -> str:
|
||||
"""Get latest circumference measurements summary."""
|
||||
with get_db() as conn:
|
||||
cur = get_cursor(conn)
|
||||
cur.execute(
|
||||
"""SELECT brust, taille, huefte, date FROM circumference_log
|
||||
WHERE profile_id=%s
|
||||
ORDER BY date DESC LIMIT 1""",
|
||||
(profile_id,)
|
||||
)
|
||||
row = r2d(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
|
||||
if not row:
|
||||
return "keine Umfangsmessungen"
|
||||
|
||||
parts = []
|
||||
if row.get('brust'): parts.append(f"Brust {row['brust']}cm")
|
||||
if row.get('taille'): parts.append(f"Taille {row['taille']}cm")
|
||||
if row.get('huefte'): parts.append(f"Hüfte {row['huefte']}cm")
|
||||
|
||||
return f"{', '.join(parts)} ({row['date']})" if parts else "keine Daten"
|
||||
|
||||
|
||||
def get_goal_weight(profile_id: str) -> str:
|
||||
"""Get goal weight from profile."""
|
||||
profile = get_profile_data(profile_id)
|
||||
goal = profile.get('goal_weight')
|
||||
return f"{goal:.1f}" if goal else "nicht gesetzt"
|
||||
|
||||
|
||||
def get_goal_bf_pct(profile_id: str) -> str:
|
||||
"""Get goal body fat percentage from profile."""
|
||||
profile = get_profile_data(profile_id)
|
||||
goal = profile.get('goal_bf_pct')
|
||||
return f"{goal:.1f}" if goal else "nicht gesetzt"
|
||||
|
||||
|
||||
def get_nutrition_days(profile_id: str, days: int = 30) -> str:
|
||||
"""Get number of days with nutrition data."""
|
||||
with get_db() as conn:
|
||||
cur = get_cursor(conn)
|
||||
cutoff = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
|
||||
cur.execute(
|
||||
"""SELECT COUNT(DISTINCT date) as days FROM nutrition_log
|
||||
WHERE profile_id=%s AND date >= %s""",
|
||||
(profile_id, cutoff)
|
||||
)
|
||||
row = cur.fetchone()
|
||||
return str(row['days']) if row else "0"
|
||||
|
||||
|
||||
def get_protein_ziel_low(profile_id: str) -> str:
|
||||
"""Calculate lower protein target based on current weight (1.6g/kg)."""
|
||||
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()
|
||||
if row:
|
||||
return f"{int(row['weight'] * 1.6)}"
|
||||
return "nicht verfügbar"
|
||||
|
||||
|
||||
def get_protein_ziel_high(profile_id: str) -> str:
|
||||
"""Calculate upper protein target based on current weight (2.2g/kg)."""
|
||||
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()
|
||||
if row:
|
||||
return f"{int(row['weight'] * 2.2)}"
|
||||
return "nicht verfügbar"
|
||||
|
||||
|
||||
def get_activity_summary(profile_id: str, days: int = 14) -> str:
|
||||
"""Get activity summary for recent period."""
|
||||
with get_db() as conn:
|
||||
|
|
@ -194,12 +303,19 @@ PLACEHOLDER_MAP: Dict[str, Callable[[str], str]] = {
|
|||
'{{weight_trend}}': get_weight_trend,
|
||||
'{{kf_aktuell}}': get_latest_bf,
|
||||
'{{bmi}}': lambda pid: calculate_bmi(pid),
|
||||
'{{caliper_summary}}': get_caliper_summary,
|
||||
'{{circ_summary}}': get_circ_summary,
|
||||
'{{goal_weight}}': get_goal_weight,
|
||||
'{{goal_bf_pct}}': get_goal_bf_pct,
|
||||
|
||||
# Ernährung
|
||||
'{{kcal_avg}}': lambda pid: get_nutrition_avg(pid, 'kcal', 30),
|
||||
'{{protein_avg}}': lambda pid: get_nutrition_avg(pid, 'protein', 30),
|
||||
'{{carb_avg}}': lambda pid: get_nutrition_avg(pid, 'carb', 30),
|
||||
'{{fat_avg}}': lambda pid: get_nutrition_avg(pid, 'fat', 30),
|
||||
'{{nutrition_days}}': lambda pid: get_nutrition_days(pid, 30),
|
||||
'{{protein_ziel_low}}': get_protein_ziel_low,
|
||||
'{{protein_ziel_high}}': get_protein_ziel_high,
|
||||
|
||||
# Training
|
||||
'{{activity_summary}}': get_activity_summary,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user