mitai-jinkendo/backend/main.py
Lars 62729d0648
All checks were successful
Deploy Development / deploy (push) Successful in 1m4s
Build Test / pytest-backend (push) Successful in 5s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 19s
feat: add report_export widget and enhance report generation capabilities
- Introduced the `report_export` widget to the dashboard, allowing users to generate structured PDF reports.
- Updated widget configuration to include `report_export` in the allowed widgets and added validation for its configuration.
- Enhanced the widget catalog with details for the new `report_export` entry.
- Implemented API endpoints for managing report profiles and generating PDFs.
- Added frontend components for configuring and displaying report settings.
- Updated tests to ensure proper validation and functionality of the new report generation features.
- Bumped application version to reflect the addition of the new widget and related functionalities.
2026-04-29 11:28:04 +02:00

142 lines
7.8 KiB
Python

"""
Mitai Jinkendo API - Main Application
FastAPI backend with modular router structure.
"""
import os
from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from db import init_db
# Placeholder registry: load all register_placeholder() side-effects before any request
# so get_placeholder_catalog() and exports see consistent metadata (see Phase A plan).
import placeholder_registrations # noqa: F401
# Import routers
from routers import auth, profiles, weight, circumference, caliper
from routers import activity, nutrition, photos, insights, prompts
from routers import admin, stats, exportdata, importdata
from routers import subscription, coupons, features, tiers_mgmt, tier_limits
from routers import user_restrictions, access_grants, training_types, admin_training_types
from routers import admin_activity_mappings, sleep, rest_days
from routers import vitals_baseline, blood_pressure # v9d Phase 2d Refactored
from routers import evaluation # v9d/v9e Training Type Profiles (#15)
from routers import goals, focus_areas # v9e/v9g Goal System v2.0 (Dynamic Focus Areas)
from routers import goal_types, goal_progress, training_phases, fitness_tests # v9h Goal System (Split routers)
from routers import charts # Phase 0c Multi-Layer Architecture
from routers import workflow_questions # Phase 1 Workflow Engine - Question Catalog
from routers import workflows # Phase 2 Workflow Engine - Execution
from routers import reference_values # Persönliche Referenzwerte (Profil)
from routers import admin_reference_value_types # Admin: Referenzwert-Typen
from routers import app_dashboard # Geschützter App-Bereich: Dashboard-Layout + Widget-Katalog
from routers import reports # Strukturierter PDF-Bericht (Profil v1)
from routers import csv_import, admin_csv_templates # Issue #21 Universal CSV Parser
from routers import admin_training_parameters, admin_activity_attribute_profiles # EAV session metrics
# ── App Configuration ─────────────────────────────────────────────────────────
DATA_DIR = Path(os.getenv("DATA_DIR", "./data"))
PHOTOS_DIR = Path(os.getenv("PHOTOS_DIR", "./photos"))
DATA_DIR.mkdir(parents=True, exist_ok=True)
PHOTOS_DIR.mkdir(parents=True, exist_ok=True)
app = FastAPI(title="Mitai Jinkendo API", version="3.0.0")
# Rate limiting
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=os.getenv("ALLOWED_ORIGINS", "*").split(","),
allow_credentials=True,
allow_methods=["GET","POST","PUT","DELETE","OPTIONS"],
allow_headers=["*"],
)
# ── Startup Event ─────────────────────────────────────────────────────────────
@app.on_event("startup")
async def startup_event():
"""Run database initialization on startup."""
try:
init_db()
except Exception as e:
print(f"[WARN] init_db() failed (non-fatal): {e}")
# Don't crash on startup - can be created manually
# Apply v9c migration if needed
try:
from apply_v9c_migration import apply_migration
apply_migration()
except Exception as e:
print(f"[WARN] v9c migration failed (non-fatal): {e}")
# ── Register Routers ──────────────────────────────────────────────────────────
app.include_router(auth.router) # /api/auth/*
app.include_router(profiles.router) # /api/profiles/*, /api/profile
app.include_router(weight.router) # /api/weight/*
app.include_router(circumference.router) # /api/circumferences/*
app.include_router(caliper.router) # /api/caliper/*
app.include_router(activity.router) # /api/activity/*
app.include_router(nutrition.router) # /api/nutrition/*
app.include_router(photos.router) # /api/photos/*
app.include_router(insights.router) # /api/insights/*, /api/ai/*
app.include_router(prompts.router) # /api/prompts/*
app.include_router(admin.router) # /api/admin/*
app.include_router(stats.router) # /api/stats
app.include_router(exportdata.router) # /api/export/*
app.include_router(importdata.router) # /api/import/*
# v9c Subscription System
app.include_router(subscription.router) # /api/subscription/*
app.include_router(coupons.router) # /api/coupons/*
app.include_router(features.router) # /api/features (admin)
app.include_router(tiers_mgmt.router) # /api/tiers (admin)
app.include_router(tier_limits.router) # /api/tier-limits (admin)
app.include_router(user_restrictions.router) # /api/user-restrictions (admin)
app.include_router(access_grants.router) # /api/access-grants (admin)
# v9d Training Types & Sleep Module & Rest Days & Vitals
app.include_router(training_types.router) # /api/training-types/*
app.include_router(admin_training_types.router) # /api/admin/training-types/*
app.include_router(admin_activity_mappings.router) # /api/admin/activity-mappings/*
app.include_router(sleep.router) # /api/sleep/* (v9d Phase 2b)
app.include_router(rest_days.router) # /api/rest-days/* (v9d Phase 2a)
app.include_router(vitals_baseline.router) # /api/vitals/baseline/* (v9d Phase 2d Refactored)
app.include_router(blood_pressure.router) # /api/blood-pressure/* (v9d Phase 2d Refactored)
app.include_router(evaluation.router) # /api/evaluation/* (v9d/v9e Training Profiles #15)
app.include_router(goals.router) # /api/goals/* (v9h Goal System Core CRUD + Focus Areas)
app.include_router(goal_types.router) # /api/goals/goal-types/* (v9h Goal Type Definitions)
app.include_router(goal_progress.router) # /api/goals/{goal_id}/progress/* (v9h Progress Tracking)
app.include_router(training_phases.router) # /api/goals/phases/* (v9h Training Phases)
app.include_router(fitness_tests.router) # /api/goals/tests/* (v9h Fitness Tests)
app.include_router(focus_areas.router) # /api/focus-areas/* (v9g Focus Area System v2.0 - Dynamic)
# Phase 0c Multi-Layer Architecture
app.include_router(charts.router) # /api/charts/* (Phase 0c Charts API)
# Phase 1-2 Workflow Engine
app.include_router(workflow_questions.router) # /api/workflow/questions/* (Phase 1 Question Catalog)
app.include_router(workflows.router) # /api/workflows/* (Phase 2 Execution)
app.include_router(reference_values.router) # /api/reference-value-types, /api/profile-reference-values
app.include_router(admin_reference_value_types.router) # /api/admin/reference-value-types
app.include_router(app_dashboard.router) # /api/app/dashboard-layout
app.include_router(reports.router) # /api/reports/* (Berichtsprofil + PDF)
app.include_router(csv_import.router) # /api/csv/* (Issue #21)
app.include_router(admin_csv_templates.router) # /api/admin/csv-templates/* (Issue #21)
app.include_router(admin_training_parameters.router) # /api/admin/training-parameters
app.include_router(admin_activity_attribute_profiles.router) # /api/admin/training-*-parameters
# ── Health Check ──────────────────────────────────────────────────────────────
@app.get("/")
def root():
"""API health check."""
return {"status": "ok", "service": "mitai-jinkendo", "version": "v9c-dev"}