Commit Graph

47 Commits

Author SHA1 Message Date
48508c164e feat: Add Activity Session Metrics functionality
All checks were successful
Deploy Development / deploy (push) Successful in 59s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 16s
- Introduced Activity Session Metrics for enhanced tracking of session data.
- Updated backend to support new API endpoints for managing session metrics.
- Added new Pydantic models for activity metrics and replaced metrics functionality.
- Enhanced data layer to include session metrics in recent training session data.
- Updated documentation to reflect changes in session metrics handling.
2026-04-14 11:49:14 +02:00
61a5bb39ae feat: Update nutrition metrics and energy balance calculations
All checks were successful
Deploy Development / deploy (push) Successful in 59s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 16s
- Introduced a single TDEE calculation based on current weight, replacing the fixed 2500 kcal value.
- Updated `get_energy_balance_data` to use daily totals for intake calculations and improved energy balance logic.
- Enhanced `get_nutrition_average_data` to calculate averages over calendar days instead of raw log entries.
- Adjusted placeholder resolution to ensure consistent metadata usage across requests.
- Fixed issues in the charts router to reflect the new energy balance logic and TDEE calculations.

These changes improve the accuracy of nutritional assessments and streamline data handling in the application.
2026-04-11 19:04:27 +02:00
4a771f6a83 feat(csv-parser): Implement CSV import functionality with mapping and type conversion
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 15s
- Added permissions for editing and deleting CSV field mappings.
- Created type converter for CSV cells to handle various data types.
- Implemented database migrations for CSV field mappings and import logs.
- Seeded initial system templates for nutrition and activity data imports.
- Developed admin endpoints for managing system CSV templates.
- Introduced user endpoints for CSV import analysis and mapping retrieval.
- Added tests for core CSV parser functionalities, including delimiter detection and value conversion.
2026-04-09 21:37:19 +02:00
e5f6e6c10d feat: Integrate Dashboard-Lab layout and enhance settings navigation
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 15s
- Added new routes and API endpoints for the Dashboard-Lab layout in the app.
- Updated main.py to include the app_dashboard router for backend integration.
- Enhanced App.jsx to include a route for the DashboardLabPage.
- Modified SettingsPage to add a link to the new Dashboard-Lab layout, improving user access to dashboard features.
- Updated version.py to reflect the new app_dashboard module version.
2026-04-07 11:38:35 +02:00
ab616ba044 feat: Introduce admin reference value types management in API and UI
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 16s
- Added new routes and API endpoints for managing reference value types in the admin section.
- Updated the frontend to include navigation and components for reference value types management.
- Enhanced the backend to support the new reference value types in the data layer and versioning.
2026-04-06 19:51:23 +02:00
f0e6fd04fb feat: Add personal reference values management in settings and API
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 15s
- Introduced new routes and API endpoints for managing personal reference values.
- Updated the SettingsPage to include a section for reference values with navigation to manage them.
- Enhanced the backend to support reference values in the data layer and versioning.
- Added necessary imports and UI components for a seamless user experience.
2026-04-06 19:45:06 +02:00
1f8791f4dd feat: Phase 2 - Normalisierung + Workflow Executor
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
Backend:
- normalization_engine.py (200 Zeilen): Synonym-Mapping, 5 Statuswerte
  * normalize_decision_signal(): Kaskade (exact → case → synonym → invalid)
  * apply_synonym_mapping(): DB-basierte Synonyme (case-insensitive)
  * normalize_all_signals(): Batch-Processing gegen Katalog
  * load_question_catalog(): Lädt normalization_rules aus DB
- workflow_executor.py (440 Zeilen): Sequenzielle Workflow-Ausführung
  * execute_workflow(): Traversiert DAG in topologischer Reihenfolge
  * execute_node(): Führt analysis nodes aus (start/end = no-op)
  * aggregate_results(): Kombiniert analysis_core + normalized_signals
  * save_execution_state(): Persistiert in workflow_executions
- workflow_models.py: Erweitert um Phase 2 Models
  * SignalStatus Enum (valid, normalized, unclear, invalid, not_decidable)
  * NormalizedSignal (question_type, raw_value, normalized_value, status)
  * NodeExecutionState (node_id, status, analysis_core, normalized_signals)
  * ExecutionResult (execution_id, workflow_id, status, node_states, aggregated_result)
- workflow_engine.py: Neue Funktion get_execution_order()
  * Flattened topological sort für sequenzielle Execution
  * Phase 7: Wird zu levels (parallele Execution)
- prompt_executor.py: execute_workflow_prompt() Implementierung
  * Ruft workflow_executor.execute_workflow() auf
  * Konvertiert ExecutionResult zu API-Response
- routers/workflows.py (230 Zeilen): Workflow Execution API
  * POST /api/workflows/{id}/execute (mit enable_debug)
  * GET /api/workflows/executions/{id} (lädt gespeicherten State)
  * GET /api/workflows (listet alle aktiven Workflows)
  * GET /api/workflows/{id} (lädt einzelnen Workflow mit Graph)
