fix: systemd ohne ProtectHome (venv unter /root sichtbar) + Phase-3-Backend

Deployment-Fixes (Dienst startete nicht -> 203/EXEC "uvicorn not found"):
- Unit ohne ProtectHome/ProtectSystem: Repo/venv dürfen unter /root oder /home
  liegen (ProtectHome=true blendete diese Pfade für den Dienst aus).
- install.sh: Python-3.11+-Prüfung mit klarer Meldung; prüft nach der Installation,
  dass uvicorn wirklich in der venv liegt.
- EZB-Kursabruf läuft beim Start jetzt im Hintergrund (blockiert den Start nie).

Phase-3-Backend (Dashboard):
- Modell + Migration 0004: dashboard_layouts (JSON-Layout je Nutzer).
- routers/dashboard: Layout speichern/laden/zurücksetzen + Kartendaten
  (Budget-Donut, Budget-Fortschritt, Einnahmen/Ausgaben, Kontostände,
  Vermögensverlauf, letzte Buchungen).
- Frontend-Infrastruktur: Chart-Komponenten (Donut/Line), palette, API-Methoden,
  react-grid-layout. (Dashboard-Seite folgt im nächsten Commit.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-19 19:31:55 +02:00
co-authored by Claude Opus 4.8
parent f53c79a20c
commit 2dd8f9cd35
14 changed files with 685 additions and 8 deletions
@@ -0,0 +1,30 @@
"""Dashboard-Layout je Benutzer.
Revision ID: 0004
Revises: 0003
Create Date: 2026-08-19
"""
from alembic import op
import sqlalchemy as sa
revision = "0004"
down_revision = "0003"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
"dashboard_layouts",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("owner_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False),
sa.Column("layout", sa.Text(), nullable=False, server_default="[]"),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True),
sa.UniqueConstraint("owner_id", name="uq_dashboard_owner"),
)
op.create_index("ix_dashboard_layouts_owner_id", "dashboard_layouts", ["owner_id"])
def downgrade() -> None:
op.drop_index("ix_dashboard_layouts_owner_id", table_name="dashboard_layouts")
op.drop_table("dashboard_layouts")