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:
@@ -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 }
|
||||
);
|
||||
@@ -1,6 +1,8 @@
|
||||
# 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
|
||||
|
||||
@@ -20,7 +22,7 @@ Dieses Dokument definiert die zentralen fachlichen Entitäten (Kern-Entitäten)
|
||||
**Beispiele:** "Apropos Pferd 2026", "Vereinsturnier Reitclub XY".
|
||||
|
||||
**Attribute:**
|
||||
* `Event-ID` (PK): Eindeutiger technischer Schlüssel.
|
||||
* `Event-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
|
||||
* `Name`: Offizieller Name des Events.
|
||||
* `Veranstaltungsort`: Adresse und Name der Anlage.
|
||||
* `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".
|
||||
|
||||
**Attribute:**
|
||||
* `Turnier-ID` (PK): Eindeutiger technischer Schlüssel.
|
||||
* `Turnier-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
|
||||
* `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`).
|
||||
* `Kategorie`: Offizielle Turnierkategorie (z.B. "CSN-A", "CSI2*", "CDI-W").
|
||||
* `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".
|
||||
|
||||
**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`.
|
||||
* `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.
|
||||
* `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.
|
||||
* `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".
|
||||
|
||||
**Attribute:**
|
||||
* `Serie-ID` (PK): Eindeutiger technischer Schlüssel.
|
||||
* `Serie-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
|
||||
* `Name`: Offizieller Name der Serie.
|
||||
* `Saison`: Das Jahr, in dem die Serie stattfindet.
|
||||
* `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`
|
||||
|
||||
**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.
|
||||
|
||||
**Attribute:**
|
||||
* `Akteur-ID` (PK): Eindeutiger technischer Schlüssel.
|
||||
* `Akteur-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
|
||||
* `Typ`: `PERSON` oder `ORGANISATION`.
|
||||
* `Name`: Vollständiger Name der Person oder Organisation.
|
||||
* `Kontakt`: Adress- und Kontaktdaten.
|
||||
* `Rollen`: Eine Liste der Rollen, die dieser Akteur einnimmt (z.B. `REITER`, `PFERDEBESITZER`, `ZÜCHTER`, `FUNKTIONÄR`, `VERANSTALTER`).
|
||||
* `Identifikatoren`: Ein flexibler Speicher (z.B. JSON oder eigene Tabelle) für alle offiziellen Nummern:
|
||||
* `OEPS-Lizenznummer`
|
||||
* `FEI-ID`
|
||||
* `Mitgliedsnummer_Zuchtverband`
|
||||
* `Rollen`: Liste der Rollen (z.B. `REITER`, `RICHTER`).
|
||||
* **OEPS-Daten (für Personen):**
|
||||
* `Satznummer`: 6-stellig, numerisch (Primärschlüssel OEPS).
|
||||
* `Lizenz`: Aktueller Lizenzcode (z.B. "R1").
|
||||
* `Startkarte`: Boolean/Status (Jahresgebühr bezahlt?).
|
||||
* `Verein_ID`: Verweis auf den Stammverein.
|
||||
* **Identifikatoren (Sonstige):**
|
||||
* `FEI-ID`
|
||||
* `Mitgliedsnummer_Zuchtverband`
|
||||
|
||||
---
|
||||
|
||||
### 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:**
|
||||
* `Pferd-ID` (PK): Eindeutiger technischer Schlüssel.
|
||||
* `Pferd-ID` (PK): Eindeutiger technischer Schlüssel (UUID).
|
||||
* `Name`: Offizieller Name des Pferdes.
|
||||
* `Abstammung_Vater_ID` (FK): Verweis auf ein anderes `Pferd` (Vater).
|
||||
* `Abstammung_Mutter_ID` (FK): Verweis auf ein anderes `Pferd` (Mutter).
|
||||
* `Besitzer_ID` (FK): Verweis auf den `Akteur`, dem das Pferd gehört.
|
||||
* `Identifikatoren`: Ein flexibler Speicher für alle offiziellen Nummern:
|
||||
* `Lebensnummer` (aus der Zucht)
|
||||
* `OEPS-Registrierungsnummer`
|
||||
* `FEI-ID`
|
||||
* `Chip-Nummer`
|
||||
* **OEPS-Daten:**
|
||||
* `Satznummer`: 10-stellig, numerisch (Primärschlüssel OEPS).
|
||||
* `Kopfnummer`: 4-stellig, alphanumerisch (Permanente ID).
|
||||
* `Lebensnummer`: 9-stellig (Zuchtnummer).
|
||||
* **FEI-Daten:**
|
||||
* `FEI-ID`: Eindeutige FEI-Nummer.
|
||||
* `FEI-Pass`: Passnummer (kann abweichen).
|
||||
|
||||
Reference in New Issue
Block a user