Document and implement CSN-C-NEU mandatory division rules: Add TURNIER_KLASSEN.md detailing forced divisions by license categories; establish uniform labels and keys (e.g., LZF_ONLY and R1_PLUS); draft optional youth division rules. Extend validation in Validierungsregeln.md. Implement FEI-ID resolver and mapping endpoint in Masterdata service.

This commit is contained in:
2026-04-02 18:36:59 +02:00
parent bbe5b1a357
commit 4ae701d969
8 changed files with 540 additions and 25 deletions
@@ -86,14 +86,212 @@ fun validateOepsId(input: String): Boolean {
---
## 2. FEIID
ToDo: Wird in A1 (weiterer Unterpunkt) spezifiziert.
Status: Draft auf Basis FEI General Regulations (Art. 113114) und vorhandener Systemdaten. Endgültige Bestätigung via FEI Lookup/API steht aus.
### 2.1 Zweck
- Eindeutige Identifikation international registrierter Athlet:innen und Pferde bei FEIrelevanten Bewerben/Kategorien (CI/CIO/CSI/CDI/CCI etc.).
### 2.2 Gültige Formate (Eingabe)
- Primär (numerisch, aktuell üblich):
- Regex: `^[0-9]{7,8}$`
Erläuterung: 78stellige numerische FEIIDs (z. B. `10011469`).
- Legacy/Referenzcode (in LegacyDaten sichtbar):
- Regex: `^[0-9]{3}[A-Z]{2}[0-9]{2}$`
Beispiel: `104FE22`. Diese Codes werden akzeptiert, aber bei Speicherung nach Möglichkeit gegen die numerische FEIID aufgelöst (siehe 2.5).
Nicht erlaubt:
- Leerzeichen, Trennzeichen, gemischte Schreibweisen mit Präfixen (z. B. `FEI-10011469`), alphanumerische Mischformen außerhalb des obigen LegacyMusters.
### 2.3 PflichtfelderRegel (Wann ist FEIID erforderlich?)
- International (FEIEvents: CI/CSI/CDI/CCI/CIO/CH/…):
- Athlet: FEIID Pflicht.
- Pferd: FEIID Pflicht (inkl. FEIPass/Microchip gem. FEIRegeln, vgl. Art. 114, 137 FEI GR).
- National (ÖTOEvents: CN/CSN/CDN/CCN):
- Athlet: FEIID optional (nur wenn FEIregistriert).
- Pferd: FEIID optional (nur wenn FEIregistriert).
- Ausnahme: Wenn eine nationale Prüfung als FEIqualifikationsrelevant ausgewiesen ist, kann FEIID für Datenexporte empfohlen/erforderlich sein (Veranstalterhinweis).
Hinweis: Die konkrete Pflicht koppeln wir im System an das Feld „Turnierkategorie“ und Disziplin, konfigurierbar per RegelSet.
### 2.4 Beispiele
- Gültig: `10011469`, `10019075`, `10028445`, `104FE22` (Legacy).
- Ungültig: `FEI10011469` (Präfix), `10011 469` (Leerzeichen), `10A11469` (Buchstabe in numerischem Format), `104F-E22` (Sonderzeichen).
### 2.5 Normalisierung (Speicherformat)
- Bevorzugtes Speicherformat: numerische FEIID (`[0-9]{7,8}`) als String ohne Trennzeichen.
- LegacyReferenzcode wird sofern möglich vor Speicherung via Mapping/Lookup in numerische FEIID überführt. Falls kein Mapping möglich, speichern als eingegeben plus `source_format = LEGACY_CODE`.
### 2.6 PseudocodeValidierung
```kotlin
fun validateFeiId(input: String): Boolean {
val s = input.trim().uppercase()
val numeric = Regex("^[0-9]{7,8}$")
val legacy = Regex("^[0-9]{3}[A-Z]{2}[0-9]{2}$")
return numeric.matches(s) || legacy.matches(s)
}
```
### 2.7 Fehlermeldungen (UXTexte)
- Kurz: "Ungültige FEIID. Erlaubt sind 78 Ziffern (z. B. 10011469)."
- Lang: "Bitte eine gültige FEIID eingeben: 78 Ziffern (z. B. 10011469). Historische Referenzcodes (z. B. 104FE22) werden akzeptiert und wenn möglich automatisch aufgelöst."
### 2.8 Quellen/Verweise
- FEI General Regulations, insbesondere Art. 113 (Registration and Eligibility) und Art. 114 (Horse Identification) — `docs/03_Domain/02_Reference/FEI_Regelwerk/FEI-2026_General-Regulations_…md`
- Systembeispiele/Fixtures in FrontendStores (FEIIDs): `frontend/shells/meldestelle-desktop/.../Stores.kt`
### 2.9 BackendLookup (MasterdataSCS)
- Endpoint: `GET /api/fei/resolve/{id}`
- Eingabe: `{id}` numerisch (`^[0-9]{7,8}$`) oder LegacyCode (`^[0-9]{3}[A-Z]{2}[0-9]{2}$`).
- Erfolg 200: `{ input, normalizedNumericId, sourceFormat, wasMapped, found: true }`
- Nicht gefunden 404: `{ input, normalizedNumericId: null, sourceFormat: null, wasMapped: false, found: false }`
- MappingQuelle: `backend/services/masterdata/masterdata-service/src/main/resources/data/fei-id-mapping.json` (kann später aus DB gespeist werden).
---
## 3. Lizenzklassen (R1R4, RD1RD3, LZF)
ToDo: Vollständige Liste und Zuordnung in A1 (weiterer Unterpunkt).
Status: Draft basierend auf ÖTOPraxis und ZNSLizenzdaten. Detaillierte ParagraphenZitate werden nachgereicht (A2/A3 Arbeiten verknüpft).
### 3.1 Katalog gültiger Lizenzklassen
- Reiten Springen (RKlassen): `R1`, `R2`, `R3`, `R4`
- Dressur Reiten (RDKlassen): `RD1`, `RD2`, `RD3`
- Lizenzfrei/ohne Lizenz Kennzeichnung: `LZF` (für bewerbsbezogene Abteilung „ohne Lizenz“)
Erweiterbarkeit: Weitere Spezial/Jugend oder FahrerLizenzen können ergänzt werden, sobald in ÖTO/ZNS erforderlich.
### 3.2 Grundregeln der Zuordnung (vereinfachte Erstfassung)
- Springen (CSN):
- Bewerbe bis inkl. 95 cm: Teilnahme mit `LZF` (Abt. „ohne Lizenz“) oder `R1` (Abt. „mit Lizenz`).
- Ab 100 cm: mindestens `R1` erforderlich; ab bestimmten Höhen empfohlen/erforderlich `R2+` (veranstalter/ausschreibungsabhängig).
- Zwangsteilungsregeln siehe Roadmap A2 (eigener Abschnitt).
- Dressur (CDN):
- Einsteigerprüfungen (z. B. Dressurreiterprüfungen niedrig): `LZF` oder `RD1`.
- Ab definiertem Schwierigkeitsgrad: `RD1+`, höhere Klassen `RD2/RD3` gemäß Ausschreibung.
Hinweis: Die exakte Matrix „Lizenzklasse × Bewerbsklasse (Disziplin, Höhe/Schwierigkeit)“ wird als Tabelle hinterlegt und aus ÖTOParagraphen abgeleitet. Nach Bestätigung durch Fachreferat wird diese Spezifikation von „Draft“ auf „Stable“ gehoben.
### 3.3 Validierungslogik (Platzhalter bis zur finalen Matrix)
- Eingabe muss in obiger Katalogliste vorkommen (`R1|R2|R3|R4|RD1|RD2|RD3|LZF`).
- Bei Auswahl eines Bewerbs wird die erlaubte(n) Lizenzklasse(n) aus der Disziplin/Höhe/Schwierigkeit abgeleitet.
- Fehler, wenn gewählte Lizenzklasse nicht in der erlaubten Menge liegt.
Pseudocode (vereinfacht):
```kotlin
fun isLicenseAllowed(discipline: Discipline, heightCm: Int?, testLevel: DressageLevel?, license: String): Boolean {
val allowed = allowedLicensesFor(discipline, heightCm, testLevel) // Tabelle/Regel-Engine
return license in allowed
}
```
### 3.4 Fehlermeldungen (UXTexte)
- Kurz: "Diese Lizenzklasse ist für den ausgewählten Bewerb nicht zugelassen."
- Lang: "Bitte eine für diesen Bewerb zugelassene Lizenz auswählen. Die Zulassung richtet sich nach Disziplin und Höhe/Schwierigkeitsgrad (ÖTO)."
### 3.5 Quellen/Verweise
- ÖTO (Abschnitte zu Lizenzen, Springen/Dressur Teilnahmevoraussetzungen)
- ZNSLizenzdaten: `docs/OePS/ZNS/LIZENZ01.dat` (Datenquelle, strukturierter Export) Parsing/Anlage in MasterdataSCS.
- Teilungs-/Warnlogik: `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md`
### 3.6 LizenzZuordnungstabelle (DRAFT, final mit ParagraphenVerweisen)
- Springen (CSN) — Bezug ÖTO § 231 ff. (finale Paragraphennummern nachreichen):
| Höhe (cm) | Zulässige Lizenz-Abteilungen | Primär-Bezug ÖTO |
|---|---|---|
| ≤ 95 | LZF „ohne Lizenz“ | § 231 (Zwangsteilung Einsteiger) |
| ≤ 95 | R1 „mit Lizenz“ | § 231 |
| 100 | R1+ | § 231 |
| 105110 | R1, R2+ (Empf. R2) | § 231 |
| 115120 | R2+ | § 231 |
| 125135 | R3+ | § 231 |
| ≥ 140 | R4 | § 231 |
- Dressur (CDN) — Bezug ÖTO § 103 ff. (finale Paragraphennummern nachreichen):
| Prüfungsniveau (national, äquiv.) | Zulässige Lizenzen | Primär-Bezug ÖTO |
|---|---|---|
| Einsteiger/Dressurreiter (niedrig) | LZF, RD1 | § 103 |
| A/L | RD1+ | § 103 |
| LM/M | RD2+ | § 103 |
| S | RD3 | § 103 |
Hinweise:
- Veranstalter/Ausschreibung kann engere Anforderungen definieren, jedoch nicht lockern.
- Zwangsteilungsregeln für CSNCNEU sind in A2 separat spezifiziert und ergänzen die obige Tabelle.
---
## 4. Altersklassen Pferd
ToDo: Mindestalter je Bewerbsklasse / Höhe und Stichtagsregel (1. Jänner) folgt in A1 (weiterer Unterpunkt).
Status: Draft FEI/ÖTO konsolidiert; Detailtabellen pro Disziplin werden ergänzt.
### 4.1 Stichtagsregel (Altersberechnung)
- Das Pferdealter wird für das gesamte Kalenderjahr mit Stichtag 1. Jänner bestimmt (Jahrgangsregel).
Beispiel: Geburtsdatum 15.06.2020 → Alter 2026 = 6 (ab 01.01.2026).
Pseudocode:
```kotlin
fun horseAgeOnJan1(birthYear: Int, year: Int): Int = year - birthYear
```
### 4.2 Mindestalter Grundregeln (Erstfassung, Disziplin-übergreifend)
- National (ÖTO, typische Praxis):
- Springen bis 100 cm: min. 4 Jahre
- Springen > 100 cm bis 120 cm: min. 5 Jahre
- Springen > 120 cm: min. 6 Jahre (Empfehlung/abhängig von Klasse)
- Dressur Einstieg/leichte Prüfungen: min. 4 Jahre
- Dressur höhere Klassen (z. B. L/M/S‑ähnlich): min. 56 Jahre (konkret per Tabelle nachzureichen)
- International (FEI, vgl. Art. 136 GR):
- Disziplinspezifische Mindestalter (werden tabellarisch hinterlegt; Abhängig von Disziplin/Testlevel/StarRating).
Hinweis: Konkrete, rechtssichere Tabellen (Disziplin × Klasse/Höhe × Mindestalter) werden nach ParagraphenSichtung ergänzt und in MasterdataSCS versioniert.
### 4.3 Validierungslogik
- Errechne `age = horseAgeOnJan1(geburtsjahr, veranstaltungsjahr)`.
- Prüfe `age >= minAgeFor(discipline, heightCm?, testLevel?)` laut Matrix.
- Fehler, wenn Bedingung nicht erfüllt.
BeispielFehlertext:
- Kurz: "Pferd ist für diesen Bewerb zu jung."
- Lang: "Das Mindestalter für diesen Bewerb ist {X} Jahre (Stichtag 1. Jänner). Dieses Pferd gilt im aktuellen Jahr als {Y} Jahre alt."
### 4.4 Quellen/Verweise
- FEI General Regulations, Art. 136 (Age of Horses)
- ÖTO (disziplinspezifische Mindestalter nationaler Bewerbe)
### 4.5 MindestalterTabellen (DRAFT; ParagraphenVerweise finalisieren)
- Springen (national, ÖTO; Bezug § 231, Pferdealter allgemeine Bestimmungen):
| Höhe (cm) | Mindestalter Pferd (Jahre, Stichtag 1.1.) |
|---|---|
| ≤ 100 | 4 |
| 105120 | 5 |
| ≥ 125 | 6 |
- Dressur (national, ÖTO; Bezug § 103, Pferdealter):
| Prüfungsniveau | Mindestalter Pferd |
|---|---|
| Einsteiger/Dressurreiter (niedrig) | 4 |
| A/L | 4 |
| LM/M | 5 |
| S | 6 |
- International (FEI, GR Art. 136 + Disziplinspezifische Regeln, exemplarisch):
| Disziplin | Prüfungs-/StarLevel | Mindestalter |
|---|---|---|
| Jumping | 1*2* | 6 |
| Jumping | 3*5* | 7 |
| Dressage | CDIYH (Young Horses) | gem. FEI YHRegeln |
| Dressage | CDI (Senior) | 7 |
Hinweis: Exakte FEITabellen sind pro Disziplinregelwerk verbindlich zu übernehmen; hier nur Platzhalter bis ParagraphenFinalisierung.
---
## 5. Offene Punkte & Nächste Schritte
- LizenzZuordnungstabelle (Springen/Dressur) mit ParagraphenVerweisen finalisieren und hier einpflegen. (Status: DRAFT Tabellen vorhanden)
- MindestalterTabellen je Disziplin und Klasse/Höhe aus ÖTO & FEI präzise ergänzen. (Status: DRAFT Tabellen vorhanden)
- FEILegacyCode → numerische ID Mappings in MasterdataSCS verankern; BackendLookup implementieren. (Status: erste Version implementiert, JSONMapping, RESTEndpoint)
Meta:
- status: DRAFT (wird auf STABLE angehoben nach Fachfreigabe)
- version: 0.3 (20260402)