Commit Graph

389 Commits

Author SHA1 Message Date
eb8b503faa debug: log all continue statements in goal deviation calculation
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
- Log when using created_at as fallback for start_date
- Log when skipping due to missing created_at
- Log when skipping due to invalid date range (total_days <= 0)

This will reveal exactly why Körperfett and Zielgewicht are not added.
2026-03-28 15:09:41 +01:00
294b3b2ece debug: extensive logging for behind_schedule/on_track calculation
All checks were successful
Deploy Development / deploy (push) Successful in 54s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
- Log each goal processing (name, values, dates)
- Log skip reasons (missing values, no target_date)
- Log exceptions during calculation
- Log successful additions with calculated values

This will reveal why Weight goal (+7% ahead) is not showing up.
2026-03-28 15:07:31 +01:00
8e67175ed2 fix: behind_schedule now uses time-based deviation, not just lowest progress
All checks were successful
Deploy Development / deploy (push) Successful in 49s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
OLD: Showed 3 goals with lowest progress %
NEW: Calculates expected progress based on elapsed time vs. total time
     Shows goals with largest negative deviation (behind schedule)

Example Weight Goal:
- Total time: 98 days (22.02 - 31.05)
- Elapsed: 34 days (35%)
- Actual progress: 41%
- Deviation: +7% (AHEAD, not behind)

Also updated on_track to show goals with positive deviation (ahead of schedule).

Note: Linear progress is a simplification. Real-world progress curves vary
by goal type (weight loss, muscle gain, VO2max, etc). Future: AI-based
projection models for more realistic expectations.
2026-03-28 14:58:50 +01:00
d7aa0eb3af feat: show target_date in goal list next to target value
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
- Start value already showed start_date in parentheses
- Now target value also shows target_date in parentheses
- Consistent UX: both dates visible at their respective values
2026-03-28 14:50:34 +01:00
cb72f342f9 fix: add missing start_date and reached_date to grouped goals query
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Root cause: listGoalsGrouped() SELECT was missing g.start_date and g.reached_date
Result: Frontend used grouped goals for editing, so start_date was undefined

This is why target_date worked (it was in SELECT) but start_date didn't.
2026-03-28 14:48:41 +01:00
623f34c184 debug: extensive frontend logging for goal dates
All checks were successful
Deploy Development / deploy (push) Successful in 54s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 14:46:06 +01:00
b7e7817392 debug: show ALL goals with dates, not just first
Some checks failed
Build Test / lint-backend (push) Waiting to run
Build Test / build-frontend (push) Waiting to run
Deploy Development / deploy (push) Has been cancelled
2026-03-28 14:45:36 +01:00
068a8e7a88 debug: show goals after serialization
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 14:41:33 +01:00
97defaf704 fix: serialize date objects to ISO format for JSON
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 14s
- Added serialize_dates() helper to convert date objects to strings
- Applied to list_goals and get_goals_grouped endpoints
- Fixes issue where start_date was saved but not visible in frontend
- Python datetime.date objects need explicit .isoformat() conversion

Root cause: FastAPI doesn't auto-serialize all date types consistently
2026-03-28 14:36:45 +01:00
370f0d46c7 debug: extensive logging for start_date persistence
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
- Log UPDATE SQL and parameters
- Verify saved values after UPDATE
- Show date types in list_goals response
- Track down why start_date not visible in UI
2026-03-28 14:33:16 +01:00
c90e30806b fix: save start_date to database in update_goal
All checks were successful
Deploy Development / deploy (push) Successful in 53s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 15s
- Rewrote update logic to determine final_start_date/start_value first
- Then append to updates/params arrays (ensures alignment)
- Fixes bug where only start_value was saved but not start_date

User feedback: start_value correctly calculated but start_date not persisted
2026-03-28 14:28:52 +01:00
ab29a85903 debug: Add console logging to trace start_date loading
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 13:55:29 +01:00
3604ebc781 fix: Load actual start_date in edit form + improve timeline display
All checks were successful
Deploy Development / deploy (push) Successful in 48s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 15s
**Problem 1:** Edit form showed today's date instead of stored start_date
- Cause: Fallback logic `goal.start_date || today` always defaulted to today
- Fix: Load actual date or empty string (no fallback)
- Input field: Remove fallback from value binding

