docs: add core domain SQL schema draft and enhance domain glossary

Introduced an initial SQL schema draft for the core domain, focusing on offline-first architecture and aligning with OEPS legacy specifications. Expanded the domain glossary to include critical terms for improved clarity and domain understanding. Added session notes and user stories to document analysis outcomes and requirements.
This commit is contained in:
Stefan Mogeritsch 2026-01-16 11:32:53 +01:00
parent 2dc3c4154b
commit 39ba21fd77
9 changed files with 975 additions and 28 deletions

View File

@ -1,8 +1,40 @@
# Glossar der Domäne "Meldestelle" # Glossar der Domäne "Meldestelle"
Dieses Dokument definiert die Ubiquitous Language des Projekts. Dieses Dokument definiert die **Ubiquitous Language** (allgegenwärtige Sprache) des Projekts. Alle Begriffe sind so zu verwenden, wie sie hier definiert sind sowohl im Code als auch in der Kommunikation.
* **Event:** Der organisatorische Rahmen für eine Veranstaltung. ## A - E
* **Turnier:** Die administrative, regelbasierte Einheit innerhalb eines Events.
* ... * **Abteilung:** Eine Unterteilung eines -> *Bewerbs*. Oft werden Bewerbe mit vielen Startern in mehrere Abteilungen geteilt (z.B. nach Lizenzklasse oder Rasse), die getrennt gewertet werden.
* **Akteur:** Oberbegriff für alle Personen (Reiter, Richter, Besitzer) und Organisationen (Vereine), die im System interagieren.
* **Ausschreibung:** Das offizielle Dokument, das alle Bedingungen eines -> *Turniers* festlegt.
* **Bewerb:** Die einzelne sportliche Prüfung (z.B. "Springprüfung Kl. L"). Kleinste Einheit für Nennungen und Ergebnisse.
* **Event:** Der organisatorische Rahmen (z.B. "Pferdefest 2026"), der ein oder mehrere -> *Turniere* beinhalten kann.
## F - J
* **FEI-ID:** Eindeutige Identifikationsnummer der Internationalen Reiterlichen Vereinigung (FEI) für Reiter und Pferde.
* **Gastreiter:** Ein Reiter mit ausländischer Staatsbürgerschaft, der nicht für einen österreichischen Verein startet.
* **Kopfnummer:**
* *National (OEPS):* Die permanente, 4-stellige Registrierungsnummer eines Pferdes beim OEPS (z.B. "A123"). Wird oft am Zaumzeug getragen.
* *International/Turnier:* Eine temporäre Startnummer für das spezifische Turnier.
## K - O
* **Lebensnummer:** Eine 9-stellige Nummer (bzw. 15-stellig international), die ein Pferd bei der Geburt vom Zuchtverband erhält. Dient der eindeutigen Identifizierung, ist aber im OEPS-Kontext bei ausländischen Pferden oft generiert und daher nicht zur Suche geeignet.
* **Lizenz:** Die Qualifikationsstufe eines Reiters (z.B. "R1", "RD3"). Bestimmt, in welchen Klassen er startberechtigt ist.
* **Nennung:** Die verbindliche Anmeldung eines Paares (Reiter & Pferd) zu einem -> *Bewerb*.
* **OEPS:** Österreichischer Pferdesportverband.
## P - T
* **Satznummer:**
* *Pferd:* 10-stellige, rein numerische ID (z.B. `0000123456`), die ein Pferd in der OEPS-Datenbank eindeutig identifiziert. **Primärer Schlüssel für den Datenaustausch.**
* *Reiter:* 6-stellige, rein numerische ID für Personen.
* **Sperrliste:** Eine vom Verband geführte Liste von Personen oder Pferden, die aktuell nicht startberechtigt sind (meist wegen offener Zahlungen).
* **Startkarte:** Der Nachweis, dass die Jahresgebühr für die Lizenz bezahlt wurde. Ohne aktive Startkarte ist (national) kein Start möglich.
* **Turnier:** Die administrative Einheit (z.B. "CSN-A"), die einem spezifischen Regelwerk (ÖTO oder FEI) unterliegt.
## U - Z
* **Wertungsserie:** Ein übergeordneter Wettbewerb (Cup, Meisterschaft), der Ergebnisse aus mehreren Bewerben/Turnieren aggregiert.
* **ZNS:** Zentrales Nennsystem (bzw. die zugehörigen Datensätze wie `zns.zip`), über das Stammdaten und Nennungen ausgetauscht werden.

View File

