| type |
status |
owner |
last_update |
sprint |
| BACKEND_SPEC |
DRAFT |
Rulebook Expert |
2026-04-03 |
B-2 |
B-2 Backend-Übergabe: Regulation-as-Data
Zweck: Vollständige Spezifikation der Lizenz-/Altersmatrix als Regulation-as-Data für das Backend (
Masterdata-SCS).
Dieses Dokument ist die verbindliche Übergabe vom 📜 Rulebook Expert an 👷 Backend Developer.
Nach Fachfreigabe durch das ÖTO-Fachreferat wird der Status von DRAFT auf STABLE angehoben.
1. Überblick: Was wird übergeben?
| Artefakt |
Datei / Ort |
Status |
LizenzKlasseE-Enum (korrigiert, R4 ergänzt) |
core/core-domain/.../Enums.kt |
✅ Implementiert |
| Flyway V008 (Turnierklassen + Lizenz-Matrix + Altersklassen Reiter) |
masterdata-service/.../V008__Seed_OETO_2026_Data.sql |
✅ Korrigiert (RD4 entfernt) |
| Flyway V009 (Höhen-Lizenz-Matrix + Mindestalter-Pferd-Matrix) |
masterdata-service/.../V009__Add_HorseAge_And_LicenseHeight_Matrix.sql |
✅ Neu angelegt |
| Validierungsregeln v0.3 |
docs/03_Domain/02_Reference/Validierungsregeln.md |
DRAFT |
| Diese Spezifikation |
docs/.../B2-Backend-Uebergabe-Regulation-as-Data.md |
DRAFT |
2. Enum-Korrekturen (core-domain)
2.1 LizenzKlasseE — Vollständiger Katalog
enum class LizenzKlasseE {
LIZENZFREI, // Keine Lizenz erforderlich (= "ohne Lizenz", CSN-C-NEU)
R1, // Reiter-Lizenz Klasse 1
R2, // Reiter-Lizenz Klasse 2
R3, // Reiter-Lizenz Klasse 3
R4, // Reiter-Lizenz Klasse 4 ← NEU ergänzt (war fehlend)
RD1, // Dressur-Reiter Klasse 1
RD2, // Dressur-Reiter Klasse 2
RD3, // Dressur-Reiter Klasse 3
JN, // Jugend/Nachwuchs
JG, // Junioren
YR // Young Rider
}
⚠️ Wichtig: RD4 existiert nicht im ÖTO-Regelwerk. Der bisherige Seed V008 enthielt RD4 fälschlicherweise —
wurde in V008 korrigiert (entfernt). Höchste Dressur-Lizenz ist RD3.
2.2 Schlüssel-Konvention (SSoT)
| Doku-Label |
Enum-Key (SSoT) |
Hinweis |
| „ohne Lizenz" / „lizenzfrei" |
LIZENZFREI |
Nicht LZF — Enum ist maßgeblich |
| „mit Lizenz" / „R1" |
R1 |
|
| „R2 und höher" |
R2, R3, R4 |
Aufwärts-kompatibel |
3. Datenbank-Tabellen (Regulation-as-Data)
3.1 Bestehende Tabellen (V005/V008)
| Tabelle |
Zweck |
turnierklasse |
Klassen-Codes (E, A, L, LM, M, S) je Sparte mit max_hoehe |
license_matrix |
Max. Turnierklasse je Lizenz (1 Zeile pro Lizenz × Sparte) |
altersklasse |
Altersklassen der Reiter (Kinder, Jugend, Junioren, YR, AK, Senioren) |
3.2 Neue Tabellen (V009)
license_height_matrix
Granulare Höhen-Lizenz-Zuordnung für Springen (eine Zeile pro Höhenbereich × erlaubte Lizenz).
-- Abfrage: Welche Lizenzen sind für 110 cm erlaubt?
SELECT lizenz_klasse
FROM license_height_matrix
WHERE sparte = 'SPRINGEN'
AND hoehe_von_cm <= 110
AND hoehe_bis_cm >= 110
AND ist_aktiv = true;
-- Ergebnis: R1, R2, R3, R4
horse_min_age_matrix
Mindestalter des Pferdes (Stichtag 1. Jänner) je Sparte + Höhenbereich oder Aufgabenniveau.
-- Abfrage: Mindestalter für Springen 125 cm?
SELECT min_alter_jahre
FROM horse_min_age_matrix
WHERE sparte = 'SPRINGEN'
AND hoehe_von_cm <= 125
AND hoehe_bis_cm >= 125
AND ist_aktiv = true;
-- Ergebnis: 5
4. Lizenz × Bewerb-Tabellen (DRAFT → Fachfreigabe erforderlich)
4.1 Springen (CSN) — Lizenz-Zuordnung nach Hindernishöhe
Quelle: ÖTO 2026 § 231 | Status: DRAFT — Fachfreigabe ausstehend
| Klasse |
Höhe (cm) |
Mindest-Lizenz |
Zugelassene Lizenzen |
Bemerkung |
| E0 (Einsteiger) |
60–95 |
LIZENZFREI |
LIZENZFREI, R1, R2, R3, R4 |
CSN-C-NEU: Zwangsteilung in Abt. „ohne Lizenz" + „mit Lizenz" |
| A (Anfänger) |
100–110 |
R1 |
R1, R2, R3, R4 |
Keine LIZENZFREI mehr ab 100 cm |
| L (Leicht) |
115–120 |
R1* |
R1, R2, R3, R4 |
*Ausschreibung kann R2 vorschreiben |
| LM (Leicht-Mittel) |
125–130 |
R2 |
R2, R3, R4 |
|
| M (Mittelschwer) |
135 |
R3 |
R3, R4 |
|
| S (Schwer) |
140–160 |
R4 |
R4 |
|
Aufwärts-Kompatibilität: Eine höhere Lizenz berechtigt immer zur Teilnahme in niedrigeren Klassen.
4.2 Dressur (CDN) — Lizenz-Zuordnung nach Aufgabenniveau
Quelle: ÖTO 2026 § 103 | Status: DRAFT — Fachfreigabe ausstehend
| Klasse |
Aufgabenniveau |
Mindest-Lizenz |
Zugelassene Lizenzen |
| Einsteiger |
E |
LIZENZFREI |
LIZENZFREI, RD1, RD2, RD3 |
| A (Anfänger) |
A |
RD1 |
RD1, RD2, RD3 |
| L (Leicht) |
L |
RD1 |
RD1, RD2, RD3 |
| LM (Leicht-Mittel) |
LM |
RD2 |
RD2, RD3 |
| M (Mittelschwer) |
M |
RD2 |
RD2, RD3 |
| S (Schwer) |
S |
RD3 |
RD3 |
5. Mindestalter Pferd (Regulation-as-Data)
Stichtagsregel: Alter = veranstaltungsjahr - geburtsjahr (Stichtag 1. Jänner)
5.1 Springen national (ÖTO § 231)
| Höhe (cm) |
Mindestalter Pferd (Jahre) |
| 60–100 |
4 |
| 101–120 |
5 |
| 121–999 |
6 |
5.2 Dressur national (ÖTO § 103)
| Aufgabenniveau |
Mindestalter Pferd (Jahre) |
| E |
4 |
| A |
4 |
| L |
4 |
| LM |
5 |
| M |
5 |
| S |
6 |
5.3 International FEI (GR Art. 136)
| Disziplin |
Level |
Mindestalter Pferd |
| Springen |
1*–2* |
6 |
| Springen |
3*–5* |
7 |
| Dressur |
CDI Senior |
7 |
| Dressur |
CDI Young Horse |
4 (gem. FEI YH-Regeln) |
6. Serverseitige Validierungslogik (Pseudocode)
Das Backend soll die folgenden Prüfungen serverseitig durchführen (analog zur Frontend-Validierung):
6.1 Lizenz-Check (Springen)
fun isLicenseAllowedForHeight(hoeheCm: Int, lizenz: LizenzKlasseE): Boolean {
// Abfrage license_height_matrix
val allowed = licenseHeightMatrixRepo.findAllowedLicenses(
sparte = "SPRINGEN",
hoehe = hoeheCm
)
return lizenz.name in allowed
}
6.2 Lizenz-Check (Dressur)
fun isLicenseAllowedForLevel(niveau: String, lizenz: LizenzKlasseE): Boolean {
// Abfrage license_matrix (max_turnierklasse_code Vergleich)
val maxKlasse = licenseMatrixRepo.findMaxKlasse(sparte = "DRESSUR", lizenz = lizenz.name)
return klasseOrdnung.indexOf(niveau) <= klasseOrdnung.indexOf(maxKlasse)
}
6.3 Mindestalter-Pferd-Check
fun isHorseOldEnough(
geburtsjahr: Int, veranstaltungsjahr: Int,
sparte: String, hoeheCm: Int?, niveau: String?
): Boolean {
val alter = veranstaltungsjahr - geburtsjahr // Stichtag 1. Jänner
val minAlter = horseMinAgeRepo.findMinAlter(sparte, hoeheCm, niveau)
return alter >= minAlter
}
7. REST-Endpunkte (Masterdata-SCS) — Empfehlung
| Methode |
Pfad |
Beschreibung |
GET |
/api/regulation/license-height-matrix?sparte=SPRINGEN&hoehe=110 |
Erlaubte Lizenzen für Höhe |
GET |
/api/regulation/license-matrix?sparte=DRESSUR&lizenz=RD2 |
Max. Klasse für Lizenz |
GET |
/api/regulation/horse-min-age?sparte=SPRINGEN&hoehe=125 |
Mindestalter Pferd |
GET |
/api/regulation/horse-min-age?sparte=DRESSUR&niveau=LM |
Mindestalter Pferd (Dressur) |
GET |
/api/fei/resolve/{id} |
FEI Legacy→Numeric Resolver (bereits implementiert ✅) |
8. Abweichungen Backend ↔ Frontend
| Thema |
Frontend (KMP) |
Backend (Spring) |
Handlungsbedarf |
| Lizenz-Keys |
LZF (alter Key in Doku) |
LIZENZFREI (Enum) |
Doku korrigiert; Frontend-Code prüfen |
| R4 |
Vorhanden in OetoValidators |
Enum jetzt ergänzt ✅ |
Kein weiterer Bedarf |
| RD4 |
Nicht vorhanden |
Seed V008 korrigiert ✅ |
Kein weiterer Bedarf |
| Höhen-Matrix |
OetoValidators.kt (hardcoded) |
V009 als DB-Tabelle |
Backend liest aus DB; Frontend bleibt hardcoded bis Phase 2 |
| Mindestalter Pferd |
OetoValidators.kt (hardcoded) |
V009 als DB-Tabelle |
Wie oben |
9. Fachfreigabe-Checkliste (DRAFT → STABLE)
Folgende Punkte müssen vor Anhebung auf STABLE durch das ÖTO-Fachreferat bestätigt werden:
Nach Bestätigung aller Punkte:
- Status in dieser Datei auf
STABLE setzen
Validierungsregeln.md → status: STABLE, version: 1.0
- Flyway V009 → Kommentar
Status: DRAFT entfernen
- Roadmap B-2 als abgeschlossen markieren
10. Offene Punkte
| # |
Thema |
Verantwortlich |
Priorität |
| 1 |
Fachfreigabe Lizenz×Bewerb-Tabellen einholen |
📜 Rulebook Expert |
🔴 Hoch |
| 2 |
Backend-Endpunkte /api/regulation/* implementieren |
👷 Backend |
🔴 Hoch |
| 3 |
Frontend LZF-Key → LIZENZFREI prüfen/angleichen |
🎨 Frontend |
🟠 Mittel |
| 4 |
AltersklasseRechner (C-1) implementieren |
👷 Backend + 📜 Rulebook |
🟠 Mittel |
| 5 |
FEI-Mindestalter-Tabellen aus Disziplinregelwerken finalisieren |
📜 Rulebook Expert |
🟡 Niedrig |