- Deleted obsolete modules related to horses, clubs, officials, and persons services, including their configurations, build files, and database provisioning scripts. - Cleaned up associated references in the project structure (e.g., `settings.gradle.kts`). - Removed unused database tables and Spring beans related to these domains. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
240 lines
10 KiB
Markdown
240 lines
10 KiB
Markdown
---
|
||
type: ADR
|
||
id: ADR-0014
|
||
status: ACTIVE
|
||
owner: Lead Architect
|
||
last_update: 2026-03-28
|
||
---
|
||
|
||
# ADR-0014: Bounded Context Mapping (SCS-Architektur)
|
||
|
||
## Status
|
||
|
||
Akzeptiert
|
||
|
||
## Kontext
|
||
|
||
Mit der Entscheidung für Domain-Driven Design (→ ADR-0002) und der modularen Architektur (→ ADR-0001) war es
|
||
notwendig, die fachlichen Grenzen des Systems explizit zu definieren. Die ursprünglichen Module (`masterdata`,
|
||
`members`, `horses`, `events`) spiegelten technische Kategorien wider, nicht die tatsächlichen Fachdomänen des
|
||
österreichischen Turniersports.
|
||
|
||
Folgende Probleme wurden identifiziert:
|
||
|
||
1. Fehlende Ausrichtung zwischen Code-Struktur und ÖTO-Regelwerk
|
||
2. Unklare Verantwortlichkeiten bei domänenübergreifenden Operationen (z.B. Nennungs-Transfer)
|
||
3. Keine explizite Trennung zwischen Kern-Domäne (Nennungs-Workflow) und unterstützenden Domänen
|
||
4. Fehlende Grundlage für eine skalierbare, offline-fähige Desktop-Architektur
|
||
|
||
## Entscheidung
|
||
|
||
Das System wird in **6 Bounded Contexts** aufgeteilt, die als **Self-Contained Systems (SCS)** implementiert werden.
|
||
Jeder Context ist fachlich eigenständig, besitzt seine eigene Ubiquitous Language und kommuniziert über definierte
|
||
Schnittstellen.
|
||
|
||
### Übersicht der 6 Bounded Contexts
|
||
|
||
| Context | Verantwortlichkeit | Priorität | Phase |
|
||
|----------------------------|------------------------------------------------------|-----------|---------|
|
||
| `registration-context` | Nennungs-Workflow (Herzstück des Systems) | **P1** | Phase 4 |
|
||
| `master-data-context` | Reiter, Pferde, Vereine, ZNS-Daten, ÖTO-Regelwerk | **P1** | Phase 4 |
|
||
| `competition-context` | Bewerbe, Startlisten, Ergebnisse, Abteilungs-Logik | **P2** | Phase 5 |
|
||
| `event-management-context` | Veranstaltung, Turnier, Ausschreibung, Genehmigungen | **P2** | Phase 5 |
|
||
| `billing-context` | Abrechnung, Kassa, Gebühren, Konten | **P3** | Phase 6 |
|
||
| `identity-context` | Authentifizierung, Rollen, Berechtigungen (Keycloak) | **P3** | Phase 6 |
|
||
|
||
> **Hinweis `series-context`:** Cups, Serien und Meisterschaften werden in Phase 2+ als eigenständiger Context
|
||
> implementiert. Die Architektur ist von Anfang an dafür vorbereitet (pluggable Berechnungsmodell,
|
||
> konfigurierbare Paar-Bindung). Kein Hard-Coding von Serien-Logik in anderen Contexts.
|
||
|
||
---
|
||
|
||
### Context-Beschreibungen
|
||
|
||
#### `registration-context` — Kern-Domäne (Core Domain)
|
||
|
||
**Verantwortlichkeit:** Der gesamte Lebenszyklus einer Nennung – von der Erstanmeldung bis zur Stornierung.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomNennung` – Verbindliche Anmeldung eines Paares (Reiter & Pferd) zu einem Bewerb
|
||
- `DomNennungsTransfer` – Transfer-Operation (kein Storno + Neu); Guthaben bleibt erhalten
|
||
- `DomAbteilung` – Kleinste Einheit für Startlisten und Ergebnisse (mit Warn-Logik)
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `Nennung`, `Nennschluss`, `Nachnenngebühr`, `Nennungs-Transfer`, `Override-Event`, `Startwunsch`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- Eine Nennung ist immer einem Paar (Reiter + Pferd) zugeordnet
|
||
- Nennungs-Transfer ist eine atomare Operation – kein Zwischenzustand ohne gültiges Paar
|
||
- Regelwerk-Verstöße erzeugen **Warnungen** (niemals harte Fehler) + `Override-Event`
|
||
|
||
---
|
||
|
||
#### `master-data-context` — Unterstützende Domäne (Supporting Domain)
|
||
|
||
**Verantwortlichkeit:** Stammdaten aller Akteure, Synchronisation mit dem ZNS (Zentrales Nennungs-System) sowie die "
|
||
Library of Truth" für das ÖTO/FEI Regelwerk.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomReiter` – Reiter mit Lizenz, Satznummer, Startkarte
|
||
- `DomPferd` – Pferd mit Lebensnummer, Kopfnummer, Satznummer
|
||
- `DomFunktionär` – Person mit Turnier-Rolle und Qualifikation (Richter, Parcoursbauer)
|
||
- `DomVerein` – OEPS-Mitgliedsverein (Veranstalter)
|
||
- `DomRegelwerk` – Richtverfahren (§ 204 Springen, § 104 Dressur etc.), Sparten, Klassen
|
||
- `DomGebührenSatz` – Standard-Sätze für Sportförderbeiträge und Tierwohl-Euros
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `Satznummer`, `Lebensnummer`, `Kopfnummer`, `FEI-ID`, `Lizenz`, `Startkarte`, `Gastreiter`, `Richtverfahren`,
|
||
`Paragraph`, `Sparte`, `Klasse`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- `Satznummer` ist der primäre Schlüssel für den ZNS-Datenaustausch
|
||
- ZNS-Daten sind schreibgeschützt; Erweiterungen erfolgen über Verknüpfungen im `identity-context`
|
||
- Das Regelwerk dient als Basis für alle fachlichen Validierungen im System
|
||
- ZNS-Daten werden lokal gecacht (Offline-First)
|
||
|
||
---
|
||
|
||
#### `competition-context` — Unterstützende Domäne (Supporting Domain)
|
||
|
||
**Verantwortlichkeit:** Strukturierung von Bewerben, Erstellung von Startlisten, Erfassung von Ergebnissen. Die *
|
||
*Abteilung** ist hierbei die kleinste operative Einheit.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomAbteilung` – Atomare Einheit für Startlisten und Ergebnisse (ÖTO § 39). Ein Bewerb ist der organisatorische
|
||
Container.
|
||
- `DomBewerb` – Klammer um eine oder mehrere Abteilungen mit gemeinsamer Bewerbsnummer, Sparte, Klasse.
|
||
- `DomStartliste` – Geordnete Liste der Starter einer Abteilung.
|
||
- `DomErgebnis` – Ergebnis eines Starts (Platzierung, Punkte, Zeit) innerhalb einer Abteilung.
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `Abteilung`, `Abteilungsnummer`, `Bewerb`, `Prüfung`, `Startliste`, `Richtverfahren`, `Klasse/Höhe`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- Startlisten und Ergebnislisten werden auf **Abteilungsebene** verwaltet
|
||
- Abteilungs-Schwellenwerte gemäß ÖTO § 39 lösen **Warnungen** aus (→ `Override-Event`)
|
||
- Ein Bewerb kann mehrere Abteilungen haben (z.B. Trennung nach R1/R2 Lizenzen)
|
||
|
||
---
|
||
|
||
#### `event-management-context` — Unterstützende Domäne (Supporting Domain)
|
||
|
||
**Verantwortlichkeit:** Verwaltung von Veranstaltungen und Turnieren, Ausschreibungs-Generierung, Genehmigungsprozesse.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomVeranstaltung` – Interne Organisationseinheit des Veranstalters (selbst vergebene ID)
|
||
- `DomTurnier` – Offizielles Turnier mit OEPS-vergebener Turniernummer
|
||
- `DomAusschreibung` – Offizielles Dokument mit Pflichtfeldern gemäß ÖTO (A-Satz ZNS)
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `Veranstaltung`, `Turnier`, `Turniernummer`, `Turnierkategorie`, `Ausschreibung`, `Kombination`, `TBA`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- `Veranstaltung` ≠ `Turnier` (→ ADR-0002, ÖTO § 2 Abs. 1): Eine Veranstaltung kann mehrere Turniere umfassen
|
||
- Turniernummern werden von der OEPS vergeben, nicht selbst generiert
|
||
- Kombinations-Turniere behalten je eigene Turniernummer
|
||
|
||
---
|
||
|
||
#### `billing-context` — Generische Domäne (Generic Domain)
|
||
|
||
**Verantwortlichkeit:** Gebührenberechnung, Kassenführung, Abrechnung mit Reitern und dem Verband.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomKonto` – Kontobasierte Abrechnung pro Zahler (Basis für „Hansi-Szenario")
|
||
- `DomGebühr` – Einzelgebühr (Nenngeld, Nachnenngebühr, Sportförderbeitrag, Tierwohl-Euro)
|
||
- `DomAbrechnung` – Zusammenfassung aller Gebühren einer Veranstaltung
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `Konto`, `Nenngeld`, `Nachnenngebühr`, `Sportförderbeitrag`, `Tierwohl-Euro`, `Gebühren-Verzicht`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- Sportförderbeitrag und Tierwohl-Euro fallen **pro Start** an (nicht pro Nennung)
|
||
- Gebühren-Verzicht wird als explizites Event gespeichert (Audit-Trail)
|
||
|
||
---
|
||
|
||
#### `identity-context` — Generische Domäne (Generic Domain)
|
||
|
||
**Verantwortlichkeit:** Authentifizierung, Rollen-Management, Berechtigungsprüfung (via Keycloak) sowie die Verwaltung
|
||
von erweiterten Profilen.
|
||
|
||
**Aggregate Roots:**
|
||
|
||
- `DomBenutzer` – Systembenutzer mit Rollen (TBA, Veranstalter, Meldestelle, Richter)
|
||
- `DomProfil` – Erweiterte Daten (Logo, Bio, Kontakt) verknüpft mit einer `Satznummer` aus dem `master-data-context`
|
||
- `DomRolle` – Definierte Rolle mit Berechtigungen
|
||
|
||
**Ubiquitous Language (Auswahl):**
|
||
|
||
- `TBA`, `Veranstalter`, `Meldestelle`, `Richter`, `Profil-Link`, `Rolle`, `Berechtigung`
|
||
|
||
**Kern-Invarianten:**
|
||
|
||
- Keycloak ist der einzige Identity Provider (→ ADR-0006)
|
||
- Ein System-Benutzer kann über eine Link-Tabelle mit amtlichen ZNS-Daten verknüpft werden
|
||
- Rollen sind turnierbezogen (ein Benutzer kann bei Turnier A TBA und bei Turnier B Richter sein)
|
||
|
||
---
|
||
|
||
## Konsequenzen
|
||
|
||
### Positive
|
||
|
||
- **Fachliche Klarheit:** Jeder Context hat eine klar definierte Verantwortlichkeit und eigene Ubiquitous Language. Die
|
||
Umbenennung in `master-data-context` schärft das Verständnis als zentrale Library of Truth.
|
||
- **Abteilungs-Fokus:** Die Anerkennung der Abteilung als kleinste Einheit im `competition-context` löst Inkonsistenzen
|
||
bei Start- und Ergebnislisten.
|
||
- **Unabhängige Entwicklung:** P1-Contexts (`registration-context`, `master-data-context`) können ohne P2/P3 entwickelt
|
||
werden
|
||
- **Offline-First:** Jeder Context kann seinen eigenen lokalen Cache verwalten (SQLDelight)
|
||
- **ÖTO-Konformität:** Die Context-Grenzen spiegeln die Struktur des ÖTO-Regelwerks wider
|
||
- **Erweiterbarkeit:** `series-context` kann in Phase 2+ ohne Änderungen an bestehenden Contexts hinzugefügt werden
|
||
|
||
### Negative
|
||
|
||
- **Koordinationsaufwand:** Domänenübergreifende Use-Cases (z.B. Nennungs-Workflow) erfordern explizite Integration
|
||
- **Datenkonsistenz:** Eventual Consistency zwischen Contexts muss bewusst gehandhabt werden
|
||
- **Initialer Aufwand:** Vollständige Context-Implementierung erfordert mehr Vorabdesign
|
||
|
||
### Neutral
|
||
|
||
- Die Context-Grenzen können sich mit wachsendem Domänenwissen verschieben (Living Architecture)
|
||
|
||
## Betrachtete Alternativen
|
||
|
||
### Technische Modulaufteilung (abgelehnt)
|
||
|
||
Die ursprüngliche Aufteilung in `masterdata`, `members`, `horses`, `events` wurde verworfen, da sie technische
|
||
Kategorien statt fachliche Domänen widerspiegelt und keine klare Heimat für den Nennungs-Workflow bietet.
|
||
|
||
### Monolithische Domäne (abgelehnt)
|
||
|
||
Ein einzelner großer Domänen-Context würde die Komplexität des ÖTO-Regelwerks nicht beherrschbar machen und
|
||
die Offline-First-Strategie erschweren.
|
||
|
||
## Referenzen
|
||
|
||
- [ADR-0001: Modulare Architektur](0001-modular-architecture-de.md)
|
||
- [ADR-0002: Domain-Driven Design](0002-domain-driven-design-de.md)
|
||
- [ADR-0015: Context Map](0015-context-map-de.md)
|
||
- [Ubiquitous Language](../../03_Domain/01_Glossary/Ubiquitous_Language.md)
|
||
- [Abteilungs-Trennungs-Schwellenwerte](../../03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md)
|
||
- [MASTER_ROADMAP](../MASTER_ROADMAP.md)
|
||
- ÖTO 2026, § 2 Abs. 1, § 2 Abs. 7, § 2 Abs. 8, § 39
|