From 217990d4170f34fcaded52a7ac5a986720b436db Mon Sep 17 00:00:00 2001 From: Lars Date: Fri, 27 Mar 2026 17:00:53 +0100 Subject: [PATCH] fix: Prevent manual progress entries for automatic goals **Backend Safeguards:** - get_goals_grouped: Added source_table, source_column, direction to SELECT - create_goal_progress: Check source_table before allowing manual entry - Returns HTTP 400 if user tries to log progress for automatic goals (weight, activity, etc.) **Prevents:** - Data confusion: Manual entries in goal_progress_log for weight/activity/etc. - Dual tracking: Same data in multiple tables - User error: Wrong data entry location **Result:** - Frontend filter (!goal.source_table) now works correctly - CustomGoalsPage shows ONLY custom goals (flexibility, strength, etc.) - Clear error message if manual entry attempted via API Co-Authored-By: Claude Opus 4.6 --- backend/routers/goals.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/routers/goals.py b/backend/routers/goals.py index e269595..8ac4061 100644 --- a/backend/routers/goals.py +++ b/backend/routers/goals.py @@ -561,15 +561,25 @@ def create_goal_progress(goal_id: str, data: GoalProgressCreate, session: dict = with get_db() as conn: cur = get_cursor(conn) - # Verify ownership - cur.execute( - "SELECT id, unit FROM goals WHERE id = %s AND profile_id = %s", - (goal_id, pid) - ) + # Verify ownership and check if manual entry is allowed + cur.execute(""" + SELECT g.id, g.unit, gt.source_table + FROM goals g + LEFT JOIN goal_type_definitions gt ON g.goal_type = gt.type_key + WHERE g.id = %s AND g.profile_id = %s + """, (goal_id, pid)) goal = cur.fetchone() if not goal: raise HTTPException(status_code=404, detail="Ziel nicht gefunden") + # Prevent manual entries for goals with automatic data sources + if goal['source_table']: + raise HTTPException( + status_code=400, + detail=f"Manuelle Einträge nicht erlaubt für automatisch erfasste Ziele. " + f"Bitte nutze die entsprechende Erfassungsseite (z.B. Gewicht, Aktivität)." + ) + # Insert progress entry try: cur.execute(""" @@ -660,7 +670,8 @@ def get_goals_grouped(session: dict = Depends(require_auth)): g.unit, g.target_date, g.status, g.is_primary, g.category, g.priority, g.name, g.description, g.progress_pct, g.on_track, g.projection_date, g.created_at, g.updated_at, - gt.label_de, gt.icon, gt.category as type_category + gt.label_de, gt.icon, gt.category as type_category, + gt.source_table, gt.source_column, gt.direction FROM goals g LEFT JOIN goal_type_definitions gt ON g.goal_type = gt.type_key WHERE g.profile_id = %s