- main.py: Router-Registrierung (workflows.router)

Tests:
- test_phase2_normalization.py (17 Tests): Alle Normalisierungs-Szenarien
  * Exact match, case-insensitive, synonym mapping, invalid, whitespace
  * Batch-Normalisierung, not_in_catalog, mixed validity
- test_phase2_workflow_executor.py (10 Tests): Executor + Aggregation
  * aggregate_results mit verschiedenen Konstellationen
  * execute_node für start/end/analysis/unknown
  * Integration mit question_augmenter + result_container_parser

Alle 27 Unit-Tests bestanden.

version: 0.9k (backend)
module:  workflow 0.3.0

Konzept: .claude/task/Workflow_engine_prompting_engine/anforderungsanalyse_umsetzungsplan.md (Phase 2)
2026-04-03 21:20:23 +02:00
ca562b7130 feat: Phase 1 - Fragenergänzung + Strukturierter Container
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
Backend:
- question_augmenter.py (290 Zeilen): Hybrid-Modell für Fragenergänzungen
  * merge_question_augmentations(): Knotengebundene Fragen überschreiben Prompt-Defaults
  * augment_prompt_with_questions(): Markdown-formatierte Fragenergänzung
  * parse_question_augmentations_from_jsonb(): JSONB → QuestionAugmentation[]
- result_container_parser.py (250 Zeilen): Markdown-Sektionen-Parsing
  * parse_result_container(): Extrahiert Analysekern, Entscheidungsanteil, Begründungsanker
  * validate_decision_signal(): Normalisierung gegen answer_spectrum
  * Fallback-Parsing bei unstrukturierten Antworten
- routers/workflow_questions.py (236 Zeilen): CRUD für workflow_question_catalog
  * GET /api/workflow/questions (mit active_only Filter)
  * POST/PUT/DELETE (Admin only, Soft Delete)
- prompt_executor.py: Integration in execute_base_prompt()
  * Fragenergänzung vor LLM-Call (wenn node_questions oder catalog vorhanden)
  * Result-Container-Parsing nach LLM-Response
- main.py: Router-Registrierung (workflow_questions)

Tests:
- test_phase1_question_augmenter.py (8 Tests): Hybrid-Modell, Formatierung, JSONB-Parsing
- test_phase1_result_container_parser.py (17 Tests): Sektion-Extraktion, Decision-Parsing, Validierung

Alle 25 Unit-Tests bestanden.

version: 0.9j (backend)
module:  workflow 0.2.0

Konzept: .claude/task/Workflow_engine_prompting_engine/konzept_workflow_engine_konsolidated.md (Phase 1)
2026-04-03 18:02:25 +02:00
c79cc9eafb feat: Phase 0c - Multi-Layer Data Architecture (Proof of Concept)
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
- Add data_layer/ module structure with utils.py + body_metrics.py
- Migrate 3 functions: weight_trend, body_composition, circumference_summary
- Refactor placeholders to use data layer
- Add charts router with 3 Chart.js endpoints
- Tests: Syntax , Confidence logic 

Phase 0c PoC (3 functions): Foundation for 40+ remaining functions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 18:26:22 +01:00
12d516c881 refactor: split goals.py into 5 modular routers
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
Code Splitting Results:
- goals.py: 1339 → 655 lines (-684 lines, -51%)
- Created 4 new routers:
  * goal_types.py (426 lines) - Goal Type Definitions CRUD
  * goal_progress.py (155 lines) - Progress tracking
  * training_phases.py (107 lines) - Training phases
  * fitness_tests.py (94 lines) - Fitness tests

Benefits:
 Improved maintainability (smaller, focused files)
 Better context window efficiency for AI tools
 Clearer separation of concerns
 Easier testing and debugging

All routers registered in main.py.
Backward compatible - no API changes.
2026-03-28 06:31:31 +01:00
f312dd0dbb feat: Backend Phase 2 - Focus Areas API + Goals integration
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 13s
**New Router: focus_areas.py**
- GET /focus-areas/definitions (list all, grouped by category)
- POST/PUT/DELETE /focus-areas/definitions (Admin CRUD)
- GET /focus-areas/user-preferences (legacy + future dynamic)
- PUT /focus-areas/user-preferences (auto-normalize to 100%)
- GET /focus-areas/stats (progress per focus area)

**Goals Router Extended:**
- FocusContribution model (focus_area_id + contribution_weight)
- GoalCreate/Update: focus_contributions field
- create_goal: Insert contributions after goal creation
- update_goal: Delete old + insert new contributions
- get_goals_grouped: Load focus_contributions per goal

**Main.py:**
- Registered focus_areas router