**Problem 2:** Timeline only showed target_date, not start_date
- Added dedicated timeline display below values
- Shows: "📅 15.01.26 → 31.05.26"
- Only appears if at least one date exists
- Start date with calendar icon, target date bold

**Result:**
- Editing goals now preserves the start_date ✓
- Timeline clearly shows start → target dates ✓
- No more accidental overwrites with today's date ✓

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:50:47 +01:00
e479627f0f feat: Auto-adjust start_date to first available measurement
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
**User Feedback:** "Macht es nicht Sinn, den nächsten verfügbaren Wert
am oder nach dem Startdatum automatisch zu ermitteln und auch das
Startdatum dann automatisch auf den Wert zu setzen?"

**New Logic:**
1. User sets start_date: 2026-01-01
2. System finds FIRST measurement >= 2026-01-01 (e.g., 2026-01-15: 88 kg)
3. System auto-adjusts:
   - start_date → 2026-01-15
   - start_value → 88 kg
4. User sees: "Start: 88 kg (15.01.26)" ✓

**Benefits:**
- User doesn't need to know exact date of first measurement
- More user-friendly UX
- Automatically finds closest available data

**Implementation:**
- Changed query from "BETWEEN date ±7 days" to "WHERE date >= target_date"
- Returns dict with {'value': float, 'date': date}
- Both create_goal() and update_goal() now adjust start_date automatically

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:41:35 +01:00
169dbba092 debug: Add comprehensive logging to trace historical value lookup
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 13:27:16 +01:00
42cc583b9b debug: Add logging to update_goal to trace start_date issue
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 13:24:29 +01:00
7ffa8f039b fix: PostgreSQL date subtraction in historical value query
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
**Error:**
function pg_catalog.extract(unknown, integer) does not exist
HINT: No function matches the given name and argument types.

**Problem:**
In PostgreSQL, date - date returns INTEGER (days), not INTERVAL.
EXTRACT(EPOCH FROM integer) fails because EPOCH expects timestamp/interval.

**Solution:**
Changed from:
  ORDER BY ABS(EXTRACT(EPOCH FROM (date - '2026-01-01')))

To:
  ORDER BY ABS(date - '2026-01-01'::date)

This directly uses the day difference (integer) for sorting,
which is exactly what we need to find the closest date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:22:05 +01:00
1c7b5e0653 fix: Include start_date in goal edit form and API call
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
**Bug:** start_date was not being loaded into edit form or sent in update request

**Fixed:**
1. handleEditGoal() - Added start_date to formData when editing
2. handleSaveGoal() - Added start_date to API payload for both create and update

Now when editing a goal:
- start_date field is populated with existing value
- Changing start_date triggers backend to recalculate start_value
- Update request includes start_date

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:19:10 +01:00
327319115d feat: Frontend - Startdatum field in goal form
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Added start_date field to goal creation/editing form:

1. New "Startdatum" input field before "Zieldatum"
   - Defaults to today
   - Hint: "Startwert wird automatisch aus historischen Daten ermittelt"

2. Display start_date in goals list
   - Shows next to start_value: "85 kg (01.01.26)"
   - Compact format for better readability

3. Updated formData state
   - Added start_date with today as default
   - API calls automatically include it

User can now:
- Set historical start date (e.g., 3 months ago)
- Backend auto-populates start_value from that date
- See exact start date and value for each goal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:15:56 +01:00
efde158dd4 feat: Auto-populate goal start_value from historical data
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
**Problem:** Goals created today had start_value = current_value,
showing 0% progress even after months of tracking.

**Solution:**
1. Added start_date and start_value to GoalCreate/GoalUpdate models
2. New function _get_historical_value_for_goal_type():
   - Queries source table for value on specific date
   - ±7 day window for closest match
   - Works with all goal types via goal_type_definitions
3. create_goal() logic:
   - If start_date < today → auto-populate from historical data
   - If start_date = today → use current value
   - User can override start_value manually
4. update_goal() logic:
   - Changing start_date recalculates start_value
   - Can manually override start_value

