2026-05-24 19:13:19 +02:00
|
|
|
"""SuS-Profil-Routen: Login, Cockpit (progressiv), Check-In, Lektion-Status, Paarung.
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
2026-05-24 19:13:19 +02:00
|
|
|
Etappe 1: Login-Flow.
|
|
|
|
|
Etappe 2: Cockpit progressiv (V1), Check-In (V3 + E-021), Lektion-Status, Paarung.
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
Etappe 6: Projekt-Workflow.
|
|
|
|
|
Etappe 7: Druckauftraege + Slots.
|
|
|
|
|
"""
|
2026-05-24 19:13:19 +02:00
|
|
|
from datetime import date
|
|
|
|
|
|
|
|
|
|
from flask import (
|
|
|
|
|
Blueprint, render_template, request, redirect, url_for,
|
|
|
|
|
session, flash, abort, jsonify
|
|
|
|
|
)
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
|
|
|
|
from database import get_db
|
|
|
|
|
from services.auth import (
|
|
|
|
|
pin_pruefen,
|
|
|
|
|
ist_gesperrt,
|
|
|
|
|
fehlversuch_loggen,
|
|
|
|
|
lockout_zuruecksetzen,
|
|
|
|
|
login_required,
|
|
|
|
|
)
|
2026-05-24 19:13:19 +02:00
|
|
|
from services.cockpit_status import (
|
|
|
|
|
get_cockpit_status,
|
|
|
|
|
get_andere_profile,
|
|
|
|
|
ONBOARDING_LEKTIONEN,
|
|
|
|
|
)
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
from tiere import tier_emoji, tier_name
|
|
|
|
|
|
|
|
|
|
bp = Blueprint("profil", __name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================================
|
2026-05-24 19:13:19 +02:00
|
|
|
# Login-Flow (Etappe 1, unveraendert)
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
# ===========================================================================
|
|
|
|
|
|
|
|
|
|
@bp.route("/login")
|
|
|
|
|
def login():
|
|
|
|
|
conn = get_db()
|
|
|
|
|
profile = conn.execute(
|
|
|
|
|
"SELECT id, vorname, tier FROM profil WHERE aktiv = 1 "
|
|
|
|
|
"ORDER BY vorname COLLATE NOCASE, tier"
|
|
|
|
|
).fetchall()
|
|
|
|
|
conn.close()
|
|
|
|
|
return render_template("login.html", profile=profile)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/login/<int:profil_id>", methods=["GET", "POST"])
|
|
|
|
|
def login_pin(profil_id):
|
|
|
|
|
conn = get_db()
|
|
|
|
|
profil = conn.execute(
|
|
|
|
|
"SELECT id, vorname, tier, pin_hash, aktiv FROM profil WHERE id = ?",
|
|
|
|
|
(profil_id,)
|
|
|
|
|
).fetchone()
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
if not profil or not profil["aktiv"]:
|
|
|
|
|
flash("Profil nicht gefunden.", "error")
|
|
|
|
|
return redirect(url_for("profil.login"))
|
|
|
|
|
|
|
|
|
|
gesperrt, sek_rest = ist_gesperrt(profil_id)
|
|
|
|
|
if gesperrt:
|
|
|
|
|
min_rest = sek_rest // 60 + 1
|
|
|
|
|
return render_template(
|
|
|
|
|
"login_pin.html",
|
|
|
|
|
profil=profil,
|
|
|
|
|
gesperrt=True,
|
|
|
|
|
min_rest=min_rest
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
eingabe_pin = (request.form.get("pin") or "").strip()
|
|
|
|
|
if pin_pruefen(eingabe_pin, profil["pin_hash"]):
|
|
|
|
|
lockout_zuruecksetzen(profil_id)
|
|
|
|
|
session.clear()
|
|
|
|
|
session["profil_id"] = profil["id"]
|
|
|
|
|
session["vorname"] = profil["vorname"]
|
|
|
|
|
session["tier"] = profil["tier"]
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
else:
|
|
|
|
|
fehlversuch_loggen(profil_id)
|
|
|
|
|
flash("Falsche PIN. Versuch's nochmal.", "error")
|
|
|
|
|
|
|
|
|
|
return render_template("login_pin.html", profil=profil, gesperrt=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/logout")
|
|
|
|
|
def logout():
|
|
|
|
|
session.clear()
|
|
|
|
|
flash("Du bist ausgeloggt.", "success")
|
|
|
|
|
return redirect(url_for("oeffentlich.index"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================================
|
2026-05-24 19:13:19 +02:00
|
|
|
# Cockpit (Etappe 2: progressives Layout V1)
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
# ===========================================================================
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit")
|
|
|
|
|
@login_required
|
|
|
|
|
def cockpit():
|
2026-05-24 19:13:19 +02:00
|
|
|
status = get_cockpit_status(session["profil_id"])
|
|
|
|
|
andere_profile = []
|
|
|
|
|
if not status["paarung"]:
|
|
|
|
|
andere_profile = get_andere_profile(session["profil_id"])
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
return render_template(
|
2026-05-24 19:13:19 +02:00
|
|
|
"cockpit.html",
|
|
|
|
|
status=status,
|
|
|
|
|
andere_profile=andere_profile,
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
vorname=session.get("vorname"),
|
|
|
|
|
tier=session.get("tier"),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2026-05-24 19:13:19 +02:00
|
|
|
# ===========================================================================
|
|
|
|
|
# Check-In (V3 + E-021)
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
@bp.route("/cockpit/check-in", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def check_in():
|
2026-05-24 19:13:19 +02:00
|
|
|
modus = (request.form.get("modus") or "").strip()
|
|
|
|
|
freitext = (request.form.get("freitext") or "").strip() or None
|
|
|
|
|
|
|
|
|
|
# Modus validieren — einfach, kein striktes ENUM
|
|
|
|
|
erlaubte_modi = {
|
|
|
|
|
"weiter_wie_bisher", "neues_projekt", "onboarding",
|
|
|
|
|
"drucken", "helfen", "sonstiges"
|
|
|
|
|
}
|
|
|
|
|
if modus not in erlaubte_modi:
|
|
|
|
|
flash("Ungueltige Auswahl.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
conn = get_db()
|
|
|
|
|
conn.execute(
|
|
|
|
|
"INSERT OR REPLACE INTO check_in (profil_id, besuch_datum, modus, freitext) "
|
|
|
|
|
"VALUES (?, ?, ?, ?)",
|
|
|
|
|
(session["profil_id"], date.today().isoformat(), modus, freitext)
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit/notiz/<int:notiz_id>/gelesen", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def notiz_gelesen(notiz_id):
|
|
|
|
|
"""Lehrer-Notiz als gelesen markieren (V6 + V5)."""
|
|
|
|
|
conn = get_db()
|
|
|
|
|
conn.execute(
|
|
|
|
|
"UPDATE lehrer_notiz SET gelesen_am = CURRENT_TIMESTAMP "
|
|
|
|
|
"WHERE id = ? AND profil_id = ? AND gelesen_am IS NULL",
|
|
|
|
|
(notiz_id, session["profil_id"])
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
|
|
|
|
|
2026-05-24 19:13:19 +02:00
|
|
|
# ===========================================================================
|
|
|
|
|
# Onboarding-Lektion-Status (selbst-zertifiziert, E-019)
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
@bp.route("/cockpit/lektion/<int:nummer>/status", methods=["POST"])
|
|
|
|
|
@login_required
|
2026-05-24 19:13:19 +02:00
|
|
|
def lektion_status_setzen(nummer):
|
|
|
|
|
"""Status-Wechsel: offen -> laeuft -> fertig (oder zurueck via 'reset')."""
|
|
|
|
|
neuer_status = (request.form.get("status") or "").strip()
|
|
|
|
|
erlaubte = {"offen", "laeuft", "fertig"}
|
|
|
|
|
if neuer_status not in erlaubte:
|
|
|
|
|
flash("Ungueltiger Status.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
conn = get_db()
|
|
|
|
|
# Pruefe ob Lektion existiert + onboarding ist (nicht jede Lektion soll selbst-zertifizierbar sein)
|
|
|
|
|
lektion = conn.execute(
|
|
|
|
|
"SELECT nummer FROM lektion WHERE nummer = ? AND aktiv = 1",
|
|
|
|
|
(nummer,)
|
|
|
|
|
).fetchone()
|
|
|
|
|
if not lektion:
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Lektion nicht gefunden.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
"INSERT INTO profil_lektion_status (profil_id, lektion_nummer, status) "
|
|
|
|
|
"VALUES (?, ?, ?) "
|
|
|
|
|
"ON CONFLICT(profil_id, lektion_nummer) DO UPDATE SET "
|
|
|
|
|
" status = excluded.status, geaendert_am = CURRENT_TIMESTAMP",
|
|
|
|
|
(session["profil_id"], nummer, neuer_status)
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
if neuer_status == "fertig":
|
|
|
|
|
flash(f"L{nummer} als fertig markiert. 👍", "success")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
# Paarung (E-002): anfragen + bestaetigen + ablehnen + aufloesen
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
#
|
|
|
|
|
# Mechanik:
|
|
|
|
|
# - Anfrage wird als profil_anfrage-Eintrag gespeichert (mit Status 'wartet').
|
|
|
|
|
# - Adressat sieht im Cockpit ein gelbes Banner "Mia moechte mit dir zusammenarbeiten — [Ja] [Nein]".
|
|
|
|
|
# - Bei [Ja]: paarung-Eintrag wird angelegt (UNIQUE-Constraint verhindert Doppel-Paarungen).
|
|
|
|
|
# - Bei [Nein]: profil_anfrage geht auf 'abgelehnt'.
|
|
|
|
|
# - Bei Aufloesung: paarung.aktiv = 0.
|
|
|
|
|
#
|
|
|
|
|
# Tabelle profil_anfrage wird hier on-demand angelegt, weil wir das nicht
|
|
|
|
|
# initial im Schema hatten. Das ist OK fuer Etappe 2 — falls die Paarung
|
|
|
|
|
# spaeter komplexer wird, migrieren wir.
|
|
|
|
|
|
|
|
|
|
def _ensure_anfrage_tabelle():
|
|
|
|
|
"""Idempotent — legt profil_anfrage an, falls noch nicht da."""
|
|
|
|
|
conn = get_db()
|
|
|
|
|
conn.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS profil_anfrage (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
von_profil_id INTEGER NOT NULL,
|
|
|
|
|
an_profil_id INTEGER NOT NULL,
|
|
|
|
|
status TEXT DEFAULT 'wartet',
|
|
|
|
|
erstellt_am DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
beantwortet_am DATETIME,
|
|
|
|
|
FOREIGN KEY (von_profil_id) REFERENCES profil(id) ON DELETE CASCADE,
|
|
|
|
|
FOREIGN KEY (an_profil_id) REFERENCES profil(id) ON DELETE CASCADE
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ensure_anfrage_tabelle()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit/paarung/anfragen/<int:andere_profil_id>", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def paarung_anfragen(andere_profil_id):
|
|
|
|
|
von = session["profil_id"]
|
|
|
|
|
if von == andere_profil_id:
|
|
|
|
|
flash("Du kannst dich nicht mit dir selbst paaren.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
conn = get_db()
|
|
|
|
|
|
|
|
|
|
# Pruefen: bin ich oder die andere Person schon in einer aktiven Paarung?
|
|
|
|
|
schon_gepaart = conn.execute(
|
|
|
|
|
"SELECT id FROM paarung WHERE aktiv = 1 AND ? IN (profil_a, profil_b)",
|
|
|
|
|
(von,)
|
|
|
|
|
).fetchone()
|
|
|
|
|
if schon_gepaart:
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Du bist schon in einer aktiven Paarung — loese sie erst auf.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
andere_gepaart = conn.execute(
|
|
|
|
|
"SELECT id FROM paarung WHERE aktiv = 1 AND ? IN (profil_a, profil_b)",
|
|
|
|
|
(andere_profil_id,)
|
|
|
|
|
).fetchone()
|
|
|
|
|
if andere_gepaart:
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Die andere Person ist schon in einer Paarung.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
# Bereits offene Anfrage in die Richtung?
|
|
|
|
|
schon_angefragt = conn.execute(
|
|
|
|
|
"SELECT id FROM profil_anfrage WHERE status = 'wartet' "
|
|
|
|
|
"AND ((von_profil_id = ? AND an_profil_id = ?) OR (von_profil_id = ? AND an_profil_id = ?))",
|
|
|
|
|
(von, andere_profil_id, andere_profil_id, von)
|
|
|
|
|
).fetchone()
|
|
|
|
|
if schon_angefragt:
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Es laeuft schon eine Anfrage zwischen euch.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
"INSERT INTO profil_anfrage (von_profil_id, an_profil_id) VALUES (?, ?)",
|
|
|
|
|
(von, andere_profil_id)
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Anfrage geschickt. Die andere Person muss sie bestaetigen.", "success")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit/paarung/anfrage/<int:anfrage_id>/<aktion>", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def paarung_anfrage_beantworten(anfrage_id, aktion):
|
|
|
|
|
if aktion not in ("annehmen", "ablehnen"):
|
|
|
|
|
abort(400)
|
|
|
|
|
|
|
|
|
|
conn = get_db()
|
|
|
|
|
anfrage = conn.execute(
|
|
|
|
|
"SELECT id, von_profil_id, an_profil_id, status FROM profil_anfrage WHERE id = ?",
|
|
|
|
|
(anfrage_id,)
|
|
|
|
|
).fetchone()
|
|
|
|
|
if not anfrage or anfrage["an_profil_id"] != session["profil_id"] or anfrage["status"] != "wartet":
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Anfrage nicht gefunden oder schon beantwortet.", "error")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
if aktion == "annehmen":
|
|
|
|
|
a, b = sorted([anfrage["von_profil_id"], anfrage["an_profil_id"]])
|
|
|
|
|
conn.execute(
|
|
|
|
|
"INSERT INTO paarung (profil_a, profil_b, aktiv) VALUES (?, ?, 1)",
|
|
|
|
|
(a, b)
|
|
|
|
|
)
|
|
|
|
|
flash("Paarung gebildet — viel Erfolg zusammen!", "success")
|
|
|
|
|
else:
|
|
|
|
|
flash("Anfrage abgelehnt.", "success")
|
|
|
|
|
|
|
|
|
|
conn.execute(
|
|
|
|
|
"UPDATE profil_anfrage SET status = ?, beantwortet_am = CURRENT_TIMESTAMP WHERE id = ?",
|
|
|
|
|
("angenommen" if aktion == "annehmen" else "abgelehnt", anfrage_id)
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit/paarung/aufloesen", methods=["POST"])
|
|
|
|
|
@login_required
|
|
|
|
|
def paarung_aufloesen():
|
|
|
|
|
conn = get_db()
|
|
|
|
|
conn.execute(
|
|
|
|
|
"UPDATE paarung SET aktiv = 0 WHERE aktiv = 1 AND ? IN (profil_a, profil_b)",
|
|
|
|
|
(session["profil_id"],)
|
|
|
|
|
)
|
|
|
|
|
conn.commit()
|
|
|
|
|
conn.close()
|
|
|
|
|
flash("Paarung aufgeloest.", "success")
|
|
|
|
|
return redirect(url_for("profil.cockpit"))
|
|
|
|
|
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
2026-05-24 19:13:19 +02:00
|
|
|
# ===========================================================================
|
|
|
|
|
# Stubs fuer spaetere Etappen
|
|
|
|
|
# ===========================================================================
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
|
|
|
|
@bp.route("/cockpit/slots")
|
|
|
|
|
@login_required
|
|
|
|
|
def slots():
|
2026-05-24 19:13:19 +02:00
|
|
|
abort(501) # Etappe 6/7
|
Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).
Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md
Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)
Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/cockpit/druckauftraege")
|
|
|
|
|
@login_required
|
|
|
|
|
def druckauftraege():
|
2026-05-24 19:13:19 +02:00
|
|
|
abort(501) # Etappe 7
|