**Features:**
- Many-to-Many mapping (goals ↔ focus areas)
- Contribution weights (0-100%)
- Auto-mapped by Migration 031
- User can edit via UI (next: frontend)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 19:48:05 +01:00
337667fc07 feat: Phase 0a - Minimal Goal System (Strategic + Tactical)
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
- Strategic Layer: Goal modes (weight_loss, strength, endurance, recomposition, health)
- Tactical Layer: Concrete goal targets with progress tracking
- Training phases (manual + auto-detection framework)
- Fitness tests (standardized performance tracking)

Backend:
- Migration 022: goal_mode in profiles, goals, training_phases, fitness_tests tables
- New router: routers/goals.py with full CRUD for goals, phases, tests
- API endpoints: /api/goals/* (mode, list, create, update, delete)

Frontend:
- GoalsPage: Goal mode selector + goal management UI
- Dashboard: Goals preview card with link
- API integration: goal mode, CRUD operations, progress calculation

Basis for 120+ placeholders and goal-aware analyses (Phase 0b)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 16:20:35 +01:00
1866ff9ce6 refactor: vitals architecture - separate baseline vs blood pressure
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
BREAKING CHANGE: vitals_log split into vitals_baseline + blood_pressure_log

**Architektur-Änderung:**
- Baseline-Vitals (langsam veränderlich, 1x täglich morgens)
  → vitals_baseline (RHR, HRV, VO2 Max, SpO2, Atemfrequenz)
- Kontext-abhängige Vitals (mehrfach täglich, situativ)
  → blood_pressure_log (Blutdruck + Kontext-Tagging)

**Migration 015:**
- CREATE TABLE vitals_baseline (once daily, morning measurements)
- CREATE TABLE blood_pressure_log (multiple daily, context-aware)
- Migrate data from vitals_log → new tables
- Rename vitals_log → vitals_log_backup_pre_015 (safety)
- Prepared for future: glucose_log, temperature_log (commented)

**Backend:**
- NEW: routers/vitals_baseline.py (CRUD + Apple Health import)
- NEW: routers/blood_pressure.py (CRUD + Omron import + context)
- UPDATED: main.py (register new routers, remove old vitals)
- UPDATED: insights.py (query new tables, split template vars)

**Frontend:**
- UPDATED: api.js (new endpoints für baseline + BP)
- UPDATED: Analysis.jsx (add {{bp_summary}} variable)

**Nächster Schritt:**
- Frontend: VitalsPage.jsx refactoren (3 Tabs: Morgenmessung, Blutdruck, Import)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:02:40 +01:00
4191c52298 feat: implement Vitals module (Ruhepuls + HRV)
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
Backend:
- New router: vitals.py with CRUD endpoints
- GET /api/vitals (list)
- GET /api/vitals/by-date/{date}
- POST /api/vitals (upsert)
- PUT /api/vitals/{id}
- DELETE /api/vitals/{id}
- GET /api/vitals/stats (7d/30d averages, trends)
- Registered in main.py

Frontend:
- VitalsPage.jsx with manual entry form
- List with inline editing
- Stats overview (averages, trend indicators)
- Added to CaptureHub (❤️ icon)
- Route /vitals in App.jsx

API:
- Added vitals methods to api.js

v9d Phase 2d - Vitals tracking complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:52:09 +01:00
1b9cd6d5e6 feat: Training Type Profiles - Phase 1.1 Foundation (#15)
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
## Implemented

### DB-Schema (Migrations)
- Migration 013: training_parameters table (16 standard parameters)
- Migration 014: training_types.profile + activity_log.evaluation columns
- Performance metric calculations (avg_hr_percent, kcal_per_km)

### Backend - Rule Engine
- RuleEvaluator: Generic rule evaluation with 9 operators
  - gte, lte, gt, lt, eq, neq, between, in, not_in
  - Weighted scoring system
  - Pass strategies: all_must_pass, weighted_score, at_least_n

- IntensityZoneEvaluator: HR zone analysis
- TrainingEffectsEvaluator: Abilities development

### Backend - Master Evaluator
- TrainingProfileEvaluator: 7-dimensional evaluation
  1. Minimum Requirements (Quality Gates)
  2. Intensity Zones (HR zones)
  3. Training Effects (Abilities)
  4. Periodization (Frequency & Recovery)
  5. Performance Indicators (KPIs)
  6. Safety (Warnings)
  7. AI Context (simplified for MVP)

- evaluation_helper.py: Utilities for loading + saving
- routers/evaluation.py: API endpoints
  - POST /api/evaluation/activity/{id}
  - POST /api/evaluation/batch
  - GET /api/evaluation/parameters

### Integration
- main.py: Router registration

## TODO (Phase 1.2)
- Auto-evaluation on activity INSERT/UPDATE
- Admin-UI for profile editing
- User-UI for results display

## Testing
-  Syntax checks passed
- 🔲 Runtime testing pending (after auto-evaluation)

Part of Issue #15 - Training Type Profiles System
2026-03-23 10:49:26 +01:00
b63d15fd02 feat: flexible rest days system with JSONB config (v9d Phase 2a)
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
PROBLEM: Simple full_rest/active_recovery model doesn't support
context-specific rest days (e.g., strength rest but cardio allowed).

SOLUTION: JSONB-based flexible rest day configuration.

## Changes:

**Migration 010:**
- Refactor rest_days.type → rest_config JSONB
- Schema: {focus, rest_from[], allows[], intensity_max}
- Validation function with check constraint
- GIN index for performant JSONB queries

**Backend (routers/rest_days.py):**
- CRUD: list, create (upsert by date), get, update, delete
- Stats: count per week, focus distribution
- Validation: check activity conflicts with rest day config

**Frontend (api.js):**
- 7 new methods: listRestDays, createRestDay, updateRestDay,
  deleteRestDay, getRestDaysStats, validateActivity

**Integration:**
- Router registered in main.py
- Ready for weekly planning validation rules

## Next Steps:
- Frontend UI (RestDaysPage with Quick/Custom mode)
- Activity conflict warnings
- Dashboard widget

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 16:20:52 +01:00
ef81c46bc0 feat: v9d Phase 2b - Sleep Module Core (Schlaf-Modul)
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 13s
- Add sleep_log table with JSONB sleep_segments (Migration 009)
- Add sleep router with CRUD + stats endpoints (7d avg, 14d debt, trend, phases)
- Add SleepPage with quick/detail entry forms and inline edit
- Add SleepWidget to Dashboard showing last night + 7d average
- Add sleep navigation entry with Moon icon
- Register sleep router in main.py
- Add 9 new API methods in api.js

Phase 2b complete - ready for testing on dev

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 08:17:11 +01:00
829edecbdc feat: learnable activity type mapping system (DB-based, auto-learning)
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 12s
Replaces hardcoded mappings with database-driven, self-learning system.

Backend:
- Migration 007: activity_type_mappings table
  - Supports global and user-specific mappings
  - Seeded with 40+ default mappings (German + English)
  - Unique constraint: (activity_type, profile_id)
- Refactored: get_training_type_for_activity() queries DB
  - Priority: user-specific → global → NULL
- Bulk categorization now saves mapping automatically
  - Source: 'bulk' for learned mappings
- admin_activity_mappings.py: Full CRUD endpoints
  - List, Get, Create, Update, Delete
  - Coverage stats endpoint
- CSV import uses DB mappings (no hardcoded logic)

Frontend:
- AdminActivityMappingsPage: Full mapping management UI
  - Coverage stats (% mapped, unmapped count)
  - Filter: All / Global
  - Create/Edit/Delete mappings
  - Tip: System learns from bulk categorization
- Added route + admin link
- API methods: adminList/Get/Create/Update/DeleteActivityMapping

Benefits:
- No code changes needed for new activity types
- System learns from user bulk categorizations
- User-specific mappings override global defaults
- Admin can manage all mappings via UI
- Migration pre-populates 40+ common German/English types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 19:31:58 +01:00
eecc00e824 feat: admin CRUD for training types + distribution chart in ActivityPage
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
Backend (v9d Phase 1b):
- Migration 006: Add abilities JSONB column + descriptions
- admin_training_types.py: Full CRUD endpoints for training types
  - List, Get, Create, Update, Delete
  - Abilities taxonomy endpoint (5 dimensions: koordinativ, konditionell, kognitiv, psychisch, taktisch)
  - Validation: Cannot delete types in use
- Register admin_training_types router in main.py

Frontend:
- AdminTrainingTypesPage: Full CRUD UI
  - Create/edit form with all fields (category, subcategory, names, icon, descriptions, sort_order)
  - List grouped by category with color coding
  - Delete with usage check
  - Note about abilities mapping coming in v9f
- Add TrainingTypeDistribution to ActivityPage stats tab
- Add admin link in AdminPanel (v9d section)
- Update api.js with admin training types methods

Notes:
- Abilities mapping UI deferred to v9f (flexible prompt system)
- Placeholders (abilities column) in place for future AI analysis

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 15:32:32 +01:00
410b2ce308 feat(v9d): add training types system + logout button
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
Phase 1: Training Types Basis
=============================

Backend:
- Migration 004: training_types table + seed data (24 types)
- New router: /api/training-types (grouped, flat, categories)
- Extend activity_log: training_type_id, training_category, training_subcategory
- Extend ActivityEntry model: support training type fields

Frontend:
- TrainingTypeSelect component (two-level dropdown)
- TrainingTypeDistribution component (pie chart)
- API functions: listTrainingTypes, listTrainingTypesFlat, getTrainingCategories

Quick Win: Logout Button
========================
- Add LogOut icon button in app header
- Confirm dialog before logout
- Redirect to / after logout
- Hover effect: red color on hover

Not yet integrated:
- TrainingTypeSelect not yet in ActivityPage form
- TrainingTypeDistribution not yet in Dashboard
  (will be added in next commit)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 13:05:33 +01:00
a849d5db9e feat: add admin management routers for subscription system
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Five new admin routers:

1. routers/features.py
   - GET/POST/PUT/DELETE /api/features
   - Feature registry CRUD
   - Allows adding new limitable features without schema changes

2. routers/tiers_mgmt.py
   - GET/POST/PUT/DELETE /api/tiers
   - Subscription tier management
   - Price configuration, sort order

3. routers/tier_limits.py
   - GET /api/tier-limits - Complete Tier x Feature matrix
   - PUT /api/tier-limits - Update single limit
   - PUT /api/tier-limits/batch - Batch update
   - DELETE /api/tier-limits - Remove limit (fallback to default)
   - Matrix editor backend

4. routers/user_restrictions.py
   - GET/POST/PUT/DELETE /api/user-restrictions
   - User-specific feature overrides
   - Highest priority in access hierarchy
   - Includes reason field for documentation

5. routers/access_grants.py
   - GET /api/access-grants - List grants with filters
   - POST /api/access-grants - Manual grant creation
   - PUT /api/access-grants/{id} - Extend/pause grants
   - DELETE /api/access-grants/{id} - Revoke access
   - Activity logging

All endpoints require admin authentication.
Completes backend API for v9c Phase 2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:09:33 +01:00
ae9743d6ed feat: add coupon management and redemption
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 12s
New router: routers/coupons.py

Admin endpoints:
- GET /api/coupons - List all coupons with stats
- POST /api/coupons - Create new coupon
- PUT /api/coupons/{id} - Update coupon
- DELETE /api/coupons/{id} - Soft-delete (set active=false)
- GET /api/coupons/{id}/redemptions - Redemption history

User endpoints:
- POST /api/coupons/redeem - Redeem coupon code

Features:
- Three coupon types: single_use, period, wellpass
- Wellpass logic: Pauses existing personal grants, resumes after expiry
- Max redemptions limit (NULL = unlimited)
- Validity period checks
- Activity logging
- Duplicate redemption prevention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:07:09 +01:00
ae47652d0c feat: add user subscription info endpoints
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
New router: routers/subscription.py
Endpoints:
- GET /api/subscription/me - Own subscription info (tier, trial, grants)
- GET /api/subscription/usage - Feature usage with limits
- GET /api/subscription/limits - All feature limits for current tier

Features:
- Shows effective tier (considers access_grants)
- Lists active access grants (from coupons, trials)
- Per-feature usage tracking
- Email verification status

Uses new middleware: get_effective_tier(), check_feature_access()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:05:55 +01:00
2f302b26af feat: add v9c subscription system database schema
All checks were successful
Deploy Development / deploy (push) Successful in 53s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 12s
Phase 1: Database Migration Complete

Created migration infrastructure:
- backend/migrations/v9c_subscription_system.sql (11 new tables)
- backend/apply_v9c_migration.py (auto-migration runner)
- Updated main.py startup event to apply migration

New tables (Feature-Registry Pattern):
1. app_settings - Global configuration
2. tiers - Subscription tiers (free/basic/premium/selfhosted)
3. features - Feature registry (11 limitable features)
4. tier_limits - Tier x Feature matrix (44 initial limits)
5. user_feature_restrictions - Individual user overrides
6. user_feature_usage - Usage tracking with reset periods
7. coupons - Coupon management (single-use, period, Wellpass)
8. coupon_redemptions - Redemption history
9. access_grants - Time-limited access with pause/resume logic
10. user_activity_log - Activity tracking (JSONB details)
11. user_stats - Aggregated statistics

Extended profiles table:
- tier, trial_ends_at, email_verified, email_verify_token
- invited_by, invitation_token

Initial data inserted:
- 4 tiers (free/basic/premium/selfhosted)
- 11 features (weight, circumference, caliper, nutrition, activity, photos, ai_calls, ai_pipeline, export_*)
- 44 tier_limits (complete Tier x Feature matrix)
- App settings (trial duration, self-registration config)

Migration auto-runs on container startup (similar to SQLite→PostgreSQL).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:42:43 +01:00
b4a1856f79 refactor: modular backend architecture with 14 router modules
All checks were successful
Deploy Development / deploy (push) Successful in 58s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Phase 2 Complete - Backend Refactoring:
- Extracted all endpoints to dedicated router modules
- main.py: 1878 → 75 lines (-96% reduction)
- Created modular structure for maintainability

Router Structure (60 endpoints total):
├── auth.py          - 7 endpoints (login, logout, password reset)
├── profiles.py      - 7 endpoints (CRUD + current user)
├── weight.py        - 5 endpoints (tracking + stats)
├── circumference.py - 4 endpoints (body measurements)
├── caliper.py       - 4 endpoints (skinfold tracking)
├── activity.py      - 6 endpoints (workouts + Apple Health import)
├── nutrition.py     - 4 endpoints (diet + FDDB import)
├── photos.py        - 3 endpoints (progress photos)
├── insights.py      - 8 endpoints (AI analysis + pipeline)
├── prompts.py       - 2 endpoints (AI prompt management)
├── admin.py         - 7 endpoints (user management)
├── stats.py         - 1 endpoint (dashboard stats)
├── exportdata.py    - 3 endpoints (CSV/JSON/ZIP export)
└── importdata.py    - 1 endpoint (ZIP import)

Core modules maintained:
- db.py: PostgreSQL connection + helpers
- auth.py: Auth functions (hash, verify, sessions)
- models.py: 11 Pydantic models

Benefits:
- Self-contained modules with clear responsibilities
- Easier to navigate and modify specific features
- Improved code organization and readability
- 100% functional compatibility maintained
- All syntax checks passed

Updated CLAUDE.md with new architecture documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:15:35 +01:00
9e6a542289 fix: change password endpoint method from POST to PUT to match frontend
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
2026-03-19 10:13:07 +01:00
c7d283c0c9 refactor: extract Pydantic models to models.py
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Phase 1.3 - Data Models isolieren

NEUE DATEI:
- backend/models.py: Alle Pydantic Models (122 Zeilen)
  * ProfileCreate, ProfileUpdate
  * WeightEntry, CircumferenceEntry, CaliperEntry
  * ActivityEntry, NutritionDay
  * LoginRequest, PasswordResetRequest, PasswordResetConfirm
  * AdminProfileUpdate

ÄNDERUNGEN:
- backend/main.py:
  * Import models from models.py
  * Entfernt: ~60 Zeilen Model-Definitionen
  * Von 2025 → 1878 Zeilen (-147 Zeilen / -7%)

PROGRESS:
 db.py: Database + init_db
 auth.py: Auth functions + dependencies
 models.py: Pydantic schemas

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 09:53:51 +01:00
d826524789 refactor: extract auth functions to auth.py
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 13s
Phase 1.2 - Authentication-Logik isolieren

NEUE DATEI:
- backend/auth.py: Auth-Funktionen mit Dokumentation
  * hash_pin() - bcrypt + SHA256 legacy support
  * verify_pin() - Password verification
  * make_token() - Session token generation
  * get_session() - Token validation
  * require_auth() - FastAPI dependency
  * require_auth_flexible() - Auth via header OR query
  * require_admin() - Admin-only dependency

ÄNDERUNGEN:
- backend/main.py:
  * Import from auth.py
  * Removed 48 lines of auth code
  * hashlib, secrets nicht mehr benötigt

KEINE funktionalen Änderungen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 09:51:25 +01:00
548d733048 refactor: move init_db() to db.py
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Phase 1.1 - Database-Logik konsolidieren

ÄNDERUNGEN:
- init_db() von main.py nach db.py verschoben
- main.py importiert init_db von db
- startup_event() ruft db.init_db() auf
- Keine funktionalen Änderungen

DATEIEN:
- backend/db.py: +60 Zeilen (init_db Funktion)
- backend/main.py: -48 Zeilen (init_db entfernt, import hinzugefügt)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 09:49:46 +01:00
85f48907a4 fix: startup crash - init_db() jetzt mit Error-Handling
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 12s
PROBLEM:
- Backend crasht beim Start auf Prod
- Login zeigt HTML statt JSON (Backend nicht erreichbar)
- Ursache: init_db() wirft Exception beim Startup

FIX:
1. startup_event() wrapped in try-except (non-fatal)
2. init_db() prüft ob ai_prompts Tabelle existiert
3. init_db() hat eigenen try-except
4. Bessere Fehlermeldungen in stdout

ERGEBNIS:
- Backend startet auch wenn init_db() fehlschlägt
- Pipeline-Prompt kann manuell angelegt werden falls nötig
- Login funktioniert wieder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 08:26:09 +01:00
c40b30737a feat: zentraler Schalter für Pipeline-Deaktivierung
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
VORHER:
- Pipeline-Deaktivierung war nicht sichtbar im UI
- Deaktivierung sollte über Sub-Prompts erfolgen (nicht intuitiv)

JETZT:
- Zentraler Toggle-Button direkt unter "Mehrstufige Pipeline"
- Button-Text: "Gesamte Pipeline aktivieren/deaktivieren"
- Visuelles Feedback: Warning-Box wird rot wenn deaktiviert

IMPLEMENTIERUNG:

Backend (main.py):
- Neuer "pipeline" Master-Prompt wird automatisch angelegt
- startup_event() ruft init_db() auf
- Prompt: slug='pipeline', sort_order=-10 (ganz oben)
- Template: 'PIPELINE_MASTER' (nur Steuerung, kein echtes Template)

Frontend (Analysis.jsx):
- Toggle-Button unter Sektionsüberschrift
- Prüft: prompts.find(p=>p.slug==='pipeline')?.active
- pipelineAvailable basiert auf diesem Prompt (nicht Sub-Prompts)
- Warning-Box wechselt Farbe + Text:
  * Aktiv: Orange + JSON-Hinweis
  * Inaktiv: Rot + "Pipeline deaktiviert"

VERHALTEN:
 Button im Prompts-Tab unter "Mehrstufige Pipeline"
 Klar sichtbar: "Gesamte Pipeline deaktivieren"
 Pipeline verschwindet von Analyse-Seite wenn deaktiviert
 Sub-Prompts bleiben unabhängig editierbar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 07:56:36 +01:00
3f4ef75463 fix: Prompt-Deaktivierung jetzt voll funktionsfähig
All checks were successful
Deploy Development / deploy (push) Successful in 57s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
PROBLEME behoben:
1. Falscher Datentyp: Frontend sendete 0/1 statt boolean
2. Button-Text: "Aktiv." → "Aktivieren"
3. Keine visuelle Markierung für deaktivierte Prompts

FIXES:

Backend (main.py):
- active-Wert wird explizit zu boolean konvertiert
- Akzeptiert jetzt sowohl true/false als auch 1/0

Frontend (Analysis.jsx):
- Sendet jetzt !p.active (boolean) statt p.active?0:1
- Button-Text: "Deaktivieren" / "Aktivieren" (klar lesbar)
- Visuelle Markierung für inaktive Prompts:
  * Opacity 0.6 (ausgegraut)
  * Rotes Badge "⏸ Deaktiviert"
- Gilt für Einzel- UND Pipeline-Prompts

RESULTAT:
 Deaktivierte Prompts werden nicht mehr auf "Analysen starten" gezeigt
 Klare visuelle Unterscheidung im Prompts-Tab
 Button-Text eindeutig ("Aktivieren" vs "Deaktivieren")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 07:27:56 +01:00
518e417b1d fix: admins können jetzt alle Prompts sehen und bearbeiten
All checks were successful
Deploy Development / deploy (push) Successful in 57s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
- /api/prompts checkt nun ob User admin ist
- Admins sehen ALLE Prompts (inkl. pipeline_ und inaktive)
- Normale User sehen nur aktive Einzelanalysen (wie bisher)
- Frontend (Analysis.jsx) zeigt Pipeline-Prompts bereits korrekt:
  * Gruppiert nach "Einzelanalysen" und "Mehrstufige Pipeline"
  * JSON-Prompts (Stage 1) mit oranger Border und Badge
  * Warnung über JSON-Format bereits vorhanden
- CSS-Variablen --warn, --warn-bg, --warn-text bereits definiert

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 06:28:48 +01:00
115d975335 feat: add ZIP import functionality
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 11s
- Backend: POST /api/import/zip endpoint with validation and rollback
- CSV import with ON CONFLICT DO NOTHING for duplicate detection
- Photo import with existence check
- AI insights import
- Frontend: file upload UI in SettingsPage
- Import summary showing count per category
- Full transaction rollback on error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 22:52:35 +01:00
e10e9d7eb9 fix: photos now display in History with token auth
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 13s
Problem: Photo endpoint requires auth header, but <img src> can't send headers.

Solution:
- Backend: Added require_auth_flexible() that accepts token via header OR query param
- Backend: Photo endpoint uses flexible auth
- Frontend: photoUrl() now appends ?token=xxx to URL

Photos in History/Verlauf now display correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 22:48:40 +01:00
b6f8b11685 fix: handle datetime.date object for birth_year in ZIP export
All checks were successful
Deploy Development / deploy (push) Successful in 58s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 12s
PostgreSQL returns dob as datetime.date object, not string.
Changed from prof['dob'][:4] to prof['dob'].year

Error was: TypeError: 'datetime.date' object is not subscriptable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 22:41:51 +01:00
64d1b9bf7b feat: implement comprehensive ZIP export per v9c specification
All checks were successful
Deploy Development / deploy (push) Successful in 1m15s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Complete rewrite of ZIP export to match CLAUDE.md specification.

**Structure:**
- README.txt (format explanation)
- profile.json (no password hash, includes stats)
- data/*.csv (5 separate CSV files)
- insights/ai_insights.json
- photos/*.jpg

**CSV Format:**
- Delimiter: semicolon (;)
- Encoding: UTF-8 with BOM (Excel compatible)
- Date format: YYYY-MM-DD
- Decimal separator: dot (.)
- NULL values: empty string
- First row: header

**Files:**
- data/weight.csv (id, date, weight, note, source, created)
- data/circumferences.csv (8 measurement points)
- data/caliper.csv (skinfold measurements + bf%)
- data/nutrition.csv (kcal, protein, fat, carbs)
- data/activity.csv (type, duration, kcal, HR, distance)

**Filename:** mitai-export-{name}-{YYYY-MM-DD}.zip

Ready for import functionality (v9c).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 22:15:31 +01:00
47a268f426 fix: comprehensive PostgreSQL Decimal handling across all endpoints
All checks were successful
Deploy Development / deploy (push) Successful in 55s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Fixed all remaining Decimal → float conversion issues found by audit.

**Fixed Endpoints:**
1. Weight Stats: min/max/avg calculations
2. Activity Stats: kcal/duration accumulation
3. Nutrition Weekly: average calculations
4. Template Variables: all f-string Decimal formatting
5. CSV Export: all numeric value formatting
6. JSON Export: added Decimal handler
7. ZIP Export: added Decimal handler
8. Correlations: weight, nutrition, caliper values

**Changes:**
- Added `from decimal import Decimal` import
- Weight stats: convert to float for min/max/avg
- Activity: float() in sum() and accumulation
- Nutrition: float() in averages
- Template vars: float() for weight_aktuell, kf_aktuell, goals
- CSV: float() in all f-strings (weight, circ, caliper, nutrition, activity)
- JSON/ZIP: custom decimal_handler for json.dumps()
- Correlations: float() for all numeric DB values

Prevents:
- TypeError in math operations
- "Decimal('X')" strings in exports
- JSON serialization failures

All numeric values from PostgreSQL now properly converted to float.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 21:52:57 +01:00
f7f7f745b1 fix: convert PostgreSQL Decimal to float for math operations
All checks were successful
Deploy Development / deploy (push) Successful in 59s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
Fixed TypeError when preparing AI prompt template variables.
PostgreSQL returns NUMERIC columns as decimal.Decimal, not float.

**Fixed in _prepare_template_vars:**
- Weight calculations (protein targets, delta)
- Nutrition averages (kcal, protein, fat, carbs)
- Activity totals (kcal_active)

All Decimal values now converted to float before math operations.

Error was: "TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 21:44:10 +01:00
1db780858b fix: align all API endpoints between frontend and backend
Fixed 11 critical endpoint mismatches found during codebase audit.

**Renamed Endpoints (consistency):**
- /api/ai/analyze/{slug} → /api/insights/run/{slug}
- /api/ai/analyze-pipeline → /api/insights/pipeline
- /api/auth/password-reset-request → /api/auth/forgot-password
- /api/auth/password-reset-confirm → /api/auth/reset-password
- /api/admin/test-email → /api/admin/email/test

**Added Missing Endpoints:**
- POST /api/auth/pin (change PIN/password for current user)
- PUT /api/admin/profiles/{id}/permissions (set permissions)
- PUT /api/admin/profiles/{id}/email (set email)
- PUT /api/admin/profiles/{id}/pin (admin set PIN)
- GET /api/admin/email/status (check SMTP config)
- PUT /api/prompts/{id} (edit prompt templates, admin only)
- GET /api/export/json (export all data as JSON)
- GET /api/export/zip (export data + photos as ZIP)

**Updated:**
- Added imports: json, zipfile, Response
- Fixed admin email test endpoint to accept dict body

All frontend API calls now have matching backend implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 17:07:41 +01:00
3d58a2db8e fix: add missing /api/insights endpoints
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 13s
- Add GET /api/insights (returns all insights for profile)
- Add DELETE /api/insights/{id} (delete by ID, not scope)
- Frontend Analysis.jsx needs these endpoints to load/delete insights

Fixes 404 error preventing prompts from displaying.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 15:26:57 +01:00
36f334aba7 fix: PostgreSQL boolean syntax in prompts queries
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
- Change WHERE active=1 to WHERE active=true (PostgreSQL uses boolean)
- Change endpoint from /api/ai/prompts to /api/prompts (simpler path)
- Fixed 5 occurrences across prompt-related queries

This fixes the issue where no prompts were returned, causing empty
prompt list in Admin and no AI analysis options.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 13:55:14 +01:00
8390c7f510 feat: add missing API endpoints
All checks were successful
Deploy Development / deploy (push) Successful in 53s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
- Add GET /api/insights/latest (returns latest 10 insights)
- Add GET /api/auth/status (health check endpoint)

These endpoints were called by frontend but returned 404,
causing uncaught promise errors that blocked page loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 12:54:25 +01:00
79a951ce92 fix: use column names for COUNT queries with RealDictCursor
All checks were successful
Deploy Development / deploy (push) Successful in 58s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 12s
RealDictCursor returns dicts, not tuples. Cannot use [0] for index access.
Changed all COUNT(*) to COUNT(*) as count and access via ['count'].

Fixes: KeyError: 0 on cur.fetchone()[0]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 12:47:01 +01:00
9fbedb6c4b fix: use RealDictCursor for PostgreSQL row access
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 12s
All conn.cursor() calls replaced with get_cursor(conn) to enable
dict-like row access (prof['pin_hash'] instead of prof[column_index]).

This fixes KeyError when accessing PostgreSQL query results.

Fixes: 'tuple' object has no attribute '__getitem__' with string keys

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 12:42:46 +01:00
0a871fea22 9b
Some checks failed
Deploy Development / deploy (push) Failing after 1s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 1m6s
2026-03-18 08:27:33 +01:00
89b6c0b072 feat: initial commit – Mitai Jinkendo v9a
Some checks are pending
Deploy to Raspberry Pi / deploy (push) Waiting to run
Build Test / build-frontend (push) Waiting to run
Build Test / lint-backend (push) Waiting to run
2026-03-16 13:35:11 +01:00