**Example:**
- Goal created today with start_date = 3 months ago
- System finds weight on that date (88 kg)
- Current weight: 85.2 kg, Target: 82 kg
- Progress: (85.2 - 88) / (82 - 88) = 47% ✓

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:14:33 +01:00
a6701bf7b2 fix: Include start_value in get_active_goals query
All checks were successful
Deploy Development / deploy (push) Successful in 49s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Goal progress placeholders were filtering out all goals because
start_value was missing from the SELECT statement.

Added start_value to both:
- get_active_goals() - for placeholder formatters
- get_goal_by_id() - for consistency

This will fix:
- active_goals_md progress column (was all "-")
- top_3_goals_behind_schedule (was "keine Ziele")
- top_3_goals_on_track (was "keine Ziele")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 13:02:43 +01:00
befc310958 fix: focus_areas column name + goal progress calculation
All checks were successful
Deploy Development / deploy (push) Successful in 49s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Fixed 2 critical placeholder issues:

1. focus_areas_weighted_json was empty:
   - Query used 'area_key' but column is 'key' in focus_area_definitions
   - Changed to SELECT key, not area_key

2. Goal progress placeholders showed "nicht verfügbar":
   - progress_pct in goals table is NULL (not auto-calculated)
   - Added manual calculation in all 3 formatter functions:
     * _format_goals_as_markdown() - shows % in table
     * _format_goals_behind() - finds lowest progress
     * _format_goals_on_track() - finds >= 50% progress

All placeholders should now return proper values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:43:54 +01:00
112226938d fix: Convert goal values to float before progress calculation
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
TypeError: unsupported operand type(s) for -: 'decimal.Decimal' and 'float'

PostgreSQL NUMERIC columns return Decimal objects. Must convert
current_value, target_value, start_value to float before passing
to calculate_goal_progress_pct().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:39:26 +01:00
8da577fe58 fix: Phase 0b - body_progress_score + placeholder formatting
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Fixed remaining placeholder calculation issues:

1. body_progress_score returning 0:
   - When start_value is NULL, query oldest weight from last 90 days
   - Prevents progress = 0% when start equals current

2. focus_areas_weighted_json empty:
   - Changed from goal_utils.get_focus_weights_v2() to scores.get_user_focus_weights()
   - Now uses same function as focus_area_weights_json

3. Implemented 5 TODO markdown formatting functions:
   - _format_goals_as_markdown() - table with progress bars
   - _format_focus_areas_as_markdown() - weighted list
   - _format_top_focus_areas() - top N by weight
   - _format_goals_behind() - lowest progress goals
   - _format_goals_on_track() - goals >= 50% progress

All placeholders should now return proper values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:34:24 +01:00
b09a7b200a fix: Phase 0b - implement active_goals and focus_areas JSON placeholders
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Root cause: Two TODO stubs always returned '[]'

Implemented:
- active_goals_json: Calls get_active_goals() from goal_utils
- focus_areas_weighted_json: Builds weighted list with names/categories

Result:
- active_goals_json now shows actual goals
- body_progress_score should calculate correctly
- top_3_goals placeholders will work

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:19:37 +01:00
05d15264c8 fix: Phase 0b - complete Decimal/float conversion in nutrition_metrics
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Previous commit only converted weight values, but missed:
- avg_intake (calories from DB)
- avg_protein (protein_g from DB)
- protein_per_kg calculations in loops

All DB numeric values now converted to float BEFORE arithmetic.

Fixed locations:
- Line 44: avg_intake conversion
- Line 126: avg_protein conversion
- Line 175: protein_per_kg in loop
- Line 213: protein_values list comprehension

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:32:07 +01:00
78437b649f fix: Phase 0b - PostgreSQL Decimal type handling
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'
TypeError: unsupported operand type(s) for -: 'float' and 'decimal.Decimal'

PostgreSQL NUMERIC/DECIMAL columns return decimal.Decimal objects,
not float. These cannot be mixed in arithmetic operations.

Fixed 3 locations:
- Line 62: float(weight_row['weight']) * 32.5
- Line 153: float(weight_row['weight']) for protein_per_kg
- Line 202: float(weight_row['avg_weight']) for adequacy calc

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:23:40 +01:00
6f20915d73 fix: Phase 0b - body_progress_score uses correct column name
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Bug: Filtered goals by g.get('type_key') but goals table has 'goal_type' column.
Result: weight_goals was always empty → _score_weight_trend returned None.

