Software-Sektion + Drucker-Verwaltung + Slot-System + Selbstlern-Loop

Vier zusammenhaengende Iterationen, die das Funktions-Geruest der AG aufbauen.
Alle 6 Migrationen sind idempotent und legen Schema-Erweiterungen + initiale
Seeds an (Mock-Projekte nur, falls Profil 100 existiert — auf prod nicht).

Software-Sektion (Etappe 3):
  - software_seite-Tabelle: schlanker Karten-Katalog (slug, titel, urls,
    plattform, kategorie, sortierung, Cover-BLOB)
  - 7 Initial-Karten (Bambu Studio/Handy, Printables, MakerWorld,
    TinkerCAD, Onshape, Gridfinity-Generator)
  - Admin-Verwaltung: Liste, Anlegen-Form, Bearbeiten, Aktiv-Toggle,
    Hart-Loeschen, Bild-Upload via Crop-Tool (Strg+V/Drag&Drop, 400x400)

Drucker-Verwaltung (Etappe 5-vorgezogen):
  - drucker.freigegeben + gesperrt_grund (Lehrer-Sperre fuer Reparatur)
  - drucker.manual_url + troubleshooting_url (Override fuer Modell-Defaults)
  - SuS-View /drucker (eingeloggt): Kacheln + Sperre-Banner + Belegung
  - Admin /admin/drucker: Status-Override (idle/printing/failed/...),
    Sperren/Freigeben mit Grund, Inline-Edit fuer URLs

Slot-System / Reservierung (Etappe 7-vorgezogen):
  - profil.reservieren_freigeschaltet (Lehrer schaltet manuell frei,
    ersetzt L1-Gate-Automatismus)
  - services/slots.py: Konflikt-Check, Belegungs-Helper
  - SuS-Routen /cockpit/slot/neu (mit Konflikt-Check), /cockpit/slots,
    Stornieren
  - Admin /admin/slots Uebersicht + /admin/slot/neu (Lehrer reserviert
    fuer SuS) + Hart-Loeschen + Profil-Freigabe-Toggle

Selbstlern-Loop (Etappe 6 — Kern):
  - projekt-Spalten: 3-Achsen-Eval (Gesamt + Planung + Ausfuehrung),
    was_klappte_nicht, cover_blob, modellier_software_slug,
    drucker_id_used, makerworld_url
  - Regel: max. 1 aktives Projekt pro SuS, neues nur nach Freigabe
    (auto bei zufrieden/mittel, Lehrer-Review bei gelernt)
  - SuS-Werkstatt-Sektion: Titel + Beschreibung + Software-Dropdown +
    Drucker-Dropdown + MakerWorld-URL + Files-Upload (drag&drop,
    base64, max 30 MB)
  - Cover-Bild via Crop-Tool (Re-use admin_software_bild-Pattern)
  - Abschluss-Block: Pflicht Cover + mindestens 1 Datei
  - Eval-Form: visuelle 3x3 Radio-Karten + 2 Freitexte
  - Lehrer-Review: /admin/projekte mit Filter (wartet/in_arbeit/
    abgeschlossen/rueckfrage), Aktionen freigeben/rueckfrage/loeschen
  - Oeffentlicher Katalog /projekte: Sortier-Tabelle (Titel/Person/
    Status/Erfolg/Datum), aufklappbare Detail mit Cover/Beschreibung/
    Datei-Downloads/MakerWorld-Link
  - Wiederhol-Logik: "Sowas mache ich auch" via Verknuepfung
    (vorlage_projekt_id), bidirektionale Lineage-Banner

Cockpit-Refactoring:
  - Projekt-Karte ganz oben (vor Onboarding) mit "Hier weitermachen"
  - Check-In-Quick-Actions: nach Auswahl direkt zu /cockpit/projekt/neu,
    /drucker, /lektionen, /cockpit/projekt/<aktiv>
  - "Modus aendern"-Button im Eingecheckt-Banner
  - Admin-Dashboard-Hub mit Karten: SuS-Profile, Software, Lektionen,
    Drucker, Reservierungen, Projekte (Badge bei wartenden), Alph

Bug-Fixes:
  - Admin-Login redirected jetzt auf /admin/dashboard statt /admin/profile
  - app.py: neue Jinja-Filter iso_format + dauer_min
  - .gitignore: .claude/ ausschliessen (lokale launch.json)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 19:04:18 +02:00
parent 66f6dd96dc
commit 8cbd803328
40 changed files with 5721 additions and 55 deletions

View File