@ -0,0 +1,241 @@
-- Database Schema Draft for Meldestelle (Offline-First)
-- Dialect: SQLite (compatible with SQLDelight)
-- Status: Draft / Proposal
-- Based on: OEPS Legacy Spec V2.4 & Domain Analysis
-- ==================================================================
-- 1. CORE INFRASTRUCTURE (Sync & Audit)
-- ==================================================================
-- Every table should ideally have these fields, but for brevity
-- they are implied or added where critical.
-- id: TEXT NOT NULL PRIMARY KEY (UUID)
-- created_at: INTEGER NOT NULL (Epoch Millis)
-- updated_at: INTEGER NOT NULL (Epoch Millis)
-- version: INTEGER NOT NULL (Optimistic Locking / Sync Counter)
-- is_deleted: INTEGER NOT NULL DEFAULT 0 (Soft Delete)
-- ==================================================================
-- 2. MASTER DATA (Stammdaten)
-- ==================================================================
-- Akteure: Personen und Organisationen
-- Covers: Reiter, Richter, Besitzer, Vereine
CREATE TABLE actor (
id TEXT NOT NULL PRIMARY KEY,
type TEXT NOT NULL, -- 'PERSON', 'ORGANIZATION'
-- Display Data
first_name TEXT, -- NULL for Organizations
last_name TEXT NOT NULL, -- Name or Org-Name
-- OEPS Specifics (Legacy Spec)
oeps_id TEXT, -- 'Satznummer' (6 digits for Person, 4 for Club)
oeps_category TEXT, -- 'Verein', 'Reiter', 'Richter'
-- Licenses & Status
license_code TEXT, -- e.g. 'R1', 'RD3'
has_start_card INTEGER NOT NULL DEFAULT 0, -- Boolean: Paid annual fee?
is_locked INTEGER NOT NULL DEFAULT 0, -- Boolean: Sperrliste?
-- Contact & Meta
nationality TEXT NOT NULL DEFAULT 'AUT', -- ISO 3-Letter
contact_json TEXT, -- Address, Phone, Email
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
version INTEGER NOT NULL DEFAULT 1
);
CREATE INDEX idx_actor_oeps_id ON actor(oeps_id);
CREATE INDEX idx_actor_name ON actor(last_name, first_name);
-- Pferde
CREATE TABLE horse (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
-- Identification
oeps_id TEXT, -- 'Satznummer' (10 digits) - CRITICAL for Export
head_number_permanent TEXT, -- 'Kopfnummer' (e.g. A123)
life_number TEXT, -- 'Lebensnummer' (Zucht)
fei_id TEXT,
-- Details
birth_year INTEGER,
gender TEXT, -- 'M', 'W', 'G' (Gelding/Wallach)
color TEXT,
sire_name TEXT, -- Vater (Denormalized for search)
dam_name TEXT, -- Mutter
-- Owner Link
owner_id TEXT, -- FK to actor.id
-- Status
is_locked INTEGER NOT NULL DEFAULT 0, -- Sperrliste
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
version INTEGER NOT NULL DEFAULT 1
);
CREATE INDEX idx_horse_oeps_id ON horse(oeps_id);
CREATE INDEX idx_horse_head_num ON horse(head_number_permanent);
CREATE INDEX idx_horse_name ON horse(name);
-- ==================================================================
-- 3. EVENT STRUCTURE
-- ==================================================================
CREATE TABLE event (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
start_date INTEGER NOT NULL, -- Epoch Day
end_date INTEGER NOT NULL,
location TEXT,
organizer_id TEXT NOT NULL, -- FK to actor.id
status TEXT NOT NULL DEFAULT 'PLANNING' -- PLANNING, ACTIVE, ARCHIVED
);
CREATE TABLE tournament (
id TEXT NOT NULL PRIMARY KEY,
event_id TEXT NOT NULL REFERENCES event(id),
-- OEPS Spec
oeps_number TEXT NOT NULL, -- 5 digits (e.g. 21001)
category TEXT, -- e.g. 'CSN-A'
ruleset TEXT NOT NULL DEFAULT 'OETO', -- 'OETO', 'FEI'
-- Sync Meta
updated_at INTEGER NOT NULL
);
-- Bewerbe (Competitions)
-- Note: If a competition is split into 2 departments (Abteilungen),
-- we create 2 rows here to match the OEPS 'B-Satz' logic.
CREATE TABLE competition (
id TEXT NOT NULL PRIMARY KEY,
tournament_id TEXT NOT NULL REFERENCES tournament(id),
-- Identification
code_internal TEXT NOT NULL, -- '01', '02' (2 digits)
code_official TEXT, -- '001' (3 digits, optional)
division_id INTEGER NOT NULL DEFAULT 0, -- 'Abteilung' (0=None, 1=1st, 2=2nd)
-- Description
title TEXT NOT NULL,
category TEXT, -- e.g. 'LM', 'S*'
discipline TEXT NOT NULL, -- 'D', 'S', 'C' (Dressage, Jumping, Combined)
-- Rules & Scoring
scoring_method TEXT NOT NULL, -- 'A0', 'C', 'DRESSAGE_PERCENT'
start_fee INTEGER NOT NULL DEFAULT 0, -- In Cents
-- State
status TEXT NOT NULL DEFAULT 'OPEN', -- OPEN, CLOSED_FOR_ENTRIES, RUNNING, FINISHED, SIGNED_OFF
-- Sync Meta
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_comp_tournament ON competition(tournament_id);
-- ==================================================================
-- 4. SPORT & PROCESS
-- ==================================================================
-- Nennungen (Entries)
-- Represents the intent to start.
CREATE TABLE entry (
id TEXT NOT NULL PRIMARY KEY,
competition_id TEXT NOT NULL REFERENCES competition(id),
-- The Pair
horse_id TEXT NOT NULL REFERENCES horse(id),
rider_id TEXT NOT NULL REFERENCES actor(id),
-- Financials
responsible_person_id TEXT REFERENCES actor(id), -- Who pays?
fee_agreed INTEGER NOT NULL, -- In Cents (Snapshot of price at entry time)
payment_status TEXT NOT NULL DEFAULT 'PENDING', -- PENDING, PAID, WAIVED
-- Validation Override (The "Human Factor")
validation_status TEXT NOT NULL DEFAULT 'OK', -- OK, WARNING, BLOCKED
override_comment TEXT, -- Why was this allowed despite warning?
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_entry_comp ON entry(competition_id);
CREATE INDEX idx_entry_rider ON entry(rider_id);
-- Startliste (Start Order)
-- Subset of entries that actually start.
CREATE TABLE start_list_entry (
id TEXT NOT NULL PRIMARY KEY,
entry_id TEXT NOT NULL REFERENCES entry(id),
-- Ordering
start_order INTEGER, -- 1, 2, 3...
start_time_planned INTEGER, -- Epoch Millis (optional)
-- Tournament Specifics
head_number_event TEXT, -- Startnummer am Turnier (kann von A123 abweichen)
-- Status
status TEXT NOT NULL DEFAULT 'READY', -- READY, STARTED, DNS (Did Not Start)
UNIQUE(entry_id)
);
-- Ergebnisse (Results)
CREATE TABLE result (
id TEXT NOT NULL PRIMARY KEY,
start_list_entry_id TEXT NOT NULL REFERENCES start_list_entry(id),
-- The Outcome
rank INTEGER, -- 1, 2, 3... (NULL if eliminated)
-- Scoring Details (Polymorphic based on Competition Type)
points_jump_faults DECIMAL(5,2), -- Springfehler
time_taken_ms INTEGER, -- Zeit in Millisekunden
score_dressage_percent DECIMAL(5,3), -- 72.500
score_dressage_total DECIMAL(6,2), -- Summe Punkte
-- Status Flags
classification TEXT NOT NULL DEFAULT 'OK', -- OK, EL (Elim), RET (Retired), DIS (Disq)
-- Detailed Marks (JSON)
-- e.g. { "judge_C": 7.5, "judge_H": 7.2, "obstacles": [...] }
details_json TEXT,
-- Money
prize_money INTEGER DEFAULT 0, -- In Cents
-- Audit
updated_by_user_id TEXT,
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_result_starter ON result(start_list_entry_id);
-- ==================================================================
-- 5. AUDIT LOG (NFR-07)
-- ==================================================================
CREATE TABLE audit_log (
id TEXT NOT NULL PRIMARY KEY,
entity_type TEXT NOT NULL, -- 'RESULT', 'ENTRY'
entity_id TEXT NOT NULL,
action TEXT NOT NULL, -- 'CREATE', 'UPDATE', 'DELETE'
user_id TEXT,
timestamp INTEGER NOT NULL,
changes_json TEXT -- { "score_old": 7.0, "score_new": 7.5 }
);

View File

@ -1,6 +1,8 @@
# 01 - Core Domain Entities # 01 - Core Domain Entities
Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten) des "Meldestelle"-Projekts. Diese Entitäten bilden das Fundament des Datenmodells und der gesamten Anwendungslogik. Sie sind das Ergebnis der Analyse der OEPS/ÖTO- und FEI-Regelwerke sowie der grundlegenden Anforderungen an das System. Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten) des "Meldestelle"-Projekts. Diese Entitäten bilden das Fundament des Datenmodells und der gesamten Anwendungslogik.
> **Hinweis:** Dieses Modell wurde basierend auf der Analyse des OEPS-Pflichtenhefts 2021 V2.4 verfeinert.
## Die 6 Kern-Entitäten ## Die 6 Kern-Entitäten
@ -20,7 +22,7 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
**Beispiele:** "Apropos Pferd 2026", "Vereinsturnier Reitclub XY". **Beispiele:** "Apropos Pferd 2026", "Vereinsturnier Reitclub XY".
**Attribute:** **Attribute:**
* `Event-ID` (PK): Eindeutiger technischer Schlüssel. * `Event-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Name`: Offizieller Name des Events. * `Name`: Offizieller Name des Events.
* `Veranstaltungsort`: Adresse und Name der Anlage. * `Veranstaltungsort`: Adresse und Name der Anlage.
* `Datum_Von`: Startdatum des Events. * `Datum_Von`: Startdatum des Events.
@ -37,8 +39,9 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
**Beispiele:** "CSN-A im Rahmen der Apropos Pferd", "CSI2* im Rahmen der Apropos Pferd". **Beispiele:** "CSN-A im Rahmen der Apropos Pferd", "CSI2* im Rahmen der Apropos Pferd".
**Attribute:** **Attribute:**
* `Turnier-ID` (PK): Eindeutiger technischer Schlüssel. * `Turnier-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Event_ID` (FK): Verweis auf das übergeordnete `Event`. * `Event_ID` (FK): Verweis auf das übergeordnete `Event`.
* `Turniernummer_OEPS`: 5-stellige Nummer (z.B. `21001`) für den Datenaustausch.
* `Regelwerk`: Entscheidende Weiche für die Anwendungslogik (Enum: `OETO`, `FEI`). * `Regelwerk`: Entscheidende Weiche für die Anwendungslogik (Enum: `OETO`, `FEI`).
* `Kategorie`: Offizielle Turnierkategorie (z.B. "CSN-A", "CSI2*", "CDI-W"). * `Kategorie`: Offizielle Turnierkategorie (z.B. "CSN-A", "CSI2*", "CDI-W").
* `Disziplinen`: Liste der angebotenen Sportarten (z.B. `Springen`, `Dressur`). * `Disziplinen`: Liste der angebotenen Sportarten (z.B. `Springen`, `Dressur`).
@ -55,11 +58,13 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
**Beispiele:** "Standardspringprüfung Kl. L", "Dressurprüfung Kl. M - Aufgabe M5". **Beispiele:** "Standardspringprüfung Kl. L", "Dressurprüfung Kl. M - Aufgabe M5".
**Attribute:** **Attribute:**
* `Bewerb-ID` (PK): Eindeutiger technischer Schlüssel. * `Bewerb-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Turnier_ID` (FK): Verweis auf das zugehörige `Turnier`. * `Turnier_ID` (FK): Verweis auf das zugehörige `Turnier`.
* `Nummer`: Die offizielle Nummer des Bewerbs laut Ausschreibung (z.B. "05"). * `Nummer_Intern`: 2-stellige Nummer (z.B. `05`).
* `Nummer_Offiziell`: 3-stellige Nummer (z.B. `005`) für Turniere > 99 Bewerbe.
* `Abteilung`: Kennzeichen für Unterteilungen (z.B. `1`, `2`). Default `0`.
* `Titel`: Der offizielle Titel des Bewerbs. * `Titel`: Der offizielle Titel des Bewerbs.
* `Startgeld`: Das für diesen Bewerb zu entrichtende Startgeld. * `Startgeld`: Das für diesen Bewerb zu entrichtende Startgeld (in EUR).
* `Startberechtigung_Text`: Textuelle Beschreibung der Teilnahmevoraussetzungen. * `Startberechtigung_Text`: Textuelle Beschreibung der Teilnahmevoraussetzungen.
* `Besondere_Bestimmungen`: Spezielle Regeln nur für diesen Bewerb. * `Besondere_Bestimmungen`: Spezielle Regeln nur für diesen Bewerb.
@ -72,7 +77,7 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
**Beispiele:** "Casino Grand Prix 2026", "OÖ Landesmeisterschaft Dressur Allgemeine Klasse". **Beispiele:** "Casino Grand Prix 2026", "OÖ Landesmeisterschaft Dressur Allgemeine Klasse".
**Attribute:** **Attribute:**
* `Serie-ID` (PK): Eindeutiger technischer Schlüssel. * `Serie-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Name`: Offizieller Name der Serie. * `Name`: Offizieller Name der Serie.
* `Saison`: Das Jahr, in dem die Serie stattfindet. * `Saison`: Das Jahr, in dem die Serie stattfindet.
* `Reglement_Text`: Die spezifischen Regeln für die Wertung (Punktesystem, etc.). * `Reglement_Text`: Die spezifischen Regeln für die Wertung (Punktesystem, etc.).
@ -83,37 +88,43 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
### 5. Entität: `Akteur` ### 5. Entität: `Akteur`
**Zweck:** Zentrale, widerspruchsfreie Verwaltung aller beteiligten Personen und Organisationen, unabhängig von ihrer Rolle. **Zweck:** Zentrale, widerspruchsfreie Verwaltung aller beteiligten Personen und Organisationen.
**Beispiele:** Ein Reiter, ein Pferdebesitzer, ein Züchter, ein Richter, ein Reitverein. **Beispiele:** Ein Reiter, ein Pferdebesitzer, ein Züchter, ein Richter, ein Reitverein.
**Attribute:** **Attribute:**
* `Akteur-ID` (PK): Eindeutiger technischer Schlüssel. * `Akteur-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Typ`: `PERSON` oder `ORGANISATION`. * `Typ`: `PERSON` oder `ORGANISATION`.
* `Name`: Vollständiger Name der Person oder Organisation. * `Name`: Vollständiger Name der Person oder Organisation.
* `Kontakt`: Adress- und Kontaktdaten. * `Kontakt`: Adress- und Kontaktdaten.
* `Rollen`: Eine Liste der Rollen, die dieser Akteur einnimmt (z.B. `REITER`, `PFERDEBESITZER`, `ZÜCHTER`, `FUNKTIONÄR`, `VERANSTALTER`). * `Rollen`: Liste der Rollen (z.B. `REITER`, `RICHTER`).
* `Identifikatoren`: Ein flexibler Speicher (z.B. JSON oder eigene Tabelle) für alle offiziellen Nummern: * **OEPS-Daten (für Personen):**
* `OEPS-Lizenznummer` * `Satznummer`: 6-stellig, numerisch (Primärschlüssel OEPS).
* `FEI-ID` * `Lizenz`: Aktueller Lizenzcode (z.B. "R1").
* `Mitgliedsnummer_Zuchtverband` * `Startkarte`: Boolean/Status (Jahresgebühr bezahlt?).
* `Verein_ID`: Verweis auf den Stammverein.
* **Identifikatoren (Sonstige):**
* `FEI-ID`
* `Mitgliedsnummer_Zuchtverband`
--- ---
### 6. Entität: `Pferd` ### 6. Entität: `Pferd`
**Zweck:** Zentrale Verwaltung aller Pferde, egal ob im Sport oder in der Zucht, mit all ihren unterschiedlichen Identitäten. **Zweck:** Zentrale Verwaltung aller Pferde, egal ob im Sport oder in der Zucht.
**Beispiele:** Ein international erfolgreiches Sportpferd, eine Zuchtstute, ein junges Pferd in Ausbildung. **Beispiele:** Ein international erfolgreiches Sportpferd, eine Zuchtstute.
**Attribute:** **Attribute:**
* `Pferd-ID` (PK): Eindeutiger technischer Schlüssel. * `Pferd-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
* `Name`: Offizieller Name des Pferdes. * `Name`: Offizieller Name des Pferdes.
* `Abstammung_Vater_ID` (FK): Verweis auf ein anderes `Pferd` (Vater). * `Abstammung_Vater_ID` (FK): Verweis auf ein anderes `Pferd` (Vater).
* `Abstammung_Mutter_ID` (FK): Verweis auf ein anderes `Pferd` (Mutter). * `Abstammung_Mutter_ID` (FK): Verweis auf ein anderes `Pferd` (Mutter).
* `Besitzer_ID` (FK): Verweis auf den `Akteur`, dem das Pferd gehört. * `Besitzer_ID` (FK): Verweis auf den `Akteur`, dem das Pferd gehört.
* `Identifikatoren`: Ein flexibler Speicher für alle offiziellen Nummern: * **OEPS-Daten:**
* `Lebensnummer` (aus der Zucht) * `Satznummer`: 10-stellig, numerisch (Primärschlüssel OEPS).
* `OEPS-Registrierungsnummer` * `Kopfnummer`: 4-stellig, alphanumerisch (Permanente ID).
* `FEI-ID` * `Lebensnummer`: 9-stellig (Zuchtnummer).
* `Chip-Nummer` * **FEI-Daten:**
* `FEI-ID`: Eindeutige FEI-Nummer.
* `FEI-Pass`: Passnummer (kann abweichen).

View File

@ -0,0 +1,241 @@
-- Database Schema Draft for Meldestelle (Offline-First)
-- Dialect: SQLite (compatible with SQLDelight)
-- Status: Draft / Proposal
-- Based on: OEPS Legacy Spec V2.4 & Domain Analysis
-- ==================================================================
-- 1. CORE INFRASTRUCTURE (Sync & Audit)
-- ==================================================================
-- Every table should ideally have these fields, but for brevity
-- they are implied or added where critical.
-- id: TEXT NOT NULL PRIMARY KEY (UUID)
-- created_at: INTEGER NOT NULL (Epoch Millis)
-- updated_at: INTEGER NOT NULL (Epoch Millis)
-- version: INTEGER NOT NULL (Optimistic Locking / Sync Counter)
-- is_deleted: INTEGER NOT NULL DEFAULT 0 (Soft Delete)
-- ==================================================================
-- 2. MASTER DATA (Stammdaten)
-- ==================================================================
-- Akteure: Personen und Organisationen
-- Covers: Reiter, Richter, Besitzer, Vereine
CREATE TABLE actor (
id TEXT NOT NULL PRIMARY KEY,
type TEXT NOT NULL, -- 'PERSON', 'ORGANIZATION'
-- Display Data
first_name TEXT, -- NULL for Organizations
last_name TEXT NOT NULL, -- Name or Org-Name
-- OEPS Specifics (Legacy Spec)
oeps_id TEXT, -- 'Satznummer' (6 digits for Person, 4 for Club)
oeps_category TEXT, -- 'Verein', 'Reiter', 'Richter'
-- Licenses & Status
license_code TEXT, -- e.g. 'R1', 'RD3'
has_start_card INTEGER NOT NULL DEFAULT 0, -- Boolean: Paid annual fee?
is_locked INTEGER NOT NULL DEFAULT 0, -- Boolean: Sperrliste?
-- Contact & Meta
nationality TEXT NOT NULL DEFAULT 'AUT', -- ISO 3-Letter
contact_json TEXT, -- Address, Phone, Email
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
version INTEGER NOT NULL DEFAULT 1
);
CREATE INDEX idx_actor_oeps_id ON actor(oeps_id);
CREATE INDEX idx_actor_name ON actor(last_name, first_name);
-- Pferde
CREATE TABLE horse (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
-- Identification
oeps_id TEXT, -- 'Satznummer' (10 digits) - CRITICAL for Export
head_number_permanent TEXT, -- 'Kopfnummer' (e.g. A123)
life_number TEXT, -- 'Lebensnummer' (Zucht)
fei_id TEXT,
-- Details
birth_year INTEGER,
gender TEXT, -- 'M', 'W', 'G' (Gelding/Wallach)
color TEXT,
sire_name TEXT, -- Vater (Denormalized for search)
dam_name TEXT, -- Mutter
-- Owner Link
owner_id TEXT, -- FK to actor.id
-- Status
is_locked INTEGER NOT NULL DEFAULT 0, -- Sperrliste
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
version INTEGER NOT NULL DEFAULT 1
);
CREATE INDEX idx_horse_oeps_id ON horse(oeps_id);
CREATE INDEX idx_horse_head_num ON horse(head_number_permanent);
CREATE INDEX idx_horse_name ON horse(name);
-- ==================================================================
-- 3. EVENT STRUCTURE
-- ==================================================================
CREATE TABLE event (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
start_date INTEGER NOT NULL, -- Epoch Day
end_date INTEGER NOT NULL,
location TEXT,
organizer_id TEXT NOT NULL, -- FK to actor.id
status TEXT NOT NULL DEFAULT 'PLANNING' -- PLANNING, ACTIVE, ARCHIVED
);
CREATE TABLE tournament (
id TEXT NOT NULL PRIMARY KEY,
event_id TEXT NOT NULL REFERENCES event(id),
-- OEPS Spec
oeps_number TEXT NOT NULL, -- 5 digits (e.g. 21001)
category TEXT, -- e.g. 'CSN-A'
ruleset TEXT NOT NULL DEFAULT 'OETO', -- 'OETO', 'FEI'
-- Sync Meta
updated_at INTEGER NOT NULL
);
-- Bewerbe (Competitions)
-- Note: If a competition is split into 2 departments (Abteilungen),
-- we create 2 rows here to match the OEPS 'B-Satz' logic.
CREATE TABLE competition (
id TEXT NOT NULL PRIMARY KEY,
tournament_id TEXT NOT NULL REFERENCES tournament(id),
-- Identification
code_internal TEXT NOT NULL, -- '01', '02' (2 digits)
code_official TEXT, -- '001' (3 digits, optional)
division_id INTEGER NOT NULL DEFAULT 0, -- 'Abteilung' (0=None, 1=1st, 2=2nd)
-- Description
title TEXT NOT NULL,
category TEXT, -- e.g. 'LM', 'S*'
discipline TEXT NOT NULL, -- 'D', 'S', 'C' (Dressage, Jumping, Combined)
-- Rules & Scoring
scoring_method TEXT NOT NULL, -- 'A0', 'C', 'DRESSAGE_PERCENT'
start_fee INTEGER NOT NULL DEFAULT 0, -- In Cents
-- State
status TEXT NOT NULL DEFAULT 'OPEN', -- OPEN, CLOSED_FOR_ENTRIES, RUNNING, FINISHED, SIGNED_OFF
-- Sync Meta
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_comp_tournament ON competition(tournament_id);
-- ==================================================================
-- 4. SPORT & PROCESS
-- ==================================================================
-- Nennungen (Entries)
-- Represents the intent to start.
CREATE TABLE entry (
id TEXT NOT NULL PRIMARY KEY,
competition_id TEXT NOT NULL REFERENCES competition(id),
-- The Pair
horse_id TEXT NOT NULL REFERENCES horse(id),
rider_id TEXT NOT NULL REFERENCES actor(id),
-- Financials
responsible_person_id TEXT REFERENCES actor(id), -- Who pays?
fee_agreed INTEGER NOT NULL, -- In Cents (Snapshot of price at entry time)
payment_status TEXT NOT NULL DEFAULT 'PENDING', -- PENDING, PAID, WAIVED
-- Validation Override (The "Human Factor")
validation_status TEXT NOT NULL DEFAULT 'OK', -- OK, WARNING, BLOCKED
override_comment TEXT, -- Why was this allowed despite warning?
-- Sync Meta
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_entry_comp ON entry(competition_id);
CREATE INDEX idx_entry_rider ON entry(rider_id);
-- Startliste (Start Order)
-- Subset of entries that actually start.
CREATE TABLE start_list_entry (
id TEXT NOT NULL PRIMARY KEY,
entry_id TEXT NOT NULL REFERENCES entry(id),
-- Ordering
start_order INTEGER, -- 1, 2, 3...
start_time_planned INTEGER, -- Epoch Millis (optional)
-- Tournament Specifics
head_number_event TEXT, -- Startnummer am Turnier (kann von A123 abweichen)
-- Status
status TEXT NOT NULL DEFAULT 'READY', -- READY, STARTED, DNS (Did Not Start)
UNIQUE(entry_id)
);
-- Ergebnisse (Results)
CREATE TABLE result (
id TEXT NOT NULL PRIMARY KEY,
start_list_entry_id TEXT NOT NULL REFERENCES start_list_entry(id),
-- The Outcome
rank INTEGER, -- 1, 2, 3... (NULL if eliminated)
-- Scoring Details (Polymorphic based on Competition Type)
points_jump_faults DECIMAL(5,2), -- Springfehler
time_taken_ms INTEGER, -- Zeit in Millisekunden
score_dressage_percent DECIMAL(5,3), -- 72.500
score_dressage_total DECIMAL(6,2), -- Summe Punkte
-- Status Flags
classification TEXT NOT NULL DEFAULT 'OK', -- OK, EL (Elim), RET (Retired), DIS (Disq)
-- Detailed Marks (JSON)
-- e.g. { "judge_C": 7.5, "judge_H": 7.2, "obstacles": [...] }
details_json TEXT,
-- Money
prize_money INTEGER DEFAULT 0, -- In Cents
-- Audit
updated_by_user_id TEXT,
updated_at INTEGER NOT NULL
);
CREATE INDEX idx_result_starter ON result(start_list_entry_id);
-- ==================================================================
-- 5. AUDIT LOG (NFR-07)
-- ==================================================================
CREATE TABLE audit_log (
id TEXT NOT NULL PRIMARY KEY,
entity_type TEXT NOT NULL, -- 'RESULT', 'ENTRY'
entity_id TEXT NOT NULL,
action TEXT NOT NULL, -- 'CREATE', 'UPDATE', 'DELETE'
user_id TEXT,
timestamp INTEGER NOT NULL,
changes_json TEXT -- { "score_old": 7.0, "score_new": 7.5 }
);

View File

@ -0,0 +1,75 @@
# Analyse der Legacy-Spezifikation (OEPS Pflichtenheft 2021 V2.4)
* **Datum:** 2026-01-14
* **Quelle:** `docs/03_Domain/02_Reference/Legacy_Specs/OETO-2026_Meldestelle_Pflichtenheft_V2.4_2021-07-28.md`
* **Status:** Draft
## 1. Zusammenfassung
Das Pflichtenheft definiert das Datenaustauschformat zwischen Meldestellen-Software und dem OEPS (Österreichischer Pferdesportverband). Es ist die **maßgebliche technische Referenz** für nationale Turniere in Österreich. Die Einhaltung dieser Spezifikation ist zwingend erforderlich, um Ergebnisse an den Verband zu melden.
## 2. Kritische Datenfelder & Identifikatoren
Die Analyse zeigt, dass das aktuelle `Core_Model` (`Overview.md`) zu generisch ist. Für den operativen Betrieb fehlen essenzielle Identifikatoren.
### 2.1. Identifikation von Personen & Pferden
Das System verlässt sich nicht primär auf Namen, sondern auf **Satznummern**.
* **Pferd:**
* `Satznummer` (10-stellig, numerisch): Der primäre Key im OEPS-System. Muss zwingend persistiert und exportiert werden.
* `Kopfnummer` (4-stellig, alphanumerisch):
* National: Die permanente Registrierungsnummer beim OEPS.
* International: Eine turnierspezifische Startnummer.
* `Lebensnummer` (9-stellig): Zuchtnummer. Achtung: Bei ausländischen Pferden oft generiert/fiktiv -> Nicht zur Suche geeignet!
* `FEI-Pass` vs. `FEI-ID`: Zwei getrennte Felder!
* **Reiter:**
* `Satznummer` (6-stellig, numerisch): Der primäre Key.
* `Lizenz` (z.B. "RD1", "R1"): Bestimmt die Startberechtigung in Klassen.
* `Startkarte`: Flag, ob die Jahresgebühr bezahlt wurde. Ohne Startkarte keine Startberechtigung (außer Gastlizenzen).
### 2.2. Turnier & Bewerbsstruktur
Die Struktur ist starrer als im aktuellen Modell angenommen.
* **Turniernummer:** 5-stellig.
* **Bewerbe:**
* Haben eine 2-stellige Nummer (intern) UND eine 3-stellige Nummer (für Turniere > 99 Bewerbe).
* **Abteilungen:** Ein Bewerb kann in Abteilungen (Abt. 1, Abt. 2...) unterteilt sein. Dies ist keine rein organisatorische Trennung, sondern datentechnisch relevant (Feld `ABTEILUNG`).
## 3. Implizite Geschäftsregeln
Aus den Datenfeldern lassen sich harte Business Rules ableiten:
1. **Startberechtigung (Sperrliste):** Es gibt ein Flag `SPERRLISTE`. Wenn gesetzt, muss das System warnen/blockieren. Grund oft: Offene Forderungen.
2. **Nation-Logik (Gast vs. Inländer):**
* Ausländer mit österr. Lizenz + bezahlter Startkarte -> Startet für österr. Verein -> Nation im Ergebnis = "AUT".
* Ausländer ohne Mitgliedschaft -> Gastreiter -> Nation = Staatsbürgerschaft (z.B. "GER").
* *Konsequenz:* Die "Nation" eines Starts ist kontextabhängig und nicht rein statisch am Reiter hängend.
3. **Pferde-Status:** Pferde, für die >3 Jahre keine Gebühr bezahlt wurde, gelten als "nicht registriert" -> Neuanlage erforderlich.
## 4. Lücken im aktuellen Modell (Gap Analysis)
| Entität | Fehlendes Attribut / Konzept | Dringlichkeit |
| :--- | :--- | :--- |
| **Pferd** | `Satznummer` (OEPS-ID) | **Hoch** (Sync unmöglich ohne dies) |
| **Pferd** | Unterscheidung `Kopfnummer` (Permanent) vs. `Startnummer` (Turnier) | Mittel |
| **Akteur** | `Satznummer` (OEPS-ID) | **Hoch** |
| **Akteur** | `Startkarte` (Status) | Hoch (Validierung) |
| **Bewerb** | `Abteilung` (Sub-Struktur) | Mittel |
| **Ergebnis** | `Ausschluss-Typ` (Disqualifikation, Aufgabe, Ausschluss) | Mittel |
| **Ergebnis** | `Geldpreis` (Formatierung, Währung ist implizit EUR) | Niedrig |
## 5. Empfehlung für das Datenmodell
Wir müssen die Entität `Akteur` in spezifische Rollen-Modelle ausdifferenzieren oder per Composition erweitern, da die Attribute für Reiter (Lizenz, Startkarte) für andere Akteure (Richter, Besitzer) irrelevant oder anders sind.
**Vorschlag:**
* `Akteur` bleibt Basis (Name, Kontakt).
* `ReiterProfile` (Value Object / 1:1 Relation): Enthält `Satznummer`, `Lizenz`, `Startkarte`, `Sperrvermerk`.
* `Pferd` erhält `OEPS_Daten` (Value Object): `Satznummer`, `Kopfnummer`, `Lebensnummer`.
## 6. Offene Fragen an den PO
1. Wie gehen wir mit **internationalen Turnieren** (FEI) um? Das Pflichtenheft deutet an, dass auch hier OEPS-Formate genutzt werden ("Version 2.4 für internationale Bewerbe"), aber die FEI hat eigene Formate. Welches ist führend?
2. Soll das System den **Import** der `zns.zip` (Stammdaten) unterstützen? Das wäre essenziell für den Offline-Betrieb.
3. Wie strikt soll die **Validierung** sein? Soll das System eine Nennung *verhindern*, wenn die Startkarte fehlt, oder nur *warnen*? (Realität: Oft wird vor Ort nachgezahlt).

View File

@ -0,0 +1,80 @@
# Non-Functional Requirements (NFRs) - Phase 1
* **Status:** Draft
* **Fokus:** Offline-First Architektur, Robustheit, Datenintegrität
---
## 1. Offline-Fähigkeit & Resilienz (Availability)
Das System muss in einer Umgebung funktionieren, in der Netzwerkverbindungen unzuverlässig oder nicht vorhanden sind (Reitställe, ländliche Gebiete).
* **NFR-01: Local-First Prinzip**
* Alle Kernfunktionen (Nennung, Startlistenerstellung, Ergebniserfassung, Drucken) müssen **zu 100% ohne Netzwerkverbindung** ausführbar sein.
* Die lokale Datenbank (SQLite/SQLDelight) ist die primäre Datenquelle für das UI.
* Der Server dient lediglich als Synchronisations-Hub und Backup, nicht als Laufzeit-Abhängigkeit.
* **NFR-02: Synchronisation & Konfliktlösung**
* Sobald eine Verbindung besteht, müssen Daten im Hintergrund synchronisiert werden.
* **Konfliktstrategie:** Bei konkurrierenden Änderungen (z.B. zwei Richter ändern dasselbe Ergebnis) muss das System:
1. Technische Konflikte automatisch lösen (z.B. "Last Write Wins" basierend auf präzisen Zeitstempeln).
2. Fachliche Konflikte protokollieren und zur manuellen Klärung markieren.
* **NFR-03: Wiederherstellung (Disaster Recovery)**
* Nach einem Absturz oder Stromausfall muss das System innerhalb von **< 30 Sekunden** wieder betriebsbereit sein.
* Kein Datenverlust von bereits bestätigten Eingaben (ACID-Transaktionen lokal).
---
## 2. Performance & Latenz (Usability)
Im Turnierbetrieb herrscht Zeitdruck. Wartezeiten summieren sich und führen zu Stress bei den Anwendern.
* **NFR-04: Optimistic UI Updates**
* Benutzeraktionen (z.B. Speichern einer Note) müssen im UI **sofort (< 50ms)** bestätigt werden, ohne auf Netzwerk-Roundtrips oder Datenbank-Commits zu warten (Asynchrone Verarbeitung).
* **NFR-05: Such-Performance**
* Die Suche nach Pferden (in > 50.000 Stammdaten) oder Reitern muss **< 200ms** dauern (Full-Text-Search Indexierung lokal).
* Dies gilt auch auf leistungsschwächerer Hardware (ältere Laptops, Tablets).
* **NFR-06: Massendaten-Verarbeitung**
* Der Import der `zns.zip` (Stammdaten) darf den UI-Thread nicht blockieren und sollte **< 5 Minuten** dauern.
---
## 3. Datenintegrität & Audit (Compliance)
Ergebnisse entscheiden über Qualifikationen und Preisgelder. Manipulationen oder versehentliche Änderungen müssen nachvollziehbar sein.
* **NFR-07: Audit Trail**
* Jede Änderung an einem Ergebnis (Score, Zeit, Platzierung) muss unveränderbar protokolliert werden.
* Inhalt: `Timestamp`, `User-ID`, `Old-Value`, `New-Value`, `Reason` (optional).
* Der Audit-Log muss mit synchronisiert werden.
* **NFR-08: Validierungs-Hierarchie**
* Das System muss zwischen "Hard Constraints" (Datenbank-Integrität, z.B. Foreign Keys) und "Soft Constraints" (Fachliche Regeln, z.B. fehlende Startkarte) unterscheiden.
* Soft Constraints dürfen den Prozess nicht blockieren, müssen aber persistente Warnungen erzeugen ("Override"-Flag).
---
## 4. Sicherheit (Security)
* **NFR-09: Lokale Datensicherheit**
* Da Laptops/Tablets gestohlen werden können: Sensible Daten (Personendaten, Adressen) sollten "At Rest" verschlüsselt sein (z.B. SQLCipher), sofern die Performance (NFR-05) nicht kritisch beeinträchtigt wird.
* Minimalanforderung: Keine Speicherung von Passwörtern im Klartext.
* **NFR-10: Rollenbasierter Zugriff (RBAC)**
* Unterscheidung der Berechtigungen im UI:
* *Richter:* Darf nur Ergebnisse für zugewiesene Bewerbe eingeben.
* *Meldestelle:* Vollzugriff.
* *Zuschauer (Kiosk-Mode):* Nur Lesezugriff auf Starter-/Ergebnislisten.
---
## 5. Hardware & Umgebung
* **NFR-11: Eingabe-Effizienz**
* Die Ergebniserfassung muss "Keyboard-First" bedienbar sein (Nummernblock-Optimierung). Maus/Touch ist für Massenerfassung zu langsam.
* **NFR-12: Druck-Unterstützung**
* Unterstützung von lokalen Druckern (USB/Netzwerk) ohne komplexe Treiber-Installation, da Listen (Starterlisten, Ergebnisse) physisch ausgehängt werden müssen (Pflicht laut Reglement).

View File

@ -0,0 +1,112 @@
# Use Cases Draft - Phase 1 (Core Domain)
* **Status:** Draft
* **Fokus:** High-Level Prozessflüsse und Systemgrenzen
---
## Cluster 1: Turnier-Initialisierung & Datenbasis
### UC-01: Turnier-Stammdaten importieren
* **Akteur:** Meldestellen-Leiter
* **Auslöser:** Vorbereitung eines neuen Turniers oder Update am Turniermorgen.
* **Vorbedingung:** `zns.zip` (oder äquivalente OEPS-Daten) liegt vor.
* **Ablauf:**
1. System liest die Datensätze für Pferde, Reiter, Vereine und Funktionäre.
2. System aktualisiert die lokale Datenbank (Insert/Update).
3. System markiert Datensätze mit Sperrvermerken oder fehlenden Lizenzen.
* **Nachbedingung:** Die lokale Datenbank ist die "Single Source of Truth" für Validierungen.
### UC-02: Turnier-Konfiguration anlegen
* **Akteur:** Meldestellen-Leiter
* **Auslöser:** Erstellung eines neuen Events.
* **Vorbedingung:** Ausschreibung liegt vor.
* **Ablauf:**
1. Akteur definiert Stammdaten (Ort, Datum, Veranstalter).
2. Akteur legt Bewerbe an (Nummer, Klasse, Richtverfahren).
3. Akteur definiert Gebühren (Nenngeld, Startgeld, Boxenpreise).
* **Nachbedingung:** Das Turniergerüst steht bereit für Nennungen.
---
## Cluster 2: Nennungs-Management (Pre-Competition)
### UC-03: Nennung erfassen & validieren
* **Akteur:** Meldestellen-Mitarbeiter
* **Auslöser:** Import von Online-Nennungen oder manuelle Eingabe.
* **Ablauf:**
1. System prüft Existenz von Reiter und Pferd (via Satznummer).
2. **Validierung:**
* Ist die Startkarte bezahlt?
* Ist die Lizenz ausreichend für die Klasse?
* Liegt eine Sperre vor?
* Ist das Pferd geimpft/registriert?
3. Bei Validierungsfehler: System zeigt Warnung, erlaubt aber "Override" durch Akteur (z.B. "Zahlung erfolgt").
4. System verknüpft Paar mit Bewerb.
* **Nachbedingung:** Das Paar ist auf der "Nennliste" (noch nicht Starterliste).
### UC-04: Pferd/Reiter tauschen
* **Akteur:** Meldestellen-Mitarbeiter
* **Auslöser:** Reiter fällt aus oder Pferd ist lahm.
* **Ablauf:**
1. Akteur wählt bestehende Nennung.
2. Akteur tauscht Reiter ODER Pferd aus.
3. System führt Validierung (UC-03) für die neue Kombination durch.
4. System protokolliert den Tausch (relevant für T-Satz im Export).
* **Nachbedingung:** Nennung ist aktualisiert, Historie ist gewahrt.
---
## Cluster 3: Durchführung & Sport (Competition)
### UC-05: Startliste erstellen
* **Akteur:** Meldestellen-Leiter
* **Auslöser:** Nennschluss für einen Bewerb ist erreicht.
* **Ablauf:**
1. Akteur definiert Startreihenfolge (z.B. "Alphabetisch", "Gelost", "Nach Lizenz").
2. System generiert die Reihenfolge.
3. System weist Kopfnummern zu (falls noch nicht geschehen).
4. System teilt bei Bedarf in Abteilungen (siehe US-005).
* **Nachbedingung:** Die Startliste ist fixiert und kann gedruckt/publiziert werden.
### UC-06: Ergebnis erfassen
* **Akteur:** Richter / Schreiber / Zeitnehmung
* **Auslöser:** Ein Ritt ist beendet.
* **Ablauf:**
1. Akteur wählt Starter.
2. Akteur gibt Rohdaten ein (Zeit, Fehlerpunkte, Wertnote).
3. System berechnet sofort den Score und den vorläufigen Rang.
4. System prüft auf Spezialfälle (Ausschluss, Aufgabe).
* **Nachbedingung:** Ergebnis ist gespeichert, Live-Ranking ist aktualisiert.
### UC-07: Bewerb abschließen
* **Akteur:** Meldestellen-Leiter / Hauptrichter
* **Auslöser:** Letzter Reiter ist fertig, Einspruchsfrist abgelaufen.
* **Ablauf:**
1. System finalisiert die Rangierung (inkl. Ex-Aequo Regeln).
2. System berechnet Geldpreise gemäß Ausschreibung und Teilnehmerzahl.
3. System sperrt den Bewerb für Änderungen.
* **Nachbedingung:** Ergebnisse sind "amtlich", Geldpreise sind den Konten gutgeschrieben.
---
## Cluster 4: Abschluss & Finanzen
### UC-08: Konto abrechnen (Kassieren)
* **Akteur:** Kassen-Mitarbeiter
* **Auslöser:** Teilnehmer will abreisen/bezahlen.
* **Ablauf:**
1. System aggregiert alle Kosten (Nenngelder, Boxen, Gebühren) pro "Verantwortlicher Person".
2. System zieht gewonnene Geldpreise ab.
3. System erstellt Saldo.
4. Akteur verbucht Zahlungseingang.
* **Nachbedingung:** Konto ist ausgeglichen, "Horse Pass" kann ausgegeben werden.
### UC-09: OEPS-Export durchführen
* **Akteur:** Meldestellen-Leiter
* **Auslöser:** Turnierende.
* **Ablauf:**
1. System prüft Datenintegrität (Alle Pflichtfelder für Export vorhanden?).
2. System generiert `XXXXX.ERG` Datei gemäß Spezifikation V2.4.
3. System erstellt Protokoll über eventuelle Warnungen/Abweichungen.
* **Nachbedingung:** Export-Datei liegt bereit zur Übermittlung.

View File

@ -0,0 +1,109 @@
# User Stories Draft - Phase 1 (Core Domain)
* **Status:** Draft
* **Fokus:** Nationale Turniere (OEPS), Offline-Betrieb, Basis-Verwaltung
---
## Epic 1: Stammdaten & Offline-Vorbereitung
### US-001: Import der Verbands-Stammdaten (ZNS)
**Als** Meldestellen-Leiter
**möchte ich** die offizielle `zns.zip` Datei (Pferde, Reiter, Vereine, Richter) in das System importieren,
**damit** ich auch ohne Internetverbindung Zugriff auf alle validen Lizenz- und Pferdedaten habe.
* **Akzeptanzkriterien:**
* System akzeptiert `zns.zip` oder entpackte `.dat` Dateien (Codepage 850).
* Importiert `PFERDE01.dat` (inkl. Mapping der 10-stelligen Satznummer).
* Importiert `LIZENZ01.dat` (inkl. Startkarten-Status und Sperrvermerke).
* Der Import ist performant genug, um am Turniermorgen aktualisiert zu werden (< 5 Min).
* Fehlerhafte Datensätze werden protokolliert, brechen den Import aber nicht ab.
### US-002: Intelligente Akteur-Suche
**Als** Meldestellen-Mitarbeiter
**möchte ich** Reiter und Pferde über eine fehlertolerante Suche finden (Name, Kopfnummer, Lizenznummer),
**damit** ich Nennungen schnell erfassen kann, auch wenn der Reiter seine genaue Nummer nicht weiß.
* **Akzeptanzkriterien:**
* Suche nach Pferdenamen (Teilübereinstimmung).
* Suche nach Kopfnummer (z.B. "A123").
* Anzeige von Warnhinweisen direkt im Suchergebnis (z.B. "Sperrliste", "Keine Startkarte").
* Unterscheidung bei Namensgleichheit durch Anzeige von Verein/Jahrgang/Abstammung.
---
## Epic 2: Nennung & Check-in
### US-003: Validierung der Startberechtigung (Startkarte)
**Als** Meldestellen-Leiter
**möchte ich**, dass das System mich warnt, wenn ein Reiter für einen Bewerb nennt, aber keine aktive Startkarte (Jahresgebühr) hat,
**damit** ich ihn zur Nachzahlung auffordern kann.
* **Akzeptanzkriterien:**
* Prüfung des Flags `STARTKARTE` aus den Stammdaten.
* Prüfung der Lizenzklasse (z.B. darf "R1" nicht in Klasse S starten).
* **Wichtig:** Das System darf die Nennung *nicht* blockieren (Soft-Validation), sondern muss einen "Override" ermöglichen (z.B. "Zahlung vor Ort erfolgt").
* Visuelle Hervorhebung in der Starterliste (z.B. roter Status).
### US-004: Manuelle Nachnennung vor Ort
**Als** Meldestellen-Mitarbeiter
**möchte ich** ein Pferd-Reiter-Paar kurzfristig zu einem Bewerb hinzufügen,
**damit** Teilnehmer, die die Online-Nennfrist verpasst haben, gegen Gebühr noch starten können.
* **Akzeptanzkriterien:**
* Auswahl von Bewerb, Reiter und Pferd.
* Automatische Berechnung der erhöhten Nenngebühr (Nachnenngebühr).
* Vergabe einer Startnummer (fortlaufend oder manuell).
* Eintrag in die `KKARTEI` (Nennliste) und `BBEWERBE` (Starterliste).
---
## Epic 3: Bewerbs-Abwicklung
### US-005: Verwaltung von Abteilungen
**Als** Meldestellen-Leiter
**möchte ich** einen Bewerb mit vielen Startern in mehrere Abteilungen (z.B. R1-Reiter vs. R2-Reiter) unterteilen,
**damit** ich getrennte Ergebnislisten und Platzierungen erstellen kann, wie es die ÖTO verlangt.
* **Akzeptanzkriterien:**
* Ein Bewerb kann in n Abteilungen gesplittet werden.
* Starter können per Drag&Drop oder Regel (z.B. "Alle R1 in Abt. 1") zugewiesen werden.
* Jede Abteilung hat eine eigene Platzierung, aber sie teilen sich die gleichen Prüfungsparameter (Parcours).
* Export berücksichtigt das Feld `ABTEILUNG` im B-Satz.
### US-006: Ergebniserfassung & Platzierung
**Als** Richter oder Schreiber
**möchte ich** Ergebnisse (Zeit, Fehler, Wertnote) für einen Starter eingeben,
**damit** die Rangierung automatisch berechnet wird.
* **Akzeptanzkriterien:**
* Eingabemaske optimiert für schnelle Nummernblock-Eingabe.
* Automatische Berechnung der Rangfolge basierend auf dem Regelwerk (Fehler/Zeit vs. Wertnote).
* Handling von Spezialfällen: Ausschluss (EL), Aufgabe (RET), Disqualifikation (DQ), Nicht angetreten (DNS).
* Sofortige Aktualisierung der "Live-Ergebnisse".
---
## Epic 4: Abschluss & Export
### US-007: OEPS-Konformer Ergebnis-Export
**Als** Meldestellen-Leiter
**möchte ich** die Ergebnisse des Turniers in das definierte Format (ASCII, Codepage 850) exportieren,
**damit** ich meiner Meldepflicht gegenüber dem Verband nachkommen kann.
* **Akzeptanzkriterien:**
* Erstellung der `XXXXX.ERG` Datei.
* Strikte Einhaltung der Spaltenbreiten und Formate (siehe Legacy Spec Analyse).
* Validierung vor Export: Warnung bei fehlenden Satznummern oder ungültigen Codes.
* Korrekte Zuordnung der Nation (Gast vs. Inländer).
### US-008: Kassenabschluss & Abrechnung
**Als** Veranstalter
**möchte ich** eine Liste aller offenen Posten (Nenngelder, Boxen, Nachnenngebühren) pro Reiter/Verein sehen,
**damit** ich vor der Ausgabe der Pferdepässe kassieren kann.
* **Akzeptanzkriterien:**
* Aggregierte Ansicht pro "Verantwortlicher Person" (Zahler).
* Auflistung aller Posten (Nennung, Startgeld, Gebühren).
* Verrechnung von gewonnenen Geldpreisen (Gutschrift).
* Druckfunktion für Rechnung/Quittung.

View File

@ -0,0 +1,46 @@
# Session Log: Domain Analysis & Core Model Definition
* **Datum:** 2026-01-15
* **Rolle:** Domain/Product Expert
* **Teilnehmer:** User (Stefan)
* **Status:** Abgeschlossen
## Ziele der Session
1. Analyse der bestehenden Dokumentation (insb. OEPS Pflichtenheft).
2. Schärfung des Domänenmodells für nationale Turniere.
3. Erstellung von User Stories, Use Cases und NFRs.
4. Ableitung eines konkreten Datenbankschemas (SQL) für die Offline-First-Architektur.
## Durchgeführte Arbeiten
### 1. Analyse & Glossar
* **Legacy Spec Analyse:** Das OEPS Pflichtenheft 2021 V2.4 wurde detailliert analysiert. Wichtigste Erkenntnis: Identifikation erfolgt über numerische `Satznummern`, nicht Namen.
* **Glossar:** `docs/03_Domain/00_Glossary.md` erstellt. Begriffe wie *Startkarte*, *Satznummer*, *Abteilung* definiert.
* **Core Model:** `docs/03_Domain/01_Core_Model/Entities/Overview.md` aktualisiert. Entitäten `Pferd` und `Akteur` um OEPS-spezifische Felder erweitert.
### 2. Anforderungen (Requirements)
* **User Stories:** `docs/03_Domain/03_Analysis/User_Stories_Draft.md` erstellt. Fokus auf Offline-Import (ZNS) und Fehlertoleranz ("Override").
* **Use Cases:** `docs/03_Domain/03_Analysis/Use_Cases_Draft.md` erstellt. Clusterung in Initialisierung, Nennung, Sport und Abschluss.
* **NFRs:** `docs/03_Domain/03_Analysis/Non_Functional_Requirements_Draft.md` erstellt. Fokus auf Local-First, Konfliktlösung und Audit-Sicherheit.
### 3. Technisches Design
* **Datenbankschema:** `docs/03_Domain/01_Core_Model/Entities/Database_Schema.sql` erstellt.
* Verwendung von UUIDs (`TEXT`) für Offline-Kompatibilität.
* Modellierung von `competition` mit `division_id` für Abteilungen.
* Einführung von `audit_log` und `version` Feldern für Sync.
## Ergebnisse & Artefakte
| Artefakt | Pfad | Status |
| :--- | :--- | :--- |
| Glossar | `docs/03_Domain/00_Glossary.md` | Final |
| Core Model | `docs/03_Domain/01_Core_Model/Entities/Overview.md` | Updated |
| Legacy Analyse | `docs/03_Domain/03_Analysis/Legacy_Spec_Analysis_2026-01.md` | Draft |
| User Stories | `docs/03_Domain/03_Analysis/User_Stories_Draft.md` | Draft |
| Use Cases | `docs/03_Domain/03_Analysis/Use_Cases_Draft.md` | Draft |
| NFRs | `docs/03_Domain/03_Analysis/Non_Functional_Requirements_Draft.md` | Draft |
| DB Schema | `docs/03_Domain/01_Core_Model/Entities/Database_Schema.sql` | Proposal |
## Nächste Schritte
* **Review:** Architekt und Backend-Dev müssen das Schema prüfen.
* **Implementierung:** Übertragung des SQL-Schemas in SQLDelight (`.sq` Dateien) im KMP-Modul.
* **Prototyping:** Erster "Walking Skeleton" für den ZNS-Import basierend auf den User Stories.