Fix: Changed 'type_key' → 'goal_type' (matches goals table schema).

Verified: Migration 022 defines goal_type column, not type_key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:16:29 +01:00
202c36fad7 fix: Phase 0b - replace non-existent get_goals_by_type import
All checks were successful
Deploy Development / deploy (push) Successful in 52s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
ImportError: cannot import name 'get_goals_by_type' from 'goal_utils'

Changes:
- body_metrics.py: Use get_active_goals() + filter by type_key
- nutrition_metrics.py: Remove unused import (dead code)

Result: Score functions no longer crash on import error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 11:04:28 +01:00
cc76ae677b fix: Phase 0b - score functions use English focus area keys
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Root cause: All 3 score functions returned None because they queried
German focus area keys that don't exist in database (migration 031
uses English keys).

Changes:
- body_progress_score: körpergewicht/körperfett/muskelmasse
  → weight_loss/muscle_gain/body_recomposition
- nutrition_score: ernährung_basis/proteinzufuhr/kalorienbilanz
  → protein_intake/calorie_balance/macro_consistency/meal_timing/hydration
- activity_score: kraftaufbau/cardio/bewegungsumfang/trainingsqualität
  → strength/aerobic_endurance/flexibility/rhythm/coordination (grouped)

Result: Scores now calculate correctly with existing focus area weights.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 10:59:37 +01:00
63bd103b2c feat: Phase 0b - add avg_per_week_30d to frontend dropdown
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 10:50:51 +01:00
14c4ea13d9 feat: Phase 0b - add avg_per_week_30d aggregation method
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
- Calculates average count per week over 30 days
- Use case: Training frequency per week (smoothed)
- Formula: (count in 30 days) / 4.285 weeks
- Documentation: .claude/docs/technical/AGGREGATION_METHODS.md
2026-03-28 10:45:36 +01:00
9fa6c5dea7 feat: Phase 0b - add nutrition focus areas to score mapping
All checks were successful
Deploy Development / deploy (push) Successful in 48s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 10:20:46 +01:00
949301a91d feat: Phase 0b - add nutrition focus area category (migration 033) 2026-03-28 10:20:08 +01:00
43e6c3e7f4 fix: Phase 0b - map German to English category names
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
2026-03-28 10:13:10 +01:00
e3e635d9f5 fix: Phase 0b - remove orphaned German mapping entries
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 10:10:18 +01:00
289b132b8f fix: Phase 0b - map_focus_to_score_components English keys
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
2026-03-28 09:53:59 +01:00
919eae6053 fix: Phase 0b - sleep dict access in health_stability_score regularity
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
2026-03-28 09:42:54 +01:00
91bafc6af1 fix: Phase 0b - activity duration column in health_stability_score
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 13s
2026-03-28 09:40:07 +01:00
10ea560fcf fix: Phase 0b - fix last sleep column names in health_stability_score
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Fixed remaining sleep_log column name errors in calculate_health_stability_score:
- SELECT: total_sleep_min, deep_min, rem_min → duration_minutes, deep_minutes, rem_minutes
- _score_sleep_quality: Updated dict access to use new column names

This was blocking goal_progress_score from calculating.

Changes:
- scores.py: Fixed sleep_log SELECT query and _score_sleep_quality dict access

This should be the LAST column name bug! All Phase 0b calculations should now work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 09:35:36 +01:00
b230a03fdd fix: Phase 0b - fix blood_pressure and top_goal_name bugs
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 14s
Final bug fixes:
1. blood_pressure_log query - changed 'date' column to 'measured_at' (correct column for TIMESTAMP)
2. top_goal_name KeyError - added 'name' to SELECT in get_active_goals()
3. top_goal_name fallback - use goal_type if name is NULL

Changes:
- scores.py: Fixed blood_pressure_log query to use measured_at instead of date
- goal_utils.py: Added 'name' column to get_active_goals() SELECT
- placeholder_resolver.py: Added fallback to goal_type if name is None