@@ -45,6 +45,10 @@ CREATE TABLE IF NOT EXISTS profil (
pin_hash TEXT NOT NULL, -- bcrypt
ag_id TEXT NOT NULL, -- FK ag_mitgliedschaft
aktiv INTEGER DEFAULT 1,
-- Lehrer schaltet SuS manuell zur Drucker-Reservierung frei (ersetzt
-- den geplanten L1-Gate-Automatismus, weil manche SuS zuhause schon
-- drucken oder schneller durch L1 sind als die Doku festhalten kann).
reservieren_freigeschaltet INTEGER DEFAULT 0,
erstellt_am DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(ag_id, vorname, tier),
FOREIGN KEY (ag_id) REFERENCES ag_mitgliedschaft(id)
@@ -99,8 +103,17 @@ CREATE TABLE IF NOT EXISTS projekt (
-- Lebenszyklus
status_lebenszyklus TEXT DEFAULT 'in_arbeit', -- 'in_arbeit'|'abgeschlossen'
abgeschlossen_am DATETIME,
selbsteinschaetzung TEXT, -- 'zufrieden'|'mittel'|'gelernt' (E-015)
was_gelernt TEXT, -- optionaler Freitext
selbsteinschaetzung TEXT, -- 'zufrieden'|'mittel'|'gelernt' (E-015) — Gesamt
selbsteinschaetzung_planung TEXT, -- 'gut'|'ok'|'schwierig' — wie war die Planung?
selbsteinschaetzung_ausfuehrung TEXT, -- 'gut'|'ok'|'schwierig' — wie war die Umsetzung?
was_gelernt TEXT,
was_klappte_nicht TEXT, -- optionaler Freitext, hilft Lehrer beim Review
cover_blob BLOB, -- Cover-Foto (Crop-Tool, 400x400 JPEG)
cover_mime TEXT,
-- Werkstatt-Erfassung (Etappe 6 Phase D, mit Herb 2026-05-25)
modellier_software_slug TEXT, -- FK auf software_seite.slug (welche Hauptsoftware)
drucker_id_used INTEGER, -- FK auf drucker.id (welcher Drucker wurde benutzt)
makerworld_url TEXT, -- optional: SuS hat Projekt zusaetzlich auf MakerWorld veroeffentlicht -- optionaler Freitext
-- Freigabe-Workflow (E-017)
freigabe_status TEXT DEFAULT 'in_arbeit', -- 'in_arbeit'|'wartet_auf_freigabe'|'freigegeben'|'rueckfrage'
freigegeben_am DATETIME,
@@ -195,7 +208,14 @@ CREATE TABLE IF NOT EXISTS drucker (
serial_nr TEXT, -- fuer Cloud-API
geschlossenes_gehaeuse INTEGER DEFAULT 1, -- A1 mini = 0
aktiv INTEGER DEFAULT 1,
notiz TEXT
notiz TEXT,
-- Freigabe-Steuerung (Etappe 5-vorgezogen): Lehrer kann Drucker
-- voruebergehend von Reservierung ausschliessen (Reparatur, Wartung).
freigegeben INTEGER DEFAULT 1, -- 1 = SuS koennen reservieren, 0 = gesperrt
gesperrt_grund TEXT, -- nur relevant wenn freigegeben=0
-- Optional: Drucker-spezifische URL-Overrides ueber dem Modell-Default
manual_url TEXT,
troubleshooting_url TEXT
);
CREATE TABLE IF NOT EXISTS drucker_status (
@@ -264,6 +284,31 @@ CREATE TABLE IF NOT EXISTS lektion (
aktiv INTEGER DEFAULT 1
);
-- ===========================================================================
-- Software-Sektion (Etappe 3 — Karten mit Bild + Kurzbeschreibung + Links)
-- ===========================================================================
-- Wir halten uns absichtlich raus: SuS haben die Software ohnehin auf den
-- Schul-PCs / im Browser und machen eigene Erfahrungen. Wir geben nur die
-- Auswahl vor (Karten-Liste mit Hauptlink + Tutorial-Link, ggf. Store-Links
-- mit QR-Code). Keine Detail-Seite.
CREATE TABLE IF NOT EXISTS software_seite (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT UNIQUE NOT NULL, -- 'bambu-studio', 'gridfinity', ...
titel TEXT NOT NULL,
kurzbeschreibung TEXT NOT NULL, -- 1-2 Saetze, sichtbar auf der Karte
url TEXT NOT NULL, -- Hauptlink (Startseite / Download)
tutorial_url TEXT, -- optionaler deutscher Einstieg
plattform TEXT, -- Klartext: 'Browser', 'Windows/macOS/Linux', ...
app_store_url TEXT, -- nur bei Apps
play_store_url TEXT, -- nur bei Apps
bild_pfad TEXT, -- alt: relativ zu static/img/software/, optional Fallback
bild_blob BLOB, -- per Crop-Tool hochgeladen (Default-Quelle)
bild_mime TEXT, -- z.B. 'image/jpeg'
kategorie TEXT NOT NULL DEFAULT 'software', -- 'software'|'app'|'generator'
sortierung INTEGER DEFAULT 100,
aktiv INTEGER DEFAULT 1
);
-- ===========================================================================
-- Einstellungen (Inline-Edit-Konfig) + Audit-Log
-- ===========================================================================