.LocalDeveloperTools) und sind nicht auf dem Server.Eine Lizenz = ein Sitzplatz für eine:n Schüler:in in einem Schuljahr. Der Admin erzeugt einen Vorrat an Codes, eine Lehrperson löst Codes ein (sie werden ihrem Konto zugeordnet) und weist sie dann einzelnen Schüler:innen zu. Alles steht in einer Tabelle licenses — die drei Zustände ergeben sich allein aus zwei Feldern: teacher_id und student_id.
| Spalte | Typ | Bedeutung |
|---|---|---|
| id | INT · PK | Interne ID |
| code | VARCHAR · UNIQUE | Der Lizenzcode, Format XXXX-XXXX-XXXX-JAHR |
| school_year | VARCHAR | Schuljahr, z. B. „26/27" — aus dem Jahr abgeleitet |
| teacher_id | FK → teachers | Einlösende Lehrperson · NULL = noch im Pool |
| student_id | FK → students | Platz-Inhaber:in · NULL = noch frei |
| redeemed_at | TIMESTAMP · NULL | Zeitpunkt des Einlösens durch die Lehrperson |
| created_at | TIMESTAMP | Erstellung (Admin-Generierung) |
teacher_id = NULL · student_id = NULL. Frisch erzeugter Code im Pool.generateteacher_id gesetzt · redeemed_at = jetzt · student_id noch NULL. Code gehört nun der Lehrperson.redeem / redeem_batchstudent_id gesetzt. Der Platz ist von einer konkreten Person belegt.assign / auto_assignlicenses.teacher_id merkt sich die einlösende Lehrperson, licenses.student_id den Platz-Inhaber. Über students.class_id → classes.teacher_id hängt jede:r Schüler:in ohnehin an einer Klasse einer Lehrperson — der direkte teacher_id-Eintrag macht aber auch eingelöste, noch nicht zugewiesene Codes eindeutig einer Lehrperson zuordenbar.