These were the last 2 errors showing in logs. All major calculation bugs should now be fixed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 09:32:04 +01:00
02394ea19c fix: Phase 0b - fix remaining calculation bugs from log analysis
All checks were successful
Deploy Development / deploy (push) Successful in 43s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Bugs fixed based on actual error logs:
1. TypeError: progress_pct None handling - changed .get('progress_pct', 0) to (goal.get('progress_pct') or 0)
2. UUID Error: focus_area_id query - changed WHERE focus_area_id = %s to WHERE key = %s
3. NameError: calculate_recovery_score_v2 - added missing import in calculate_category_progress
4. UndefinedColumn: c_thigh_r - removed left/right separation, only c_thigh exists
5. UndefinedColumn: resting_heart_rate - fixed remaining AVG(resting_heart_rate) to AVG(resting_hr)
6. KeyError: total_sleep_min - changed dict access to duration_minutes

Changes:
- scores.py: Fixed progress_pct None handling, focus_area key query, added recovery import
- body_metrics.py: Fixed thigh_28d_delta to use single c_thigh column
- recovery_metrics.py: Fixed resting_hr SELECT queries, fixed sleep_debt dict access

All errors from logs should now be resolved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:50:55 +01:00
dd3a4111fc fix: Phase 0b - fix remaining calculation errors
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Fixes applied:
1. WHERE clause column names (total_sleep_min → duration_minutes, resting_heart_rate → resting_hr)
2. COUNT() column names (avg_heart_rate → hr_avg, quality_label → rpe)
3. Type errors (Decimal * float) - convert to float before multiplication
4. rest_days table (type column removed in migration 010, now uses rest_config JSONB)
5. c_thigh_l → c_thigh (no separate left/right columns)
6. focus_area_definitions queries (focus_area_id → key, label_de → name_de)

Missing functions implemented:
- goal_utils.get_active_goals() - queries goals table for active goals
- goal_utils.get_goal_by_id() - gets single goal
- calculations.scores.calculate_category_progress() - maps categories to score functions

Changes:
- activity_metrics.py: Fixed Decimal/float type errors, rest_config JSONB, data quality query
- recovery_metrics.py: Fixed all WHERE clause column names
- body_metrics.py: Fixed c_thigh column reference
- scores.py: Fixed focus_area queries, added calculate_category_progress()
- goal_utils.py: Added get_active_goals(), get_goal_by_id()

All calculation functions should now work with correct schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:39:31 +01:00
4817fd2b29 fix: Phase 0b - correct all SQL column names in calculation engine
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
Schema corrections applied:
- weight_log: weight_kg → weight
- nutrition_log: calories → kcal
- activity_log: duration → duration_min, avg_heart_rate → hr_avg, max_heart_rate → hr_max
- rest_days: rest_type → type (aliased for backward compat)
- vitals_baseline: resting_heart_rate → resting_hr
- sleep_log: total_sleep_min → duration_minutes, deep_min → deep_minutes, rem_min → rem_minutes, waketime → wake_time
- focus_area_definitions: fa.focus_area_id → fa.key (proper join column)

Affected files:
- body_metrics.py: weight column (all queries)
- nutrition_metrics.py: kcal column + weight
- activity_metrics.py: duration_min, hr_avg, hr_max, quality via RPE mapping
- recovery_metrics.py: sleep + vitals columns
- correlation_metrics.py: kcal, weight
- scores.py: focus_area key selection

All 100+ Phase 0b placeholders should now calculate correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:28:20 +01:00
53969f8768 fix: SyntaxError in placeholder_resolver.py line 1037
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 14s
- Fixed unterminated string literal in get_placeholder_catalog()
- Line 1037 had extra quote: ('quality_sessions_pct', 'Qualitätssessions (%)'),'
- Should be: ('quality_sessions_pct', 'Qualitätssessions (%)'),

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:18:31 +01:00
6f94154b9e fix: Add error logging to Phase 0b placeholder calculation wrappers
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
Problem: All _safe_* functions were silently catching exceptions and returning 'nicht verfügbar',
making it impossible to debug why calculations fail.

Solution: Add detailed error logging with traceback to all 4 wrapper functions:
- _safe_int(): Logs function name, exception type, message, full stack trace
- _safe_float(): Same logging
- _safe_str(): Same logging
- _safe_json(): Same logging

