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:
|
with get_db() as conn:
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
cutoff = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
|
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(
|
cur.execute(
|
||||||
f"""SELECT AVG({field}) as avg FROM nutrition_log
|
f"""SELECT AVG({db_field}) as avg FROM nutrition_log
|
||||||
WHERE profile_id=%s AND date >= %s AND {field} IS NOT NULL""",
|
WHERE profile_id=%s AND date >= %s AND {db_field} IS NOT NULL""",
|
||||||
(profile_id, cutoff)
|
(profile_id, cutoff)
|
||||||
)
|
)
|
||||||
row = cur.fetchone()
|
row = cur.fetchone()
|
||||||
|
|
@ -93,6 +103,105 @@ def get_nutrition_avg(profile_id: str, field: str, days: int = 30) -> str:
|
||||||
return "nicht verfügbar"
|
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:
|
def get_activity_summary(profile_id: str, days: int = 14) -> str:
|
||||||
"""Get activity summary for recent period."""
|
"""Get activity summary for recent period."""
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
|
|
@ -194,12 +303,19 @@ PLACEHOLDER_MAP: Dict[str, Callable[[str], str]] = {
|
||||||
'{{weight_trend}}': get_weight_trend,
|
'{{weight_trend}}': get_weight_trend,
|
||||||
'{{kf_aktuell}}': get_latest_bf,
|
'{{kf_aktuell}}': get_latest_bf,
|
||||||
'{{bmi}}': lambda pid: calculate_bmi(pid),
|
'{{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
|
# Ernährung
|
||||||
'{{kcal_avg}}': lambda pid: get_nutrition_avg(pid, 'kcal', 30),
|
'{{kcal_avg}}': lambda pid: get_nutrition_avg(pid, 'kcal', 30),
|
||||||
'{{protein_avg}}': lambda pid: get_nutrition_avg(pid, 'protein', 30),
|
'{{protein_avg}}': lambda pid: get_nutrition_avg(pid, 'protein', 30),
|
||||||
'{{carb_avg}}': lambda pid: get_nutrition_avg(pid, 'carb', 30),
|
'{{carb_avg}}': lambda pid: get_nutrition_avg(pid, 'carb', 30),
|
||||||
'{{fat_avg}}': lambda pid: get_nutrition_avg(pid, 'fat', 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
|
# Training
|
||||||
'{{activity_summary}}': get_activity_summary,
|
'{{activity_summary}}': get_activity_summary,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user