Files
breakpilot-lehrer/backend-lehrer/classroom_engine/context_models.py
Benjamin Boenisch 5a31f52310 Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website,
Klausur-Service, School-Service, Voice-Service, Geo-Service,
BreakPilot Drive, Agent-Core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:47:26 +01:00

292 lines
9.0 KiB
Python

"""
SQLAlchemy Database Models fuer Schuljahres-Kontext (Phase 8).
Erweitert das Companion-Modul um ein 2-Schichten-Modell:
- Makro-Ebene: 7 Schuljahres-Phasen (langsam wechselnd)
- Mikro-Ebene: Events, Routinen, Arbeitsmodi (tagesaktuell)
"""
from datetime import datetime, time
from sqlalchemy import (
Column, String, Integer, DateTime, JSON,
Boolean, Text, Enum as SQLEnum, Time
)
import enum
import uuid
from .database import Base
# Exports
__all__ = [
"MacroPhaseEnum",
"EventTypeEnum",
"EventStatusEnum",
"RoutineTypeEnum",
"RecurrencePatternEnum",
"TeacherContextDB",
"SchoolyearEventDB",
"RecurringRoutineDB",
"FEDERAL_STATES",
"SCHOOL_TYPES",
]
# ==================== Konstanten ====================
FEDERAL_STATES = {
"BW": "Baden-Wuerttemberg",
"BY": "Bayern",
"BE": "Berlin",
"BB": "Brandenburg",
"HB": "Bremen",
"HH": "Hamburg",
"HE": "Hessen",
"MV": "Mecklenburg-Vorpommern",
"NI": "Niedersachsen",
"NW": "Nordrhein-Westfalen",
"RP": "Rheinland-Pfalz",
"SL": "Saarland",
"SN": "Sachsen",
"ST": "Sachsen-Anhalt",
"SH": "Schleswig-Holstein",
"TH": "Thueringen",
}
SCHOOL_TYPES = {
"grundschule": "Grundschule",
"hauptschule": "Hauptschule",
"realschule": "Realschule",
"gymnasium": "Gymnasium",
"gesamtschule": "Gesamtschule",
"foerderschule": "Foerderschule",
"berufsschule": "Berufsschule",
"gemeinschaftsschule": "Gemeinschaftsschule",
}
# ==================== Enums ====================
class MacroPhaseEnum(str, enum.Enum):
"""
7 Schuljahres-Phasen (Makro-State).
Wechselt alle paar Wochen basierend auf Schulkalender und Nutzungsverhalten.
"""
ONBOARDING = "onboarding" # Ersteinrichtung (Klassen, Stundenplan)
SCHULJAHRESSTART = "schuljahresstart" # Erste 2-3 Wochen
UNTERRICHTSAUFBAU = "unterrichtsaufbau" # Routinen etablieren
LEISTUNGSPHASE_1 = "leistungsphase_1" # Erste Klausuren
HALBJAHRESABSCHLUSS = "halbjahresabschluss" # Notenschluss, Zeugnisse
LEISTUNGSPHASE_2 = "leistungsphase_2" # Pruefungsvorbereitung
JAHRESABSCHLUSS = "jahresabschluss" # Finale Noten, Versetzung
class EventTypeEnum(str, enum.Enum):
"""Event-Typen fuer Schuljahr-Events."""
EXAM = "exam" # Klassenarbeit, Klausur
PARENT_EVENING = "parent_evening" # Elternabend
TRIP = "trip" # Klassenfahrt, Ausflug
PROJECT = "project" # Projektwoche
INTERNSHIP = "internship" # Praktikum
PRESENTATION = "presentation" # Referate, Praesentationen
SPORTS_DAY = "sports_day" # Sporttag, Bundesjugendspiele
SCHOOL_FESTIVAL = "school_festival" # Schulfest
PARENT_CONSULTATION = "parent_consultation" # Elternsprechtag
GRADE_DEADLINE = "grade_deadline" # Notenschluss
REPORT_CARDS = "report_cards" # Zeugnisausgabe
HOLIDAY_START = "holiday_start" # Ferienbeginn
HOLIDAY_END = "holiday_end" # Ferienende
OTHER = "other"
class EventStatusEnum(str, enum.Enum):
"""Status eines Events."""
PLANNED = "planned"
IN_PROGRESS = "in_progress"
DONE = "done"
CANCELLED = "cancelled"
class RoutineTypeEnum(str, enum.Enum):
"""Typen wiederkehrender Routinen."""
TEACHER_CONFERENCE = "teacher_conference" # Lehrerkonferenz
SUBJECT_CONFERENCE = "subject_conference" # Fachkonferenz
OFFICE_HOURS = "office_hours" # Sprechstunde
TEAM_MEETING = "team_meeting" # Teamsitzung
SUPERVISION = "supervision" # Pausenaufsicht
CORRECTION_TIME = "correction_time" # Korrekturzeit
PREP_TIME = "prep_time" # Vorbereitungszeit
OTHER = "other"
class RecurrencePatternEnum(str, enum.Enum):
"""Wiederholungsmuster fuer Routinen."""
DAILY = "daily"
WEEKLY = "weekly"
BIWEEKLY = "biweekly"
MONTHLY = "monthly"
# ==================== Models ====================
class TeacherContextDB(Base):
"""
Lehrer-Kontext fuer Schuljahres-Begleitung (Phase 8).
Speichert den Makro-Kontext eines Lehrers:
- Bundesland (fuer Schulkalender/Ferien)
- Schulart
- Aktuelles Schuljahr
- Aktuelle Makro-Phase
Ein Lehrer hat genau einen Context-Eintrag.
"""
__tablename__ = 'teacher_contexts'
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
teacher_id = Column(String(100), unique=True, nullable=False, index=True)
# Schul-Kontext
federal_state = Column(String(10), default="BY") # BY, NRW, etc.
school_type = Column(String(50), default="gymnasium") # gymnasium, realschule, etc.
# Schuljahr
schoolyear = Column(String(20), default="2024-2025") # z.B. "2024-2025"
schoolyear_start = Column(DateTime, nullable=True) # Erster Schultag
# Aktueller Stand (Makro-Phase)
macro_phase = Column(
SQLEnum(MacroPhaseEnum),
default=MacroPhaseEnum.ONBOARDING,
nullable=False
)
current_week = Column(Integer, default=1) # Schulwoche 1-52
# Berechnete Flags (werden beim Abrufen aktualisiert)
is_exam_period = Column(Boolean, default=False)
is_before_holidays = Column(Boolean, default=False)
# Onboarding-Status
onboarding_completed = Column(Boolean, default=False)
has_classes = Column(Boolean, default=False)
has_schedule = Column(Boolean, default=False)
# Metadaten
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<TeacherContext {self.teacher_id} ({self.macro_phase.value})>"
class SchoolyearEventDB(Base):
"""
Schuljahr-Event (Phase 8).
Ein einmaliges Event im Schuljahr wie:
- Klassenarbeit
- Elternabend
- Klassenfahrt
- Projektwoche
Events haben einen Zeitraum und optionale Klassen-/Fach-Zuordnung.
"""
__tablename__ = 'schoolyear_events'
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
teacher_id = Column(String(100), nullable=False, index=True)
# Event-Typ und Titel
event_type = Column(
SQLEnum(EventTypeEnum),
default=EventTypeEnum.OTHER,
nullable=False
)
title = Column(String(300), nullable=False)
description = Column(Text, default="")
# Zeitraum
start_date = Column(DateTime, nullable=False, index=True)
end_date = Column(DateTime, nullable=True) # Null = eintaegiges Event
# Optionale Zuordnung
class_id = Column(String(100), nullable=True, index=True)
subject = Column(String(100), nullable=True)
# Status
status = Column(
SQLEnum(EventStatusEnum),
default=EventStatusEnum.PLANNED,
nullable=False,
index=True
)
# Flags fuer Antizipation
needs_preparation = Column(Boolean, default=True) # Braucht Vorbereitung?
preparation_done = Column(Boolean, default=False) # Vorbereitung erledigt?
reminder_days_before = Column(Integer, default=7) # Tage vorher erinnern
# Flexible Zusatzdaten (z.B. Rubric-ID fuer Klausur)
extra_data = Column(JSON, default=dict) # Renamed from 'metadata' which is reserved in SQLAlchemy
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<SchoolyearEvent {self.title} ({self.event_type.value})>"
class RecurringRoutineDB(Base):
"""
Wiederkehrende Routine (Phase 8).
Eine regelmaessig wiederkehrende Aktivitaet wie:
- Lehrerkonferenz (woechentlich/monatlich)
- Fachkonferenz
- Sprechstunde
- Korrekturzeit
Routinen wiederholen sich nach einem bestimmten Muster.
"""
__tablename__ = 'recurring_routines'
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
teacher_id = Column(String(100), nullable=False, index=True)
# Routine-Typ und Titel
routine_type = Column(
SQLEnum(RoutineTypeEnum),
default=RoutineTypeEnum.OTHER,
nullable=False
)
title = Column(String(300), nullable=False)
description = Column(Text, default="")
# Wiederholung
recurrence_pattern = Column(
SQLEnum(RecurrencePatternEnum),
default=RecurrencePatternEnum.WEEKLY,
nullable=False
)
day_of_week = Column(Integer, nullable=True) # 0=Mo, 6=So (Null wenn daily/monthly)
day_of_month = Column(Integer, nullable=True) # 1-31 fuer monthly
time_of_day = Column(Time, nullable=True) # z.B. 14:00
# Dauer in Minuten
duration_minutes = Column(Integer, default=60)
# Aktiv?
is_active = Column(Boolean, default=True)
# Startdatum (ab wann gilt die Routine?)
valid_from = Column(DateTime, nullable=True)
valid_until = Column(DateTime, nullable=True)
# Metadaten
extra_data = Column(JSON, default=dict) # Renamed from 'metadata' which is reserved in SQLAlchemy
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<RecurringRoutine {self.title} ({self.recurrence_pattern.value})>"