Now when placeholders return 'nicht verfügbar', the backend logs will show:
- Which placeholder function failed
- What exception occurred
- Full stack trace for debugging

Example log output:
[ERROR] _safe_int(goal_progress_score, uuid): ModuleNotFoundError: No module named 'calculations'
Traceback (most recent call last):
  ...

This will help identify if issue is:
- Missing calculations module import
- Missing data in database
- Wrong column names
- Calculation logic errors
2026-03-28 07:39:53 +01:00
7d4f6fe726 fix: Update placeholder catalog with Phase 0b placeholders
All checks were successful
Deploy Development / deploy (push) Successful in 1m2s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 17s
Added ~40 Phase 0b placeholders to get_placeholder_catalog():
- Scores (6 new): goal_progress_score, body/nutrition/activity/recovery/data_quality
- Focus Areas (8 new): top focus area, category progress/weights
- Body Metrics (7 new): weight trends, FM/LBM changes, waist, recomposition
- Nutrition (4 new): energy balance, protein g/kg, adequacy, consistency
- Activity (6 new): minutes/week, quality, ability balance, compliance
- Recovery (4 new): sleep duration/debt/regularity/quality
- Vitals (3 new): HRV/RHR vs baseline, VO2max trend

Fixes: Placeholders now visible in Admin UI placeholder list
2026-03-28 07:35:48 +01:00
4f365e9a69 docs: Phase 0b Quick Test prompt (Option B)
All checks were successful
Deploy Development / deploy (push) Successful in 52s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
Compact test prompt for validating calculation engine:
- Tests 25 key placeholders (scores, categories, metrics)
- Covers body, nutrition, activity, recovery calculations
- Documents expected behavior and known limitations
- Step-by-step testing instructions

Use this to validate Phase 0b before implementing JSON formatters.
2026-03-28 07:27:42 +01:00
bf0b32b536 feat: Phase 0b - Integrate 100+ Goal-Aware Placeholders
Extended placeholder_resolver.py with:
- 100+ new placeholders across 5 levels (meta-scores, categories, individual metrics, correlations, JSON)
- Safe wrapper functions (_safe_int, _safe_float, _safe_str, _safe_json)
- Integration with calculation engine (body, nutrition, activity, recovery, correlations, scores)
- Dynamic Focus Areas v2.0 support (category progress/weights)
- Top-weighted goals/focus areas (instead of deprecated primary goal)

Placeholder categories:
- Meta Scores: goal_progress_score, body/nutrition/activity/recovery_score (6)
- Top-Weighted: top_goal_*, top_focus_area_* (5)
- Category Scores: focus_cat_*_progress/weight for 7 categories (14)
- Body Metrics: weight trends, FM/LBM changes, circumferences, recomposition (12)
- Nutrition Metrics: energy balance, protein adequacy, macro consistency (7)
- Activity Metrics: training volume, ability balance, load monitoring (13)
- Recovery Metrics: HRV/RHR vs baseline, sleep quality/debt/regularity (7)
- Correlation Metrics: lagged correlations, plateau detection, driver panel (7)
- JSON/Markdown: active_goals, focus_areas, top drivers (8)

TODO: Implement goal_utils extensions for JSON formatters
TODO: Add unit tests for all placeholder functions
2026-03-28 07:22:37 +01:00
09e6a5fbfb feat: Phase 0b - Calculation Engine for 120+ Goal-Aware Placeholders
- body_metrics.py: K1-K5 calculations (weight trend, FM/LBM, circumferences, recomposition, body score)
- nutrition_metrics.py: E1-E5 calculations (energy balance, protein adequacy, macro consistency, nutrition score)
- activity_metrics.py: A1-A8 calculations (training volume, intensity, quality, ability balance, load monitoring)
- recovery_metrics.py: Improved Recovery Score v2 (HRV, RHR, sleep, regularity, load balance)
- correlation_metrics.py: C1-C7 calculations (lagged correlations, plateau detection, driver panel)
- scores.py: Meta-scores with Dynamic Focus Areas v2.0 integration

All calculations include:
- Data quality assessment
- Confidence levels
- Dynamic weighting by user's focus area priorities
- Support for custom goals via goal_utils integration

Next: Placeholder integration in placeholder_resolver.py
2026-03-28 07:20:40 +01:00