Standardize and refactor master data infrastructure: rename tables for plural consistency, remove unused entity tables, improve ZNS import mappings with enriched license properties, introduce Altersklasse domain model, activate Consul service discovery, and update application configuration accordingly.
This commit is contained in:
@@ -37,6 +37,15 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
|||||||
|
|
||||||
### Behoben
|
### Behoben
|
||||||
|
|
||||||
|
- **Masterdata/Infrastructure:** Kompilierfehler in `AltersklasseRepositoryImpl` durch Vereinheitlichung der Exposed-Tabellendefinition behoben:
|
||||||
|
- `AltersklassenTable` → `AltersklasseTable`
|
||||||
|
- Spalte `altersklassen_code` → `altersklasse_code`
|
||||||
|
- Tabellenname `altersklassen` → `altersklasse`
|
||||||
|
- **Masterdata/API:** Fehlendes Interface-Mapping ergänzt: `RegulationRepository` enthält nun `findAllTurnierklassen()`; `ExposedRegulationRepository` implementiert die Methode und `RegulationController` kompiliert wieder.
|
||||||
|
- **ZNS-Import:** `AltersklassenExposedRepository` korrigiert (richtiger Domain-Typ `AltersklasseDefinition`, Mapping von `SparteE` und Zeitstempeln).
|
||||||
|
|
||||||
|
### Behoben
|
||||||
|
|
||||||
- **Masterdata:** Qualifikations-Management für Funktionäre (Richter/Parcoursbauer) professionalisiert: Umstellung von unstrukturiertem Text auf offizielle ÖTO/FEI Master-Daten Referenzen (`QualifikationMasterTable`).
|
- **Masterdata:** Qualifikations-Management für Funktionäre (Richter/Parcoursbauer) professionalisiert: Umstellung von unstrukturiertem Text auf offizielle ÖTO/FEI Master-Daten Referenzen (`QualifikationMasterTable`).
|
||||||
- **Masterdata:** Fehlende Tabelle `funktionaer_qualifikation` in der Initialisierung beider Services (`masterdata` und `zns-import`) ergänzt, um `PSQLException` während des ZNS-Imports zu beheben.
|
- **Masterdata:** Fehlende Tabelle `funktionaer_qualifikation` in der Initialisierung beider Services (`masterdata` und `zns-import`) ergänzt, um `PSQLException` während des ZNS-Imports zu beheben.
|
||||||
- **Infrastructure:** Start-Probleme des `masterdata-service` endgültig behoben: Port-Konflikt zwischen Spring Boot (Management/Actuator) und dem Gateway (8081) durch Umzug auf Port 8086 (gemäß Infrastruktur-Vorgaben) gelöst.
|
- **Infrastructure:** Start-Probleme des `masterdata-service` endgültig behoben: Port-Konflikt zwischen Spring Boot (Management/Actuator) und dem Gateway (8081) durch Umzug auf Port 8086 (gemäß Infrastruktur-Vorgaben) gelöst.
|
||||||
@@ -57,6 +66,27 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [1.0.5-SNAPSHOT] — 2026-04-06
|
||||||
|
|
||||||
|
### Geändert
|
||||||
|
- **Masterdata:** Bereinigung und Standardisierung von Masterdaten-Tabellen (Mehrzahl-Konvention):
|
||||||
|
- `bundesland` -> `bundeslaender`
|
||||||
|
- `qualifikation_master` -> `funktionaers_qualifikationen`
|
||||||
|
- `reiter_lizenz` -> `reit_lizenzen`
|
||||||
|
- `turnierklasse` -> `turnier_klassen`
|
||||||
|
- **Seeding:** Umfassende Erweiterung der Seeder für Funktionärs-Qualifikationen, Turnierklassen und Turnier-Sparten gemäß ÖTO.
|
||||||
|
- **Data Modeling:** Einführung der Tabelle `turnier_sparten` und Entfernung der redundanten `reiter_sparte`.
|
||||||
|
- **Infrastructure:** Datenbank-Migration `V013` implementiert alle Schema-Änderungen und Umbenennungen.
|
||||||
|
|
||||||
|
## [1.0.4-SNAPSHOT] — 2026-04-06
|
||||||
|
|
||||||
|
### Hinzugefügt
|
||||||
|
- **Reiter-Lizenzen:** Strukturierte Speicherung von Lizenzen (STARTKARTE, REITERLIZENZ, FAHRLIZENZ) in einer 1:n Relation (`ReiterLizenzTable`).
|
||||||
|
- **Altersklassen:** Einführung von Enums (`ReiterAltersKlasseE`) für präzise Filterung und Validierung im Domain-Modell und Parser.
|
||||||
|
- **Mitgliedsnummer:** Validierungs-Logik gemäß ÖTO-Spezifikation (Bundesland-Präfix 1-9) in `Reiter.kt` implementiert.
|
||||||
|
- **ZNS-Import:** `ZnsReiterParser` erweitert, um Lizenzen und Altersklassen-Enums direkt aus LIZENZ01.DAT zu extrahieren.
|
||||||
|
- **Persistenz:** `ReiterExposedRepository` unterstützt nun das transaktionale Speichern und Laden der 1:n Lizenzen.
|
||||||
|
|
||||||
## [1.0.3-SNAPSHOT] — 2026-04-06
|
## [1.0.3-SNAPSHOT] — 2026-04-06
|
||||||
|
|
||||||
### Hinzugefügt
|
### Hinzugefügt
|
||||||
@@ -66,6 +96,12 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
|||||||
- **ZNS-Import:** Automatisches Auflösen von Relationen (Verein nach Name, Bundesland nach Nummer, Nation nach ISO-Code) während des Reiter-Imports.
|
- **ZNS-Import:** Automatisches Auflösen von Relationen (Verein nach Name, Bundesland nach Nummer, Nation nach ISO-Code) während des Reiter-Imports.
|
||||||
|
|
||||||
### Behoben
|
### Behoben
|
||||||
|
- **Infrastruktur:** Consul Health-Check für `masterdata-service` korrigiert (Port 8086 für Actuator).
|
||||||
|
- **Masterdaten:** `MasterdataSeeder` für Nationen und Bundesländer hinzugefügt, um Datenvollständigkeit nach Volume-Cleanup sicherzustellen.
|
||||||
|
- **Datenintegrität:** Heilungs-Logik (`fixReiterForeignKeys`) implementiert, die Reiter-Datensätze nachträglich mit Masterdaten verknüpft.
|
||||||
|
- **Code-Qualität:** Redundante `BundeslandTable` Definition in `ReiterTable.kt` entfernt.
|
||||||
|
- **Infrastruktur:** `BeanDefinitionOverrideException` im `zns-import-service` durch Konsolidierung der Repositories in `RepositoryConfiguration` behoben.
|
||||||
|
- **Service-Discovery:** Fehlende Consul-Registrierung des `masterdata-service` durch Hinzufügen der Discovery-Dependency und Konfiguration behoben.
|
||||||
- **Build:** Kompilierfehler in `BundeslandExposedRepository.kt` behoben (inkonsistente Rückgabetypen im `BundeslandRepository`-Interface).
|
- **Build:** Kompilierfehler in `BundeslandExposedRepository.kt` behoben (inkonsistente Rückgabetypen im `BundeslandRepository`-Interface).
|
||||||
- **Infrastruktur:** Fehlendes Autowiring im `zns-import-service` durch explizite Bean-Definitionen für alle Repositories in `ZnsImportServiceApplication.kt` behoben.
|
- **Infrastruktur:** Fehlendes Autowiring im `zns-import-service` durch explizite Bean-Definitionen für alle Repositories in `ZnsImportServiceApplication.kt` behoben.
|
||||||
- **Domain:** Kompilierfehler in `Bundesland.kt` behoben (uninitialisierte Eigenschaft `bundeslandId` entfernt).
|
- **Domain:** Kompilierfehler in `Bundesland.kt` behoben (uninitialisierte Eigenschaft `bundeslandId` entfernt).
|
||||||
|
|||||||
+15
-2
@@ -4,6 +4,8 @@ package at.mocode.zns.importer
|
|||||||
|
|
||||||
import at.mocode.masterdata.domain.repository.VereinRepository
|
import at.mocode.masterdata.domain.repository.VereinRepository
|
||||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||||
|
import at.mocode.masterdata.domain.repository.AltersklassenRepository
|
||||||
|
import at.mocode.masterdata.domain.repository.MasterdataLicenseRepository
|
||||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||||
import at.mocode.masterdata.domain.repository.LandRepository
|
import at.mocode.masterdata.domain.repository.LandRepository
|
||||||
@@ -44,7 +46,9 @@ class ZnsImportService(
|
|||||||
private val horseRepository: HorseRepository,
|
private val horseRepository: HorseRepository,
|
||||||
private val funktionaerRepository: FunktionaerRepository,
|
private val funktionaerRepository: FunktionaerRepository,
|
||||||
private val landRepository: LandRepository,
|
private val landRepository: LandRepository,
|
||||||
private val bundeslandRepository: BundeslandRepository
|
private val bundeslandRepository: BundeslandRepository,
|
||||||
|
private val licenseRepository: MasterdataLicenseRepository? = null,
|
||||||
|
private val altersklassenRepository: AltersklassenRepository? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -176,11 +180,17 @@ class ZnsImportService(
|
|||||||
val verein = parsed.vereinsName?.let { vereinRepository.findByExactName(it) }
|
val verein = parsed.vereinsName?.let { vereinRepository.findByExactName(it) }
|
||||||
val bundesland = parsed.bundeslandNummer?.let { bundeslandRepository.findByNr(it) }
|
val bundesland = parsed.bundeslandNummer?.let { bundeslandRepository.findByNr(it) }
|
||||||
val nation = parsed.nation?.let { landRepository.findByIsoAlpha3Code(it) }
|
val nation = parsed.nation?.let { landRepository.findByIsoAlpha3Code(it) }
|
||||||
|
val reitLizenz = parsed.reiterLizenz?.let { licenseRepository?.findReitLizenzByCode(it) }
|
||||||
|
val fahrLizenz = parsed.fahrLizenz?.let { licenseRepository?.findFahrLizenzByCode(it) }
|
||||||
|
val startkarte = parsed.startkarte?.let { licenseRepository?.findStartkarteByCode(it) }
|
||||||
|
|
||||||
val reiter = parsed.copy(
|
val reiter = parsed.copy(
|
||||||
vereinId = verein?.vereinId,
|
vereinId = verein?.vereinId,
|
||||||
bundeslandId = bundesland?.bundeslandId,
|
bundeslandId = bundesland?.bundeslandId,
|
||||||
nationId = nation?.landId
|
nationId = nation?.landId,
|
||||||
|
reitLizenzId = reitLizenz?.lizenzId,
|
||||||
|
fahrLizenzId = fahrLizenz?.lizenzId,
|
||||||
|
startkarteId = startkarte?.startkarteId
|
||||||
)
|
)
|
||||||
|
|
||||||
val vorhanden = reiterRepository.findBySatznummer(reiter.satznummer)
|
val vorhanden = reiterRepository.findBySatznummer(reiter.satznummer)
|
||||||
@@ -198,6 +208,9 @@ class ZnsImportService(
|
|||||||
vereinId = reiter.vereinId,
|
vereinId = reiter.vereinId,
|
||||||
bundeslandId = reiter.bundeslandId,
|
bundeslandId = reiter.bundeslandId,
|
||||||
nationId = reiter.nationId,
|
nationId = reiter.nationId,
|
||||||
|
reitLizenzId = reiter.reitLizenzId,
|
||||||
|
fahrLizenzId = reiter.fahrLizenzId,
|
||||||
|
startkarteId = reiter.startkarteId,
|
||||||
reiterLizenz = reiter.reiterLizenz,
|
reiterLizenz = reiter.reiterLizenz,
|
||||||
startkarte = reiter.startkarte,
|
startkarte = reiter.startkarte,
|
||||||
fahrLizenz = reiter.fahrLizenz,
|
fahrLizenz = reiter.fahrLizenz,
|
||||||
|
|||||||
+22
-7
@@ -88,12 +88,20 @@ class ZnsImportServiceTest {
|
|||||||
nachname: String = "Mustermann",
|
nachname: String = "Mustermann",
|
||||||
vorname: String = "Max"
|
vorname: String = "Max"
|
||||||
): String {
|
): String {
|
||||||
// Stelle 1-6: Satznummer, 7-56: Nachname (50), 57-81: Vorname (25)
|
val line = StringBuilder()
|
||||||
return satznummer.padEnd(6) +
|
line.append(satznummer.padEnd(6)) // 1-6
|
||||||
nachname.padEnd(50) +
|
line.append(nachname.padEnd(50)) // 7-56
|
||||||
vorname.padEnd(25) +
|
line.append(vorname.padEnd(25)) // 57-81
|
||||||
"01" + // 82-83 Bundesland
|
line.append("01") // 82-83 (Buli)
|
||||||
" ".repeat(250) // Rest auffüllen
|
line.append("".padEnd(50)) // 84-133 (Verein)
|
||||||
|
line.append("AUT") // 134-136 (Nation)
|
||||||
|
line.append("R2 ") // 137-140 (Lizenz)
|
||||||
|
line.append(" ") // 141 (Startkarte)
|
||||||
|
line.append(" ") // 142-143 (Fahrlizenz)
|
||||||
|
line.append("JG") // 144-145 (Altersklasse)
|
||||||
|
line.append(" ") // 146 (Altersklasse Y)
|
||||||
|
line.append("01234567") // 147-154 (Mitglied) - Bundesland 01 (Wien) + Rest
|
||||||
|
return line.toString().padEnd(220)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Erzeugt eine gültige PFERDE01.DAT-Zeile (mind. 211 Zeichen). */
|
/** Erzeugt eine gültige PFERDE01.DAT-Zeile (mind. 211 Zeichen). */
|
||||||
@@ -169,7 +177,14 @@ class ZnsImportServiceTest {
|
|||||||
assertThat(result.reiterImportiert).isEqualTo(1)
|
assertThat(result.reiterImportiert).isEqualTo(1)
|
||||||
assertThat(result.reiterAktualisiert).isEqualTo(0)
|
assertThat(result.reiterAktualisiert).isEqualTo(0)
|
||||||
assertThat(result.fehler).isEmpty()
|
assertThat(result.fehler).isEmpty()
|
||||||
coVerify(exactly = 1) { reiterRepository.save(any<Reiter>()) }
|
coVerify(exactly = 1) {
|
||||||
|
reiterRepository.save(match {
|
||||||
|
it.reiterLizenz == "R2" &&
|
||||||
|
it.lizenzen.size == 1 &&
|
||||||
|
it.lizenzen[0].kuerzel == "R2" &&
|
||||||
|
it.altersklasseJgJrU25 == at.mocode.core.domain.model.ReiterAltersKlasseE.JG
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Bewerbs-Klasse (z.B. E, A, L, M, S).
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class BewerbsKlasse(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val bewerbsklasseId: Uuid = Uuid.random(),
|
||||||
|
val sparte: String,
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val maxHoehe: Int? = null,
|
||||||
|
val aufgabenNiveau: String? = null,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import at.mocode.core.domain.model.SparteE
|
||||||
|
import at.mocode.core.domain.serialization.InstantSerializer
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlin.time.Instant
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domänenmodell für eine Bewerbsklasse gemäß ÖTO.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class BewerbsklasseDefinition(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val bewerbsklasseId: Uuid = Uuid.random(),
|
||||||
|
val sparte: SparteE,
|
||||||
|
val code: String, // E, A, L, LM, M, S
|
||||||
|
val bezeichnung: String,
|
||||||
|
val maxHoehe: Int? = null, // in cm (Springen)
|
||||||
|
val aufgabenNiveau: String? = null, // (Dressur)
|
||||||
|
|
||||||
|
@Serializable(with = InstantSerializer::class)
|
||||||
|
val validFrom: Instant,
|
||||||
|
@Serializable(with = InstantSerializer::class)
|
||||||
|
val validTo: Instant? = null,
|
||||||
|
|
||||||
|
val istAktiv: Boolean = true,
|
||||||
|
@Serializable(with = InstantSerializer::class)
|
||||||
|
val createdAt: Instant,
|
||||||
|
@Serializable(with = InstantSerializer::class)
|
||||||
|
val updatedAt: Instant
|
||||||
|
)
|
||||||
+2
-2
@@ -7,12 +7,12 @@ import at.mocode.core.domain.serialization.UuidSerializer
|
|||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain-Modell für Bundesland.
|
* Domain-Modell für Bundesland (Mehrzahl 'Bundeslaender').
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Bundesland(
|
data class Bundesland(
|
||||||
@Serializable(with = UuidSerializer::class)
|
@Serializable(with = UuidSerializer::class)
|
||||||
val id: Uuid,
|
val bundeslandId: Uuid,
|
||||||
val bundeslandNr: Int,
|
val bundeslandNr: Int,
|
||||||
val bezeichnung: String,
|
val bezeichnung: String,
|
||||||
val wappenUrl: String? = null
|
val wappenUrl: String? = null
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Fahr-Lizenz (z.B. F1, F2).
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class FahrLizenz(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val lizenzId: Uuid = Uuid.random(),
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import at.mocode.core.domain.serialization.LocalDateSerializer
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ReitLizenz(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val lizenzId: Uuid = Uuid.random(),
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val sparte: String? = null,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+39
-7
@@ -14,6 +14,16 @@ import kotlin.time.Clock
|
|||||||
import kotlin.time.Instant
|
import kotlin.time.Instant
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ReiterLizenz(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val lizenzId: Uuid = Uuid.random(),
|
||||||
|
val lizenzTyp: String, // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
|
||||||
|
val kuerzel: String,
|
||||||
|
@Serializable(with = LocalDateSerializer::class)
|
||||||
|
val gueltigBis: LocalDate? = null
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain model representing a rider (Reiter) in the actor-context.
|
* Domain model representing a rider (Reiter) in the actor-context.
|
||||||
*
|
*
|
||||||
@@ -88,6 +98,15 @@ data class Reiter(
|
|||||||
@Serializable(with = UuidSerializer::class)
|
@Serializable(with = UuidSerializer::class)
|
||||||
var nationId: Uuid? = null,
|
var nationId: Uuid? = null,
|
||||||
|
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
var reitLizenzId: Uuid? = null,
|
||||||
|
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
var fahrLizenzId: Uuid? = null,
|
||||||
|
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
var startkarteId: Uuid? = null,
|
||||||
|
|
||||||
// Alphanumerisch (4) Keine Lizenz: BLANK
|
// Alphanumerisch (4) Keine Lizenz: BLANK
|
||||||
var reiterLizenz: String? = null,
|
var reiterLizenz: String? = null,
|
||||||
|
|
||||||
@@ -98,10 +117,10 @@ data class Reiter(
|
|||||||
var fahrLizenz: String? = null,
|
var fahrLizenz: String? = null,
|
||||||
|
|
||||||
// Alphanumerisch (2) WERTE: Standard: BLANK, JG=JUGENDLICHER, JR=JUNIOR, 25=U25
|
// Alphanumerisch (2) WERTE: Standard: BLANK, JG=JUGENDLICHER, JR=JUNIOR, 25=U25
|
||||||
var altersklasseJgJrU25: String? = null,
|
var altersklasseJgJrU25: at.mocode.core.domain.model.ReiterAltersKlasseE? = null,
|
||||||
|
|
||||||
// Alphanumerisch (1) WERTE: Standard: BLANK Y=JUNGER-REITER
|
// Alphanumerisch (1) WERTE: Standard: BLANK Y=JUNGER-REITER
|
||||||
var altersklasseY: String? = null,
|
var altersklasseY: at.mocode.core.domain.model.ReiterAltersKlasseE? = null,
|
||||||
|
|
||||||
// Numerisch (8) FORMAT: 00000000
|
// Numerisch (8) FORMAT: 00000000
|
||||||
var mitgliedsNummer: Int? = null,
|
var mitgliedsNummer: Int? = null,
|
||||||
@@ -145,7 +164,12 @@ data class Reiter(
|
|||||||
@Serializable(with = InstantSerializer::class)
|
@Serializable(with = InstantSerializer::class)
|
||||||
val createdAt: Instant = Clock.System.now(),
|
val createdAt: Instant = Clock.System.now(),
|
||||||
@Serializable(with = InstantSerializer::class)
|
@Serializable(with = InstantSerializer::class)
|
||||||
var updatedAt: Instant = Clock.System.now()
|
var updatedAt: Instant = Clock.System.now(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of specialized licenses for this rider.
|
||||||
|
*/
|
||||||
|
var lizenzen: List<ReiterLizenz> = emptyList()
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Returns the display name of the rider.
|
* Returns the display name of the rider.
|
||||||
@@ -183,7 +207,7 @@ data class Reiter(
|
|||||||
/**
|
/**
|
||||||
* Validates the 8-digit membership number.
|
* Validates the 8-digit membership number.
|
||||||
* Format: [B][VVV][MMMM]
|
* Format: [B][VVV][MMMM]
|
||||||
* B: Bundesland (1 digit)
|
* B: Bundesland (1 digit, 1-9)
|
||||||
* VVV: Verein (3 digits)
|
* VVV: Verein (3 digits)
|
||||||
* MMMM: Member (4 digits)
|
* MMMM: Member (4 digits)
|
||||||
*/
|
*/
|
||||||
@@ -192,12 +216,20 @@ data class Reiter(
|
|||||||
if (nrStr.length != 8) return false
|
if (nrStr.length != 8) return false
|
||||||
|
|
||||||
val b = nrStr.substring(0, 1).toInt()
|
val b = nrStr.substring(0, 1).toInt()
|
||||||
|
if (b < 1 || b > 9) return false // Valid Bundesland prefix is 1-9
|
||||||
|
|
||||||
// Validation against bundeslandNummer if available
|
// Validation against bundeslandNummer if available
|
||||||
if (bundeslandNummer != null && b != (bundeslandNummer!! % 10)) {
|
// ZNS bundeslandNummer is 01-09, while membership first digit is 1-9
|
||||||
// ZNS bundeslandNummer is 01-09, while membership first digit is 1-9
|
if (bundeslandNummer != null && b != bundeslandNummer) {
|
||||||
// This might need refinement depending on how "00" (Unbekannt) is handled in membership numbers.
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verein part (2nd-4th digit)
|
||||||
|
// ZNS Verein ID usually contains state + 3 digits.
|
||||||
|
// Here we just check if it's not all zeros as a basic sanity check
|
||||||
|
val vvv = nrStr.substring(1, 4).toInt()
|
||||||
|
if (vvv == 0) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Startkarte.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class Startkarte(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val startkarteId: Uuid = Uuid.random(),
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Turnier-Kategorie (z.B. CSN-C, CDN-A, CSN-C Neu).
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class TurnierKategorie(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val kategorieId: Uuid = Uuid.random(),
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val sparte: String? = null,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Turnier-Klasse.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class TurnierKlasse(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val turnierklasseId: Uuid = Uuid.random(),
|
||||||
|
val sparte: String,
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val maxHoehe: Int? = null,
|
||||||
|
val aufgabenNiveau: String? = null,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import at.mocode.core.domain.serialization.UuidSerializer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain-Modell für eine Turnier-Sparte.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class TurnierSparte(
|
||||||
|
@Serializable(with = UuidSerializer::class)
|
||||||
|
val sparteId: Uuid = Uuid.random(),
|
||||||
|
val code: String,
|
||||||
|
val bezeichnung: String,
|
||||||
|
val istAktiv: Boolean = true
|
||||||
|
)
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.repository
|
||||||
|
|
||||||
|
import at.mocode.masterdata.domain.model.AltersklasseDefinition
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository für Altersklassen-Stammdaten.
|
||||||
|
*/
|
||||||
|
interface AltersklassenRepository {
|
||||||
|
suspend fun findByCode(code: String): AltersklasseDefinition?
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.domain.repository
|
||||||
|
|
||||||
|
import at.mocode.masterdata.domain.model.FahrLizenz
|
||||||
|
import at.mocode.masterdata.domain.model.ReitLizenz
|
||||||
|
import at.mocode.masterdata.domain.model.Startkarte
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository für alle Lizenz-Stammdaten (Reit, Fahr, Startkarten).
|
||||||
|
*/
|
||||||
|
interface MasterdataLicenseRepository {
|
||||||
|
suspend fun findReitLizenzByCode(code: String): at.mocode.masterdata.domain.model.ReitLizenz?
|
||||||
|
suspend fun findFahrLizenzByCode(code: String): at.mocode.masterdata.domain.model.FahrLizenz?
|
||||||
|
suspend fun findStartkarteByCode(code: String): at.mocode.masterdata.domain.model.Startkarte?
|
||||||
|
}
|
||||||
+1
@@ -9,6 +9,7 @@ import at.mocode.masterdata.domain.model.*
|
|||||||
*/
|
*/
|
||||||
interface RegulationRepository {
|
interface RegulationRepository {
|
||||||
suspend fun findAllTurnierklassen(): List<TurnierklasseDefinition>
|
suspend fun findAllTurnierklassen(): List<TurnierklasseDefinition>
|
||||||
|
suspend fun findAllBewerbsklassen(): List<BewerbsklasseDefinition>
|
||||||
suspend fun findAllLicenseMatrixEntries(): List<LicenseMatrixEntry>
|
suspend fun findAllLicenseMatrixEntries(): List<LicenseMatrixEntry>
|
||||||
suspend fun findAllRichtverfahren(): List<RichtverfahrenDefinition>
|
suspend fun findAllRichtverfahren(): List<RichtverfahrenDefinition>
|
||||||
suspend fun findAllGebuehren(): List<GebuehrDefinition>
|
suspend fun findAllGebuehren(): List<GebuehrDefinition>
|
||||||
|
|||||||
+3
-3
@@ -7,10 +7,10 @@ import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
|||||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposed-Tabellendefinition für die Altersklasse-Entität (Altersklassendefinition).
|
* Exposed-Tabellendefinition für die Altersklassen-Entität (Altersklassendefinition).
|
||||||
*
|
*
|
||||||
* Diese Tabelle speichert alle Informationen zu Altersklassen für Teilnehmer
|
* Diese Tabelle speichert alle Informationen zu Altersklassen für Teilnehmer
|
||||||
* entsprechend der AltersklasseDefinition Domain-Entität.
|
* entsprechend der AltersklassenDefinition Domain-Entität.
|
||||||
*/
|
*/
|
||||||
object AltersklasseTable : Table("altersklasse") {
|
object AltersklasseTable : Table("altersklasse") {
|
||||||
val id = uuid("id")
|
val id = uuid("id")
|
||||||
@@ -29,7 +29,7 @@ object AltersklasseTable : Table("altersklasse") {
|
|||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Index for performance on common queries
|
// Index für Performance (an Migration angepasst)
|
||||||
index(customIndexName = "idx_altersklasse_aktiv", columns = arrayOf(istAktiv))
|
index(customIndexName = "idx_altersklasse_aktiv", columns = arrayOf(istAktiv))
|
||||||
index(customIndexName = "idx_altersklasse_sparte", columns = arrayOf(sparteFilter))
|
index(customIndexName = "idx_altersklasse_sparte", columns = arrayOf(sparteFilter))
|
||||||
index(customIndexName = "idx_altersklasse_geschlecht", columns = arrayOf(geschlechtFilter))
|
index(customIndexName = "idx_altersklasse_geschlecht", columns = arrayOf(geschlechtFilter))
|
||||||
|
|||||||
+7
-7
@@ -7,12 +7,12 @@ import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
|||||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposed-Tabellendefinition für die Bundesland-Entität.
|
* Exposed-Tabellendefinition für die Bundesländer-Entität.
|
||||||
*/
|
*/
|
||||||
object BundeslandTable : Table("bundesland") {
|
object BundeslaenderTable : Table("bundeslaender") {
|
||||||
val id = uuid("id")
|
val id = uuid("bundesland_id")
|
||||||
val landId = uuid("land_id")
|
val landId = uuid("land_id")
|
||||||
val bundeslandNr = integer("bundesland_nr").nullable()
|
val bundeslandNr = integer("bundesland_nr").uniqueIndex().nullable()
|
||||||
val oepsCode = varchar("oeps_code", 10).nullable()
|
val oepsCode = varchar("oeps_code", 10).nullable()
|
||||||
val iso3166_2_Code = varchar("iso_3166_2_code", 10).nullable()
|
val iso3166_2_Code = varchar("iso_3166_2_code", 10).nullable()
|
||||||
val name = varchar("name", 100)
|
val name = varchar("name", 100)
|
||||||
@@ -26,10 +26,10 @@ object BundeslandTable : Table("bundesland") {
|
|||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
uniqueIndex("idx_bundesland_oeps", oepsCode, landId)
|
uniqueIndex("idx_bundeslaender_oeps", oepsCode, landId)
|
||||||
uniqueIndex("idx_bundesland_iso", iso3166_2_Code)
|
uniqueIndex("idx_bundeslaender_iso", iso3166_2_Code)
|
||||||
// Natürlicher Schlüssel gem. Architektur: (land_id + kuerzel) eindeutig
|
// Natürlicher Schlüssel gem. Architektur: (land_id + kuerzel) eindeutig
|
||||||
// Hinweis: kuerzel kann NULL sein – der Unique-Index greift dann nur für nicht-null Werte pro Land.
|
// Hinweis: kuerzel kann NULL sein – der Unique-Index greift dann nur für nicht-null Werte pro Land.
|
||||||
uniqueIndex("ux_bundesland_land_kuerzel", landId, kuerzel)
|
uniqueIndex("ux_bundeslaender_land_kuerzel", landId, kuerzel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+47
-42
@@ -11,46 +11,47 @@ import kotlin.uuid.Uuid
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementierung des BundeslandRepository für die Datenbankzugriffe.
|
* Implementierung des BundeslandRepository für die Datenbankzugriffe.
|
||||||
|
* Verwendet die Tabelle 'bundeslaender'.
|
||||||
*/
|
*/
|
||||||
class BundeslandRepositoryImpl : BundeslandRepository {
|
class BundeslandRepositoryImpl : BundeslandRepository {
|
||||||
|
|
||||||
private fun rowToBundeslandDefinition(row: ResultRow): BundeslandDefinition {
|
private fun rowToBundeslandDefinition(row: ResultRow): BundeslandDefinition {
|
||||||
return BundeslandDefinition(
|
return BundeslandDefinition(
|
||||||
bundeslandId = row[BundeslandTable.id],
|
bundeslandId = row[BundeslaenderTable.id],
|
||||||
landId = row[BundeslandTable.landId],
|
landId = row[BundeslaenderTable.landId],
|
||||||
bundeslandNr = row[BundeslandTable.bundeslandNr],
|
bundeslandNr = row[BundeslaenderTable.bundeslandNr],
|
||||||
oepsCode = row[BundeslandTable.oepsCode],
|
oepsCode = row[BundeslaenderTable.oepsCode],
|
||||||
iso3166_2_Code = row[BundeslandTable.iso3166_2_Code],
|
iso3166_2_Code = row[BundeslaenderTable.iso3166_2_Code],
|
||||||
name = row[BundeslandTable.name],
|
name = row[BundeslaenderTable.name],
|
||||||
kuerzel = row[BundeslandTable.kuerzel],
|
kuerzel = row[BundeslaenderTable.kuerzel],
|
||||||
wappenUrl = row[BundeslandTable.wappenUrl],
|
wappenUrl = row[BundeslaenderTable.wappenUrl],
|
||||||
istAktiv = row[BundeslandTable.istAktiv],
|
istAktiv = row[BundeslaenderTable.istAktiv],
|
||||||
sortierReihenfolge = row[BundeslandTable.sortierReihenfolge],
|
sortierReihenfolge = row[BundeslaenderTable.sortierReihenfolge],
|
||||||
createdAt = row[BundeslandTable.createdAt],
|
createdAt = row[BundeslaenderTable.createdAt],
|
||||||
updatedAt = row[BundeslandTable.updatedAt]
|
updatedAt = row[BundeslaenderTable.updatedAt]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByNr(nr: Int): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
override suspend fun findByNr(nr: Int): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.bundeslandNr eq nr }
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.bundeslandNr eq nr }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findById(id: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
override suspend fun findById(id: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.id eq id }
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.id eq id }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
override suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { (BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId) }
|
BundeslaenderTable.selectAll().where { (BundeslaenderTable.oepsCode eq oepsCode) and (BundeslaenderTable.landId eq landId) }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
override suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.iso3166_2_Code eq iso3166_2_Code }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
@@ -60,14 +61,14 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
activeOnly: Boolean,
|
activeOnly: Boolean,
|
||||||
orderBySortierung: Boolean
|
orderBySortierung: Boolean
|
||||||
): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
|
): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
|
||||||
val query = BundeslandTable.selectAll().where { BundeslandTable.landId eq landId }
|
val query = BundeslaenderTable.selectAll().where { BundeslaenderTable.landId eq landId }
|
||||||
if (activeOnly) {
|
if (activeOnly) {
|
||||||
query.andWhere { BundeslandTable.istAktiv eq true }
|
query.andWhere { BundeslaenderTable.istAktiv eq true }
|
||||||
}
|
}
|
||||||
if (orderBySortierung) {
|
if (orderBySortierung) {
|
||||||
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
|
query.orderBy(BundeslaenderTable.sortierReihenfolge to SortOrder.ASC, BundeslaenderTable.name to SortOrder.ASC)
|
||||||
} else {
|
} else {
|
||||||
query.orderBy(BundeslandTable.name to SortOrder.ASC)
|
query.orderBy(BundeslaenderTable.name to SortOrder.ASC)
|
||||||
}
|
}
|
||||||
query.map(::rowToBundeslandDefinition)
|
query.map(::rowToBundeslandDefinition)
|
||||||
}
|
}
|
||||||
@@ -75,26 +76,27 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
override suspend fun findByName(searchTerm: String, landId: Uuid?, limit: Int): List<BundeslandDefinition> =
|
override suspend fun findByName(searchTerm: String, landId: Uuid?, limit: Int): List<BundeslandDefinition> =
|
||||||
DatabaseFactory.dbQuery {
|
DatabaseFactory.dbQuery {
|
||||||
val pattern = "%$searchTerm%"
|
val pattern = "%$searchTerm%"
|
||||||
val query = BundeslandTable.selectAll().where { BundeslandTable.name like pattern }
|
val query = BundeslaenderTable.selectAll().where { BundeslaenderTable.name like pattern }
|
||||||
landId?.let { query.andWhere { BundeslandTable.landId eq it } }
|
landId?.let { query.andWhere { BundeslaenderTable.landId eq it } }
|
||||||
query.limit(limit).map(::rowToBundeslandDefinition)
|
query.limit(limit).map(::rowToBundeslandDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findAllActive(orderBySortierung: Boolean): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
|
override suspend fun findAllActive(orderBySortierung: Boolean): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
|
||||||
val query = BundeslandTable.selectAll().where { BundeslandTable.istAktiv eq true }
|
val query = BundeslaenderTable.selectAll().where { BundeslaenderTable.istAktiv eq true }
|
||||||
if (orderBySortierung) {
|
if (orderBySortierung) {
|
||||||
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
|
query.orderBy(BundeslaenderTable.sortierReihenfolge to SortOrder.ASC, BundeslaenderTable.name to SortOrder.ASC)
|
||||||
} else {
|
} else {
|
||||||
query.orderBy(BundeslandTable.name to SortOrder.ASC)
|
query.orderBy(BundeslaenderTable.name to SortOrder.ASC)
|
||||||
}
|
}
|
||||||
query.map(::rowToBundeslandDefinition)
|
query.map(::rowToBundeslandDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
|
override suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
|
||||||
val exists = BundeslandTable.selectAll().where { BundeslandTable.id eq bundesland.bundeslandId }.any()
|
val exists = BundeslaenderTable.selectAll().where { BundeslaenderTable.id eq bundesland.bundeslandId }.any()
|
||||||
if (exists) {
|
if (exists) {
|
||||||
BundeslandTable.update({ BundeslandTable.id eq bundesland.bundeslandId }) {
|
BundeslaenderTable.update({ BundeslaenderTable.id eq bundesland.bundeslandId }) {
|
||||||
it[landId] = bundesland.landId
|
it[landId] = bundesland.landId
|
||||||
|
it[bundeslandNr] = bundesland.bundeslandNr
|
||||||
it[oepsCode] = bundesland.oepsCode
|
it[oepsCode] = bundesland.oepsCode
|
||||||
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
||||||
it[name] = bundesland.name
|
it[name] = bundesland.name
|
||||||
@@ -106,9 +108,10 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
}
|
}
|
||||||
bundesland
|
bundesland
|
||||||
} else {
|
} else {
|
||||||
BundeslandTable.insert {
|
BundeslaenderTable.insert {
|
||||||
it[id] = bundesland.bundeslandId
|
it[id] = bundesland.bundeslandId
|
||||||
it[landId] = bundesland.landId
|
it[landId] = bundesland.landId
|
||||||
|
it[bundeslandNr] = bundesland.bundeslandNr
|
||||||
it[oepsCode] = bundesland.oepsCode
|
it[oepsCode] = bundesland.oepsCode
|
||||||
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
||||||
it[name] = bundesland.name
|
it[name] = bundesland.name
|
||||||
@@ -124,31 +127,31 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
|
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.deleteWhere { BundeslandTable.id eq id } > 0
|
BundeslaenderTable.deleteWhere { BundeslaenderTable.id eq id } > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean = DatabaseFactory.dbQuery {
|
override suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { (BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId) }
|
BundeslaenderTable.selectAll().where { (BundeslaenderTable.oepsCode eq oepsCode) and (BundeslaenderTable.landId eq landId) }
|
||||||
.any()
|
.any()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean = DatabaseFactory.dbQuery {
|
override suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }.any()
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.iso3166_2_Code eq iso3166_2_Code }.any()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun countActiveByCountry(landId: Uuid): Long = DatabaseFactory.dbQuery {
|
override suspend fun countActiveByCountry(landId: Uuid): Long = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { (BundeslandTable.landId eq landId) and (BundeslandTable.istAktiv eq true) }
|
BundeslaenderTable.selectAll().where { (BundeslaenderTable.landId eq landId) and (BundeslaenderTable.istAktiv eq true) }
|
||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun upsertByLandIdAndKuerzel(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
|
override suspend fun upsertByLandIdAndKuerzel(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
|
||||||
// 1) Update anhand des natürlichen Schlüssels (landId + kuerzel)
|
// 1) Update anhand des natürlichen Schlüssels (landId + kuerzel)
|
||||||
val updated = if (bundesland.kuerzel == null) {
|
val updated = if (bundesland.kuerzel == null) {
|
||||||
// Ohne Kuerzel ist der natürliche Schlüssel nicht definiert → versuche Update via (landId + name) als Fallback nicht, bleib bei None
|
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
BundeslandTable.update({ (BundeslandTable.landId eq bundesland.landId) and (BundeslandTable.kuerzel eq bundesland.kuerzel) }) {
|
BundeslaenderTable.update({ (BundeslaenderTable.landId eq bundesland.landId) and (BundeslaenderTable.kuerzel eq bundesland.kuerzel) }) {
|
||||||
it[landId] = bundesland.landId
|
it[landId] = bundesland.landId
|
||||||
|
it[bundeslandNr] = bundesland.bundeslandNr
|
||||||
it[oepsCode] = bundesland.oepsCode
|
it[oepsCode] = bundesland.oepsCode
|
||||||
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
||||||
it[name] = bundesland.name
|
it[name] = bundesland.name
|
||||||
@@ -161,16 +164,17 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updated > 0) {
|
if (updated > 0) {
|
||||||
BundeslandTable.selectAll()
|
BundeslaenderTable.selectAll()
|
||||||
.where { (BundeslandTable.landId eq bundesland.landId) and (BundeslandTable.kuerzel eq bundesland.kuerzel) }
|
.where { (BundeslaenderTable.landId eq bundesland.landId) and (BundeslaenderTable.kuerzel eq bundesland.kuerzel) }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.single()
|
.single()
|
||||||
} else {
|
} else {
|
||||||
// 2) Insert versuchen
|
// 2) Insert versuchen
|
||||||
try {
|
try {
|
||||||
BundeslandTable.insert {
|
BundeslaenderTable.insert {
|
||||||
it[id] = bundesland.bundeslandId
|
it[id] = bundesland.bundeslandId
|
||||||
it[landId] = bundesland.landId
|
it[landId] = bundesland.landId
|
||||||
|
it[bundeslandNr] = bundesland.bundeslandNr
|
||||||
it[oepsCode] = bundesland.oepsCode
|
it[oepsCode] = bundesland.oepsCode
|
||||||
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
||||||
it[name] = bundesland.name
|
it[name] = bundesland.name
|
||||||
@@ -184,8 +188,9 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
// Race-Condition → erneut Update
|
// Race-Condition → erneut Update
|
||||||
if (bundesland.kuerzel != null) {
|
if (bundesland.kuerzel != null) {
|
||||||
BundeslandTable.update({ (BundeslandTable.landId eq bundesland.landId) and (BundeslandTable.kuerzel eq bundesland.kuerzel) }) {
|
BundeslaenderTable.update({ (BundeslaenderTable.landId eq bundesland.landId) and (BundeslaenderTable.kuerzel eq bundesland.kuerzel) }) {
|
||||||
it[landId] = bundesland.landId
|
it[landId] = bundesland.landId
|
||||||
|
it[bundeslandNr] = bundesland.bundeslandNr
|
||||||
it[oepsCode] = bundesland.oepsCode
|
it[oepsCode] = bundesland.oepsCode
|
||||||
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
it[iso3166_2_Code] = bundesland.iso3166_2_Code
|
||||||
it[name] = bundesland.name
|
it[name] = bundesland.name
|
||||||
@@ -197,14 +202,14 @@ class BundeslandRepositoryImpl : BundeslandRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rückgabe des aktuellen Datensatzes: Falls Kuerzel null greift auf ID zurück
|
|
||||||
if (bundesland.kuerzel != null) {
|
if (bundesland.kuerzel != null) {
|
||||||
BundeslandTable.selectAll()
|
BundeslaenderTable.selectAll()
|
||||||
.where { (BundeslandTable.landId eq bundesland.landId) and (BundeslandTable.kuerzel eq bundesland.kuerzel) }
|
.where { (BundeslaenderTable.landId eq bundesland.landId) and (BundeslaenderTable.kuerzel eq bundesland.kuerzel) }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.single()
|
.single()
|
||||||
} else {
|
} else {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.id eq bundesland.bundeslandId }
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.id eq bundesland.bundeslandId }
|
||||||
.map(::rowToBundeslandDefinition)
|
.map(::rowToBundeslandDefinition)
|
||||||
.single()
|
.single()
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-12
@@ -19,10 +19,15 @@ import kotlin.time.Instant as KxInstant
|
|||||||
class ExposedRegulationRepository : RegulationRepository {
|
class ExposedRegulationRepository : RegulationRepository {
|
||||||
|
|
||||||
override suspend fun findAllTurnierklassen(): List<TurnierklasseDefinition> = DatabaseFactory.dbQuery {
|
override suspend fun findAllTurnierklassen(): List<TurnierklasseDefinition> = DatabaseFactory.dbQuery {
|
||||||
TurnierklasseTable.selectAll()
|
TurnierKlassenTable.selectAll()
|
||||||
.map { it.toTurnierklasseDefinition() }
|
.map { it.toTurnierklasseDefinition() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun findAllBewerbsklassen(): List<BewerbsklasseDefinition> = DatabaseFactory.dbQuery {
|
||||||
|
TurnierKlassenTable.selectAll()
|
||||||
|
.map { it.toBewerbsklasseDefinition() }
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun findAllLicenseMatrixEntries(): List<LicenseMatrixEntry> = DatabaseFactory.dbQuery {
|
override suspend fun findAllLicenseMatrixEntries(): List<LicenseMatrixEntry> = DatabaseFactory.dbQuery {
|
||||||
LicenseTable.selectAll()
|
LicenseTable.selectAll()
|
||||||
.map { it.toLicenseMatrixEntry() }
|
.map { it.toLicenseMatrixEntry() }
|
||||||
@@ -55,18 +60,32 @@ class ExposedRegulationRepository : RegulationRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ResultRow.toBewerbsklasseDefinition() = BewerbsklasseDefinition(
|
||||||
|
bewerbsklasseId = this[TurnierKlassenTable.id],
|
||||||
|
sparte = SparteE.valueOf(this[TurnierKlassenTable.sparte]),
|
||||||
|
code = this[TurnierKlassenTable.code],
|
||||||
|
bezeichnung = this[TurnierKlassenTable.bezeichnung],
|
||||||
|
maxHoehe = this[TurnierKlassenTable.maxHoehe],
|
||||||
|
aufgabenNiveau = this[TurnierKlassenTable.aufgabenNiveau],
|
||||||
|
validFrom = this[TurnierKlassenTable.validFrom].toKtInstant(),
|
||||||
|
validTo = this[TurnierKlassenTable.validTo]?.toOptionalKtInstant(),
|
||||||
|
istAktiv = this[TurnierKlassenTable.istAktiv],
|
||||||
|
createdAt = this[TurnierKlassenTable.createdAt].toKtInstant(),
|
||||||
|
updatedAt = this[TurnierKlassenTable.updatedAt].toKtInstant()
|
||||||
|
)
|
||||||
|
|
||||||
private fun ResultRow.toTurnierklasseDefinition() = TurnierklasseDefinition(
|
private fun ResultRow.toTurnierklasseDefinition() = TurnierklasseDefinition(
|
||||||
turnierklasseId = this[TurnierklasseTable.id],
|
turnierklasseId = this[TurnierKlassenTable.id],
|
||||||
sparte = SparteE.valueOf(this[TurnierklasseTable.sparte]),
|
sparte = SparteE.valueOf(this[TurnierKlassenTable.sparte]),
|
||||||
code = this[TurnierklasseTable.code],
|
code = this[TurnierKlassenTable.code],
|
||||||
bezeichnung = this[TurnierklasseTable.bezeichnung],
|
bezeichnung = this[TurnierKlassenTable.bezeichnung],
|
||||||
maxHoehe = this[TurnierklasseTable.maxHoehe],
|
maxHoehe = this[TurnierKlassenTable.maxHoehe],
|
||||||
aufgabenNiveau = this[TurnierklasseTable.aufgabenNiveau],
|
aufgabenNiveau = this[TurnierKlassenTable.aufgabenNiveau],
|
||||||
validFrom = this[TurnierklasseTable.validFrom].toKtInstant(),
|
validFrom = this[TurnierKlassenTable.validFrom].toKtInstant(),
|
||||||
validTo = this[TurnierklasseTable.validTo]?.toOptionalKtInstant(),
|
validTo = this[TurnierKlassenTable.validTo]?.toOptionalKtInstant(),
|
||||||
istAktiv = this[TurnierklasseTable.istAktiv],
|
istAktiv = this[TurnierKlassenTable.istAktiv],
|
||||||
createdAt = this[TurnierklasseTable.createdAt].toKtInstant(),
|
createdAt = this[TurnierKlassenTable.createdAt].toKtInstant(),
|
||||||
updatedAt = this[TurnierklasseTable.updatedAt].toKtInstant()
|
updatedAt = this[TurnierKlassenTable.updatedAt].toKtInstant()
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun ResultRow.toLicenseMatrixEntry() = LicenseMatrixEntry(
|
private fun ResultRow.toLicenseMatrixEntry() = LicenseMatrixEntry(
|
||||||
|
|||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
|
||||||
|
|
||||||
package at.mocode.masterdata.infrastructure.persistence
|
|
||||||
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
|
||||||
import org.jetbrains.exposed.v1.core.Table
|
|
||||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
|
||||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exposed-Tabellendefinition für die Spartenberechtigung eines Reiters.
|
|
||||||
* Verknüpft einen Reiter mit den Sparten (DRESSUR, SPRINGEN), für die er lizenziert ist.
|
|
||||||
*/
|
|
||||||
object ReiterSparteTable : Table("reiter_sparte") {
|
|
||||||
val id = uuid("id")
|
|
||||||
val reiterId = uuid("reiter_id").references(ReiterTable.id)
|
|
||||||
val sparte = varchar("sparte", 20) // DRESSUR, SPRINGEN
|
|
||||||
|
|
||||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
|
||||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
|
||||||
|
|
||||||
override val primaryKey = PrimaryKey(id)
|
|
||||||
|
|
||||||
init {
|
|
||||||
uniqueIndex("ux_reiter_sparte", reiterId, sparte)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.infrastructure.persistence
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.v1.core.Table
|
||||||
|
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-Tabellendefinition für Turnier-Kategorien (z.B. CSN-B, CDN-A).
|
||||||
|
*/
|
||||||
|
object TurnierKategorienTable : Table("turnier_kategorien") {
|
||||||
|
val id = uuid("kategorie_id")
|
||||||
|
val code = varchar("code", 20).uniqueIndex()
|
||||||
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
|
val sparte = varchar("sparte", 20).nullable()
|
||||||
|
val istAktiv = bool("ist_aktiv").default(true)
|
||||||
|
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||||
|
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
||||||
+4
-4
@@ -7,11 +7,11 @@ import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
|||||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposed-Tabellendefinition für Turnierklassen (Springen/Dressur).
|
* Exposed-Tabellendefinition für Bewerbsklassen (Springen/Dressur).
|
||||||
* Basierend auf ÖTO 2026.
|
* Basierend auf ÖTO 2026.
|
||||||
*/
|
*/
|
||||||
object TurnierklasseTable : Table("turnierklasse") {
|
object TurnierKlassenTable : Table("bewerbs_klassen") {
|
||||||
val id = uuid("turnierklasse_id")
|
val id = uuid("bewerbsklasse_id")
|
||||||
val sparte = varchar("sparte", 20) // DRESSUR, SPRINGEN
|
val sparte = varchar("sparte", 20) // DRESSUR, SPRINGEN
|
||||||
val code = varchar("code", 10) // E, A, L, LM, M, S
|
val code = varchar("code", 10) // E, A, L, LM, M, S
|
||||||
val bezeichnung = varchar("bezeichnung", 100)
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
@@ -29,6 +29,6 @@ object TurnierklasseTable : Table("turnierklasse") {
|
|||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
index("idx_turnierklasse_sparte_code", false, sparte, code)
|
index("idx_bewerbs_klassen_sparte_code", false, sparte, code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.infrastructure.persistence
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.v1.core.Table
|
||||||
|
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||||
|
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-Tabellendefinition für Turnier-Sparten (z.B. Dressur, Springen, Fahren).
|
||||||
|
*/
|
||||||
|
object TurnierSpartenTable : Table("turnier_sparten") {
|
||||||
|
val id = uuid("sparte_id")
|
||||||
|
val code = varchar("code", 10).uniqueIndex() // z.B. D, S, V, F, R, C
|
||||||
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
|
val istAktiv = bool("ist_aktiv").default(true)
|
||||||
|
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||||
|
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
||||||
+11
-14
@@ -5,10 +5,7 @@ import at.mocode.core.domain.model.DatenQuelleE
|
|||||||
import at.mocode.core.utils.database.DatabaseFactory
|
import at.mocode.core.utils.database.DatabaseFactory
|
||||||
import at.mocode.masterdata.domain.model.Funktionaer
|
import at.mocode.masterdata.domain.model.Funktionaer
|
||||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||||
import org.jetbrains.exposed.v1.core.ResultRow
|
import org.jetbrains.exposed.v1.core.*
|
||||||
import org.jetbrains.exposed.v1.core.and
|
|
||||||
import org.jetbrains.exposed.v1.core.eq
|
|
||||||
import org.jetbrains.exposed.v1.core.inList
|
|
||||||
import org.jetbrains.exposed.v1.jdbc.deleteWhere
|
import org.jetbrains.exposed.v1.jdbc.deleteWhere
|
||||||
import org.jetbrains.exposed.v1.jdbc.insert
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
import org.jetbrains.exposed.v1.jdbc.selectAll
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
@@ -20,7 +17,7 @@ import kotlin.uuid.Uuid
|
|||||||
* Exposed-basierte Implementierung des Funktionaer-Repositorys.
|
* Exposed-basierte Implementierung des Funktionaer-Repositorys.
|
||||||
*
|
*
|
||||||
* Verwaltet die Persistenz von Funktionären und deren Qualifikationen.
|
* Verwaltet die Persistenz von Funktionären und deren Qualifikationen.
|
||||||
* Die Qualifikationen werden beim Speichern gegen die [QualifikationMasterTable]
|
* Die Qualifikationen werden beim Speichern gegen die [FunktionaersQualifikationenTable]
|
||||||
* aufgelöst, um Datenintegrität bezüglich offizieller ÖTO-Kürzel sicherzustellen.
|
* aufgelöst, um Datenintegrität bezüglich offizieller ÖTO-Kürzel sicherzustellen.
|
||||||
*/
|
*/
|
||||||
class FunktionaerExposedRepository : FunktionaerRepository {
|
class FunktionaerExposedRepository : FunktionaerRepository {
|
||||||
@@ -44,9 +41,9 @@ class FunktionaerExposedRepository : FunktionaerRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findById(id: Uuid): Funktionaer? = DatabaseFactory.dbQuery {
|
override suspend fun findById(id: Uuid): Funktionaer? = DatabaseFactory.dbQuery {
|
||||||
val qualifikationen = (FunktionaerQualifikationTable innerJoin QualifikationMasterTable)
|
val qualifikationen = (FunktionaerQualifikationTable innerJoin FunktionaersQualifikationenTable)
|
||||||
.selectAll().where { FunktionaerQualifikationTable.funktionaerId eq id }
|
.selectAll().where { FunktionaerQualifikationTable.funktionaerId eq id }
|
||||||
.map { it[QualifikationMasterTable.code] }
|
.map { it[FunktionaersQualifikationenTable.code] }
|
||||||
|
|
||||||
FunktionaerTable.selectAll().where { FunktionaerTable.id eq id }
|
FunktionaerTable.selectAll().where { FunktionaerTable.id eq id }
|
||||||
.map { rowToDomFunktionaer(it, qualifikationen) }
|
.map { rowToDomFunktionaer(it, qualifikationen) }
|
||||||
@@ -58,9 +55,9 @@ class FunktionaerExposedRepository : FunktionaerRepository {
|
|||||||
.where { (FunktionaerTable.satzId eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
.where { (FunktionaerTable.satzId eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
||||||
.singleOrNull() ?: return@dbQuery null
|
.singleOrNull() ?: return@dbQuery null
|
||||||
|
|
||||||
val qualifikationen = (FunktionaerQualifikationTable innerJoin QualifikationMasterTable)
|
val qualifikationen = (FunktionaerQualifikationTable innerJoin FunktionaersQualifikationenTable)
|
||||||
.selectAll().where { FunktionaerQualifikationTable.funktionaerId eq row[FunktionaerTable.id] }
|
.selectAll().where { FunktionaerQualifikationTable.funktionaerId eq row[FunktionaerTable.id] }
|
||||||
.map { it[QualifikationMasterTable.code] }
|
.map { it[FunktionaersQualifikationenTable.code] }
|
||||||
|
|
||||||
rowToDomFunktionaer(row, qualifikationen)
|
rowToDomFunktionaer(row, qualifikationen)
|
||||||
}
|
}
|
||||||
@@ -71,9 +68,9 @@ class FunktionaerExposedRepository : FunktionaerRepository {
|
|||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val ids = funktionaere.map { it[FunktionaerTable.id] }
|
val ids = funktionaere.map { it[FunktionaerTable.id] }
|
||||||
val qualisMap = (FunktionaerQualifikationTable innerJoin QualifikationMasterTable)
|
val qualisMap = (FunktionaerQualifikationTable innerJoin FunktionaersQualifikationenTable)
|
||||||
.selectAll().where { FunktionaerQualifikationTable.funktionaerId inList ids }
|
.selectAll().where { FunktionaerQualifikationTable.funktionaerId inList ids }
|
||||||
.groupBy({ it[FunktionaerQualifikationTable.funktionaerId] }) { it[QualifikationMasterTable.code] }
|
.groupBy({ it[FunktionaerQualifikationTable.funktionaerId] }) { it[FunktionaersQualifikationenTable.code] }
|
||||||
|
|
||||||
funktionaere.map { row ->
|
funktionaere.map { row ->
|
||||||
rowToDomFunktionaer(row, qualisMap[row[FunktionaerTable.id]] ?: emptyList())
|
rowToDomFunktionaer(row, qualisMap[row[FunktionaerTable.id]] ?: emptyList())
|
||||||
@@ -118,9 +115,9 @@ class FunktionaerExposedRepository : FunktionaerRepository {
|
|||||||
val typ = if (funktionaer.istRichter()) "RICHTER" else "PARCOURSBAUER"
|
val typ = if (funktionaer.istRichter()) "RICHTER" else "PARCOURSBAUER"
|
||||||
|
|
||||||
funktionaer.qualifikationen.forEach { code ->
|
funktionaer.qualifikationen.forEach { code ->
|
||||||
val masterId = QualifikationMasterTable
|
val masterId = FunktionaersQualifikationenTable
|
||||||
.selectAll().where { (QualifikationMasterTable.code eq code) and (QualifikationMasterTable.typ eq typ) }
|
.selectAll().where { (FunktionaersQualifikationenTable.code eq code) and (FunktionaersQualifikationenTable.typ eq typ) }
|
||||||
.map { it[QualifikationMasterTable.id] }
|
.map { it[FunktionaersQualifikationenTable.id] }
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
|
|
||||||
if (masterId != null) {
|
if (masterId != null) {
|
||||||
|
|||||||
+4
-4
@@ -48,10 +48,10 @@ object FunktionaerTable : Table("funktionaer") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposed-Tabellendefinition für die Qualifikation-Master-Daten.
|
* Exposed-Tabellendefinition für die Qualifikation-Master-Daten (Funktionäre).
|
||||||
* Enthält offizielle ÖTO/FEI Kürzel (z.B. "D", "S", "P1").
|
* Enthält offizielle ÖTO/FEI Kürzel (z.B. "D", "S", "P1").
|
||||||
*/
|
*/
|
||||||
object QualifikationMasterTable : Table("qualifikation_master") {
|
object FunktionaersQualifikationenTable : Table("funktionaers_qualifikationen") {
|
||||||
val id = uuid("qualifikation_id")
|
val id = uuid("qualifikation_id")
|
||||||
|
|
||||||
/** Offizielles Kürzel (z.B. "SPF" für Springpferde) */
|
/** Offizielles Kürzel (z.B. "SPF" für Springpferde) */
|
||||||
@@ -66,7 +66,7 @@ object QualifikationMasterTable : Table("qualifikation_master") {
|
|||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
index("idx_qualifikation_code_typ", isUnique = true, code, typ)
|
index("idx_funktionaers_qualifikationen_code_typ", isUnique = true, code, typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ object QualifikationMasterTable : Table("qualifikation_master") {
|
|||||||
*/
|
*/
|
||||||
object FunktionaerQualifikationTable : Table("funktionaer_qualifikation") {
|
object FunktionaerQualifikationTable : Table("funktionaer_qualifikation") {
|
||||||
val funktionaerId = uuid("funktionaer_id").references(FunktionaerTable.id)
|
val funktionaerId = uuid("funktionaer_id").references(FunktionaerTable.id)
|
||||||
val qualifikationId = uuid("qualifikation_id").references(QualifikationMasterTable.id)
|
val qualifikationId = uuid("qualifikation_id").references(FunktionaersQualifikationenTable.id)
|
||||||
|
|
||||||
override val primaryKey = PrimaryKey(funktionaerId, qualifikationId)
|
override val primaryKey = PrimaryKey(funktionaerId, qualifikationId)
|
||||||
}
|
}
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||||
|
|
||||||
|
import at.mocode.core.domain.model.SparteE
|
||||||
|
import at.mocode.core.utils.database.DatabaseFactory
|
||||||
|
import at.mocode.masterdata.domain.model.AltersklasseDefinition
|
||||||
|
import at.mocode.masterdata.domain.repository.AltersklassenRepository
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.AltersklasseTable
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-basierte Implementierung des AltersklassenRepository.
|
||||||
|
*/
|
||||||
|
class AltersklassenExposedRepository : AltersklassenRepository {
|
||||||
|
|
||||||
|
override suspend fun findByCode(code: String): AltersklasseDefinition? = DatabaseFactory.dbQuery {
|
||||||
|
AltersklasseTable.selectAll().where { AltersklasseTable.altersklasseCode eq code }
|
||||||
|
.map {
|
||||||
|
AltersklasseDefinition(
|
||||||
|
altersklasseId = it[AltersklasseTable.id],
|
||||||
|
altersklasseCode = it[AltersklasseTable.altersklasseCode],
|
||||||
|
bezeichnung = it[AltersklasseTable.bezeichnung],
|
||||||
|
minAlter = it[AltersklasseTable.minAlter],
|
||||||
|
maxAlter = it[AltersklasseTable.maxAlter],
|
||||||
|
stichtagRegelText = it[AltersklasseTable.stichtagRegelText],
|
||||||
|
sparteFilter = it[AltersklasseTable.sparteFilter]?.let { s -> SparteE.valueOf(s) },
|
||||||
|
geschlechtFilter = it[AltersklasseTable.geschlechtFilter],
|
||||||
|
oetoRegelReferenzId = it[AltersklasseTable.oetoRegelReferenzId],
|
||||||
|
istAktiv = it[AltersklasseTable.istAktiv],
|
||||||
|
createdAt = it[AltersklasseTable.createdAt],
|
||||||
|
updatedAt = it[AltersklasseTable.updatedAt]
|
||||||
|
)
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-14
@@ -5,7 +5,7 @@ package at.mocode.masterdata.infrastructure.persistence.reiter
|
|||||||
import at.mocode.core.utils.database.DatabaseFactory
|
import at.mocode.core.utils.database.DatabaseFactory
|
||||||
import at.mocode.masterdata.domain.model.BundeslandDefinition
|
import at.mocode.masterdata.domain.model.BundeslandDefinition
|
||||||
import at.mocode.masterdata.domain.repository.BundeslandRepository
|
import at.mocode.masterdata.domain.repository.BundeslandRepository
|
||||||
import at.mocode.masterdata.infrastructure.persistence.BundeslandTable
|
import at.mocode.masterdata.infrastructure.persistence.BundeslaenderTable
|
||||||
import org.jetbrains.exposed.v1.core.ResultRow
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.v1.core.eq
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
import org.jetbrains.exposed.v1.jdbc.selectAll
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
@@ -17,22 +17,22 @@ import kotlin.uuid.Uuid
|
|||||||
*/
|
*/
|
||||||
class BundeslandExposedRepository : BundeslandRepository {
|
class BundeslandExposedRepository : BundeslandRepository {
|
||||||
private fun rowToDom(row: ResultRow) = BundeslandDefinition(
|
private fun rowToDom(row: ResultRow) = BundeslandDefinition(
|
||||||
bundeslandId = row[BundeslandTable.id],
|
bundeslandId = row[BundeslaenderTable.id],
|
||||||
landId = row[BundeslandTable.landId],
|
landId = row[BundeslaenderTable.landId],
|
||||||
bundeslandNr = row[BundeslandTable.bundeslandNr],
|
bundeslandNr = row[BundeslaenderTable.bundeslandNr],
|
||||||
oepsCode = row[BundeslandTable.oepsCode],
|
oepsCode = row[BundeslaenderTable.oepsCode],
|
||||||
iso3166_2_Code = row[BundeslandTable.iso3166_2_Code],
|
iso3166_2_Code = row[BundeslaenderTable.iso3166_2_Code],
|
||||||
name = row[BundeslandTable.name],
|
name = row[BundeslaenderTable.name],
|
||||||
kuerzel = row[BundeslandTable.kuerzel],
|
kuerzel = row[BundeslaenderTable.kuerzel],
|
||||||
wappenUrl = row[BundeslandTable.wappenUrl],
|
wappenUrl = row[BundeslaenderTable.wappenUrl],
|
||||||
istAktiv = row[BundeslandTable.istAktiv],
|
istAktiv = row[BundeslaenderTable.istAktiv],
|
||||||
sortierReihenfolge = row[BundeslandTable.sortierReihenfolge],
|
sortierReihenfolge = row[BundeslaenderTable.sortierReihenfolge],
|
||||||
createdAt = row[BundeslandTable.createdAt],
|
createdAt = row[BundeslaenderTable.createdAt],
|
||||||
updatedAt = row[BundeslandTable.updatedAt]
|
updatedAt = row[BundeslaenderTable.updatedAt]
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun findByNr(nr: Int): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
override suspend fun findByNr(nr: Int): BundeslandDefinition? = DatabaseFactory.dbQuery {
|
||||||
BundeslandTable.selectAll().where { BundeslandTable.bundeslandNr eq nr }
|
BundeslaenderTable.selectAll().where { BundeslaenderTable.bundeslandNr eq nr }
|
||||||
.map(::rowToDom)
|
.map(::rowToDom)
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
|
||||||
|
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||||
|
|
||||||
|
import at.mocode.core.utils.database.DatabaseFactory
|
||||||
|
import at.mocode.masterdata.domain.model.FahrLizenz
|
||||||
|
import at.mocode.masterdata.domain.model.ReitLizenz
|
||||||
|
import at.mocode.masterdata.domain.model.Startkarte
|
||||||
|
import at.mocode.masterdata.domain.repository.MasterdataLicenseRepository
|
||||||
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-basierte Implementierung des MasterdataLicenseRepository.
|
||||||
|
*/
|
||||||
|
class MasterdataLicenseExposedRepository : MasterdataLicenseRepository {
|
||||||
|
|
||||||
|
override suspend fun findReitLizenzByCode(code: String): ReitLizenz? = DatabaseFactory.dbQuery {
|
||||||
|
ReitLizenzenTable.selectAll().where { ReitLizenzenTable.code eq code }
|
||||||
|
.map {
|
||||||
|
ReitLizenz(
|
||||||
|
lizenzId = it[ReitLizenzenTable.id],
|
||||||
|
code = it[ReitLizenzenTable.code],
|
||||||
|
bezeichnung = it[ReitLizenzenTable.bezeichnung],
|
||||||
|
sparte = it[ReitLizenzenTable.sparte],
|
||||||
|
istAktiv = it[ReitLizenzenTable.istAktiv]
|
||||||
|
)
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun findFahrLizenzByCode(code: String): FahrLizenz? = DatabaseFactory.dbQuery {
|
||||||
|
FahrLizenzenTable.selectAll().where { FahrLizenzenTable.code eq code }
|
||||||
|
.map {
|
||||||
|
FahrLizenz(
|
||||||
|
lizenzId = it[FahrLizenzenTable.id],
|
||||||
|
code = it[FahrLizenzenTable.code],
|
||||||
|
bezeichnung = it[FahrLizenzenTable.bezeichnung],
|
||||||
|
istAktiv = it[FahrLizenzenTable.istAktiv]
|
||||||
|
)
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun findStartkarteByCode(code: String): Startkarte? = DatabaseFactory.dbQuery {
|
||||||
|
StartkartenTable.selectAll().where { StartkartenTable.code eq code }
|
||||||
|
.map {
|
||||||
|
Startkarte(
|
||||||
|
startkarteId = it[StartkartenTable.id],
|
||||||
|
code = it[StartkartenTable.code],
|
||||||
|
bezeichnung = it[StartkartenTable.bezeichnung],
|
||||||
|
istAktiv = it[StartkartenTable.istAktiv]
|
||||||
|
)
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
-9
@@ -3,15 +3,20 @@
|
|||||||
package at.mocode.masterdata.infrastructure.persistence.reiter
|
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||||
|
|
||||||
import at.mocode.core.domain.model.DatenQuelleE
|
import at.mocode.core.domain.model.DatenQuelleE
|
||||||
|
import at.mocode.core.domain.model.ReiterAltersKlasseE
|
||||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||||
import at.mocode.core.utils.database.DatabaseFactory
|
import at.mocode.core.utils.database.DatabaseFactory
|
||||||
import at.mocode.masterdata.domain.model.Reiter
|
import at.mocode.masterdata.domain.model.Reiter
|
||||||
|
import at.mocode.masterdata.domain.model.ReiterLizenz
|
||||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||||
import org.jetbrains.exposed.v1.core.ResultRow
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
import org.jetbrains.exposed.v1.core.and
|
import org.jetbrains.exposed.v1.core.and
|
||||||
import org.jetbrains.exposed.v1.core.eq
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
import org.jetbrains.exposed.v1.core.lowerCase
|
import org.jetbrains.exposed.v1.core.lowerCase
|
||||||
import org.jetbrains.exposed.v1.jdbc.*
|
import org.jetbrains.exposed.v1.jdbc.deleteWhere
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.update
|
||||||
import kotlin.uuid.ExperimentalUuidApi
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
@@ -33,11 +38,14 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
vereinId = row[ReiterTable.vereinId],
|
vereinId = row[ReiterTable.vereinId],
|
||||||
bundeslandId = row[ReiterTable.bundeslandId],
|
bundeslandId = row[ReiterTable.bundeslandId],
|
||||||
nationId = row[ReiterTable.nationId],
|
nationId = row[ReiterTable.nationId],
|
||||||
|
reitLizenzId = row[ReiterTable.reitLizenzId],
|
||||||
|
fahrLizenzId = row[ReiterTable.fahrLizenzId],
|
||||||
|
startkarteId = row[ReiterTable.startkarteId],
|
||||||
reiterLizenz = row[ReiterTable.reiterLizenz],
|
reiterLizenz = row[ReiterTable.reiterLizenz],
|
||||||
startkarte = row[ReiterTable.startkarte],
|
startkarte = row[ReiterTable.startkarte],
|
||||||
fahrLizenz = row[ReiterTable.fahrLizenz],
|
fahrLizenz = row[ReiterTable.fahrLizenz],
|
||||||
altersklasseJgJrU25 = row[ReiterTable.altersklasseJgJrU25],
|
altersklasseJgJrU25 = row[ReiterTable.altersklasseJgJrU25]?.let { ReiterAltersKlasseE.valueOf(it) },
|
||||||
altersklasseY = row[ReiterTable.altersklasseY],
|
altersklasseY = row[ReiterTable.altersklasseY]?.let { ReiterAltersKlasseE.valueOf(it) },
|
||||||
mitgliedsNummer = row[ReiterTable.mitgliedsNummer],
|
mitgliedsNummer = row[ReiterTable.mitgliedsNummer],
|
||||||
telefonNummer = row[ReiterTable.telefonNummer],
|
telefonNummer = row[ReiterTable.telefonNummer],
|
||||||
kader = row[ReiterTable.kader],
|
kader = row[ReiterTable.kader],
|
||||||
@@ -52,10 +60,23 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
bemerkungen = row[ReiterTable.bemerkungen],
|
bemerkungen = row[ReiterTable.bemerkungen],
|
||||||
datenQuelle = DatenQuelleE.valueOf(row[ReiterTable.datenQuelle]),
|
datenQuelle = DatenQuelleE.valueOf(row[ReiterTable.datenQuelle]),
|
||||||
createdAt = row[ReiterTable.createdAt],
|
createdAt = row[ReiterTable.createdAt],
|
||||||
updatedAt = row[ReiterTable.updatedAt]
|
updatedAt = row[ReiterTable.updatedAt],
|
||||||
|
lizenzen = loadLizenzen(row[ReiterTable.id])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadLizenzen(reiterId: Uuid): List<ReiterLizenz> {
|
||||||
|
return ReiterLizenzenZuordnungTable.selectAll().where { ReiterLizenzenZuordnungTable.reiterId eq reiterId }
|
||||||
|
.map {
|
||||||
|
at.mocode.masterdata.domain.model.ReiterLizenz(
|
||||||
|
lizenzId = it[ReiterLizenzenZuordnungTable.id],
|
||||||
|
lizenzTyp = it[ReiterLizenzenZuordnungTable.lizenzTyp],
|
||||||
|
kuerzel = it[ReiterLizenzenZuordnungTable.kuerzel],
|
||||||
|
gueltigBis = it[ReiterLizenzenZuordnungTable.gueltigBis]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun findById(id: Uuid): Reiter? = DatabaseFactory.dbQuery {
|
override suspend fun findById(id: Uuid): Reiter? = DatabaseFactory.dbQuery {
|
||||||
ReiterTable.selectAll().where { ReiterTable.id eq id }
|
ReiterTable.selectAll().where { ReiterTable.id eq id }
|
||||||
.map { rowToDomReiter(it) }
|
.map { rowToDomReiter(it) }
|
||||||
@@ -72,7 +93,7 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
ReiterTable.selectAll()
|
ReiterTable.selectAll()
|
||||||
.where {
|
.where {
|
||||||
(ReiterTable.vorname.lowerCase() eq vorname.lowercase()) and
|
(ReiterTable.vorname.lowerCase() eq vorname.lowercase()) and
|
||||||
(ReiterTable.nachname.lowerCase() eq nachname.lowercase())
|
(ReiterTable.nachname.lowerCase() eq nachname.lowercase())
|
||||||
}
|
}
|
||||||
.map { row -> rowToDomReiter(row) }
|
.map { row -> rowToDomReiter(row) }
|
||||||
}
|
}
|
||||||
@@ -97,11 +118,14 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
it[vereinId] = reiter.vereinId
|
it[vereinId] = reiter.vereinId
|
||||||
it[bundeslandId] = reiter.bundeslandId
|
it[bundeslandId] = reiter.bundeslandId
|
||||||
it[nationId] = reiter.nationId
|
it[nationId] = reiter.nationId
|
||||||
|
it[reitLizenzId] = reiter.reitLizenzId
|
||||||
|
it[fahrLizenzId] = reiter.fahrLizenzId
|
||||||
|
it[startkarteId] = reiter.startkarteId
|
||||||
it[reiterLizenz] = reiter.reiterLizenz
|
it[reiterLizenz] = reiter.reiterLizenz
|
||||||
it[startkarte] = reiter.startkarte
|
it[startkarte] = reiter.startkarte
|
||||||
it[fahrLizenz] = reiter.fahrLizenz
|
it[fahrLizenz] = reiter.fahrLizenz
|
||||||
it[altersklasseJgJrU25] = reiter.altersklasseJgJrU25
|
it[altersklasseJgJrU25] = reiter.altersklasseJgJrU25?.name
|
||||||
it[altersklasseY] = reiter.altersklasseY
|
it[altersklasseY] = reiter.altersklasseY?.name
|
||||||
it[mitgliedsNummer] = reiter.mitgliedsNummer
|
it[mitgliedsNummer] = reiter.mitgliedsNummer
|
||||||
it[telefonNummer] = reiter.telefonNummer
|
it[telefonNummer] = reiter.telefonNummer
|
||||||
it[kader] = reiter.kader
|
it[kader] = reiter.kader
|
||||||
@@ -117,6 +141,7 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
it[datenQuelle] = reiter.datenQuelle.name
|
it[datenQuelle] = reiter.datenQuelle.name
|
||||||
it[updatedAt] = reiter.updatedAt
|
it[updatedAt] = reiter.updatedAt
|
||||||
}
|
}
|
||||||
|
saveLizenzen(reiter)
|
||||||
} else {
|
} else {
|
||||||
ReiterTable.insert {
|
ReiterTable.insert {
|
||||||
it[id] = reiter.reiterId
|
it[id] = reiter.reiterId
|
||||||
@@ -130,11 +155,14 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
it[vereinId] = reiter.vereinId
|
it[vereinId] = reiter.vereinId
|
||||||
it[bundeslandId] = reiter.bundeslandId
|
it[bundeslandId] = reiter.bundeslandId
|
||||||
it[nationId] = reiter.nationId
|
it[nationId] = reiter.nationId
|
||||||
|
it[reitLizenzId] = reiter.reitLizenzId
|
||||||
|
it[fahrLizenzId] = reiter.fahrLizenzId
|
||||||
|
it[startkarteId] = reiter.startkarteId
|
||||||
it[reiterLizenz] = reiter.reiterLizenz
|
it[reiterLizenz] = reiter.reiterLizenz
|
||||||
it[startkarte] = reiter.startkarte
|
it[startkarte] = reiter.startkarte
|
||||||
it[fahrLizenz] = reiter.fahrLizenz
|
it[fahrLizenz] = reiter.fahrLizenz
|
||||||
it[altersklasseJgJrU25] = reiter.altersklasseJgJrU25
|
it[altersklasseJgJrU25] = reiter.altersklasseJgJrU25?.name
|
||||||
it[altersklasseY] = reiter.altersklasseY
|
it[altersklasseY] = reiter.altersklasseY?.name
|
||||||
it[mitgliedsNummer] = reiter.mitgliedsNummer
|
it[mitgliedsNummer] = reiter.mitgliedsNummer
|
||||||
it[telefonNummer] = reiter.telefonNummer
|
it[telefonNummer] = reiter.telefonNummer
|
||||||
it[kader] = reiter.kader
|
it[kader] = reiter.kader
|
||||||
@@ -151,11 +179,25 @@ class ReiterExposedRepository : ReiterRepository {
|
|||||||
it[createdAt] = reiter.createdAt
|
it[createdAt] = reiter.createdAt
|
||||||
it[updatedAt] = reiter.updatedAt
|
it[updatedAt] = reiter.updatedAt
|
||||||
}
|
}
|
||||||
|
saveLizenzen(reiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
reiter
|
reiter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveLizenzen(reiter: Reiter) {
|
||||||
|
ReiterLizenzenZuordnungTable.deleteWhere { reiterId eq reiter.reiterId }
|
||||||
|
reiter.lizenzen.forEach { lizenz ->
|
||||||
|
ReiterLizenzenZuordnungTable.insert {
|
||||||
|
it[id] = lizenz.lizenzId
|
||||||
|
it[reiterId] = reiter.reiterId
|
||||||
|
it[lizenzTyp] = lizenz.lizenzTyp
|
||||||
|
it[kuerzel] = lizenz.kuerzel
|
||||||
|
it[gueltigBis] = lizenz.gueltigBis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
|
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
|
||||||
ReiterTable.deleteWhere { ReiterTable.id eq id } > 0
|
ReiterTable.deleteWhere { ReiterTable.id eq id } > 0
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-17
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
package at.mocode.masterdata.infrastructure.persistence.reiter
|
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.BundeslaenderTable
|
||||||
import org.jetbrains.exposed.v1.core.Table
|
import org.jetbrains.exposed.v1.core.Table
|
||||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||||
import org.jetbrains.exposed.v1.datetime.date
|
import org.jetbrains.exposed.v1.datetime.date
|
||||||
@@ -27,6 +28,9 @@ object ReiterTable : Table("reiter") {
|
|||||||
val vereinId = uuid("verein_id").nullable()
|
val vereinId = uuid("verein_id").nullable()
|
||||||
val bundeslandId = uuid("bundesland_id").nullable()
|
val bundeslandId = uuid("bundesland_id").nullable()
|
||||||
val nationId = uuid("nation_id").nullable()
|
val nationId = uuid("nation_id").nullable()
|
||||||
|
val reitLizenzId = uuid("reit_lizenz_id").nullable()
|
||||||
|
val fahrLizenzId = uuid("fahr_lizenz_id").nullable()
|
||||||
|
val startkarteId = uuid("startkarte_id").nullable()
|
||||||
|
|
||||||
val reiterLizenz = varchar("reiter_lizenz", 20).nullable()
|
val reiterLizenz = varchar("reiter_lizenz", 20).nullable()
|
||||||
val startkarte = varchar("startkarte", 20).nullable()
|
val startkarte = varchar("startkarte", 20).nullable()
|
||||||
@@ -65,24 +69,10 @@ object ReiterTable : Table("reiter") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposed-Tabellendefinition für die Bundesland-Mastertabelle.
|
* Exposed-Tabellendefinition für die Reiter-Lizenzen-Zuordnung (historisch/mehrfach).
|
||||||
*/
|
*/
|
||||||
object BundeslandTable : Table("bundesland") {
|
object ReiterLizenzenZuordnungTable : Table("reiter_lizenzen_zuordnung") {
|
||||||
val id = uuid("bundesland_id")
|
val id = uuid("lizenz_zuordnung_id")
|
||||||
val bundeslandNr = integer("bundesland_nr").uniqueIndex()
|
|
||||||
val bezeichnung = varchar("bezeichnung", 100)
|
|
||||||
val wappenUrl = varchar("wappen_url", 255).nullable()
|
|
||||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
|
||||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
|
||||||
|
|
||||||
override val primaryKey = PrimaryKey(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exposed-Tabellendefinition für die Reiter-Lizenzen.
|
|
||||||
*/
|
|
||||||
object ReiterLizenzTable : Table("reiter_lizenz") {
|
|
||||||
val id = uuid("lizenz_id")
|
|
||||||
val reiterId = uuid("reiter_id")
|
val reiterId = uuid("reiter_id")
|
||||||
val lizenzTyp = varchar("lizenz_typ", 50) // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
|
val lizenzTyp = varchar("lizenz_typ", 50) // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
|
||||||
val kuerzel = varchar("kuerzel", 20)
|
val kuerzel = varchar("kuerzel", 20)
|
||||||
@@ -92,3 +82,46 @@ object ReiterLizenzTable : Table("reiter_lizenz") {
|
|||||||
|
|
||||||
override val primaryKey = PrimaryKey(id)
|
override val primaryKey = PrimaryKey(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-Tabellendefinition für Reit-Lizenzen (Stammdaten).
|
||||||
|
*/
|
||||||
|
object ReitLizenzenTable : Table("reit_lizenzen") {
|
||||||
|
val id = uuid("lizenz_id")
|
||||||
|
val code = varchar("code", 20).uniqueIndex()
|
||||||
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
|
val sparte = varchar("sparte", 20).nullable()
|
||||||
|
val istAktiv = bool("ist_aktiv").default(true)
|
||||||
|
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||||
|
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-Tabellendefinition für Fahr-Lizenzen (Stammdaten).
|
||||||
|
*/
|
||||||
|
object FahrLizenzenTable : Table("fahr_lizenzen") {
|
||||||
|
val id = uuid("lizenz_id")
|
||||||
|
val code = varchar("code", 20).uniqueIndex()
|
||||||
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
|
val istAktiv = bool("ist_aktiv").default(true)
|
||||||
|
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||||
|
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposed-Tabellendefinition für Startkarten (Stammdaten).
|
||||||
|
*/
|
||||||
|
object StartkartenTable : Table("startkarten") {
|
||||||
|
val id = uuid("startkarte_id")
|
||||||
|
val code = varchar("code", 20).uniqueIndex()
|
||||||
|
val bezeichnung = varchar("bezeichnung", 100)
|
||||||
|
val istAktiv = bool("ist_aktiv").default(true)
|
||||||
|
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||||
|
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ class RegulationSeedVerificationTest {
|
|||||||
Database.connect("jdbc:h2:mem:regulationseed;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
|
Database.connect("jdbc:h2:mem:regulationseed;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
|
||||||
transaction {
|
transaction {
|
||||||
SchemaUtils.create(
|
SchemaUtils.create(
|
||||||
TurnierklasseTable,
|
TurnierKlassenTable,
|
||||||
LicenseTable,
|
LicenseTable,
|
||||||
RichtverfahrenTable,
|
RichtverfahrenTable,
|
||||||
GebuehrTable,
|
GebuehrTable,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ dependencies {
|
|||||||
implementation(libs.spring.boot.starter.web)
|
implementation(libs.spring.boot.starter.web)
|
||||||
implementation(libs.spring.boot.starter.validation)
|
implementation(libs.spring.boot.starter.validation)
|
||||||
implementation(libs.spring.boot.starter.actuator)
|
implementation(libs.spring.boot.starter.actuator)
|
||||||
|
implementation(libs.spring.cloud.starter.consul.discovery)
|
||||||
implementation(libs.jackson.module.kotlin)
|
implementation(libs.jackson.module.kotlin)
|
||||||
//implementation(libs.springdoc.openapi.starter.webmvc.ui)
|
//implementation(libs.springdoc.openapi.starter.webmvc.ui)
|
||||||
|
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.AltersklasseTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Altersklassen gemäß LIZENZ01.DAT (JG, JR, 25, Y).
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class AltersklassenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(AltersklassenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Altersklassen...")
|
||||||
|
transaction {
|
||||||
|
val klassen = listOf(
|
||||||
|
Triple("JG", "JUGENDLICHER", "Altersklasse Jugend"),
|
||||||
|
Triple("JR", "JUNIOR", "Altersklasse Junior"),
|
||||||
|
Triple("25", "U25", "Altersklasse U25"),
|
||||||
|
Triple("Y", "JUNGER-REITER", "Altersklasse Junger Reiter")
|
||||||
|
)
|
||||||
|
|
||||||
|
klassen.forEach { (code, bez, desc) ->
|
||||||
|
upsertAltersklasse(code, bez)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun upsertAltersklasse(code: String, bezeichnung: String) {
|
||||||
|
val exists = AltersklasseTable.selectAll()
|
||||||
|
.where { AltersklasseTable.altersklasseCode eq code }
|
||||||
|
.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
AltersklasseTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[altersklasseCode] = code
|
||||||
|
it[AltersklasseTable.bezeichnung] = bezeichnung
|
||||||
|
it[istAktiv] = true
|
||||||
|
}
|
||||||
|
log.debug("Altersklasse '{}' angelegt.", code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.TurnierKlassenTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Bewerbsklassen (ehemals Turnierklassen) gemäß ÖTO.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class BewerbsKlassenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(BewerbsKlassenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Bewerbsklassen...")
|
||||||
|
transaction {
|
||||||
|
seedSpringenKlassen()
|
||||||
|
seedDressurKlassen()
|
||||||
|
}
|
||||||
|
log.info("Seeding der Bewerbsklassen abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedSpringenKlassen() {
|
||||||
|
val klassen = listOf(
|
||||||
|
Triple("E", "Einsteiger", 80),
|
||||||
|
Triple("A", "Anfänger", 105),
|
||||||
|
Triple("L", "Leicht", 115),
|
||||||
|
Triple("LM", "Leicht-Mittel", 125),
|
||||||
|
Triple("M", "Mittelschwer", 135),
|
||||||
|
Triple("S", "Schwer", 150)
|
||||||
|
)
|
||||||
|
klassen.forEach { (code, bez, hoehe) ->
|
||||||
|
upsertKlasse("SPRINGEN", code, bez, hoehe, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedDressurKlassen() {
|
||||||
|
val klassen = listOf(
|
||||||
|
Triple("E", "Einsteiger", "Aufgaben E"),
|
||||||
|
Triple("A", "Anfänger", "Aufgaben A"),
|
||||||
|
Triple("L", "Leicht", "Aufgaben L"),
|
||||||
|
Triple("LM", "Leicht-Mittel", "Aufgaben LM"),
|
||||||
|
Triple("M", "Mittelschwer", "Aufgaben M"),
|
||||||
|
Triple("S", "Schwer", "Aufgaben S")
|
||||||
|
)
|
||||||
|
klassen.forEach { (code, bez, niveau) ->
|
||||||
|
upsertKlasse("DRESSUR", code, bez, null, niveau)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun upsertKlasse(sparte: String, code: String, bezeichnung: String, hoehe: Int?, niveau: String?) {
|
||||||
|
val exists = TurnierKlassenTable.selectAll()
|
||||||
|
.where { (TurnierKlassenTable.sparte eq sparte) and (TurnierKlassenTable.code eq code) }
|
||||||
|
.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
TurnierKlassenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[TurnierKlassenTable.sparte] = sparte
|
||||||
|
it[TurnierKlassenTable.code] = code
|
||||||
|
it[TurnierKlassenTable.bezeichnung] = bezeichnung
|
||||||
|
it[TurnierKlassenTable.maxHoehe] = hoehe
|
||||||
|
it[TurnierKlassenTable.aufgabenNiveau] = niveau
|
||||||
|
}
|
||||||
|
log.debug("Bewerbsklasse '{}' ({}) angelegt.", code, sparte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaersQualifikationenTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Funktionärs-Qualifikationen.
|
||||||
|
* Befüllt die FunktionaersQualifikationenTable mit Standard-Werten.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class FunktionaersQualifikationenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(FunktionaersQualifikationenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Funktionärs-Qualifikationen...")
|
||||||
|
transaction {
|
||||||
|
seedRichterQualifikationen()
|
||||||
|
seedParcoursbauerQualifikationen()
|
||||||
|
}
|
||||||
|
log.info("Seeding der Funktionärs-Qualifikationen abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedRichterQualifikationen() {
|
||||||
|
val qualis = listOf(
|
||||||
|
"D" to "Dressur",
|
||||||
|
"S" to "Springen",
|
||||||
|
"DPF" to "Dressurpferde",
|
||||||
|
"SPF" to "Springpferde",
|
||||||
|
"G" to "Gelände",
|
||||||
|
"STW" to "Steward",
|
||||||
|
"DM" to "Dressur Master",
|
||||||
|
"SM" to "Springen Master"
|
||||||
|
)
|
||||||
|
qualis.forEach { (code, bezeichnung) ->
|
||||||
|
upsertQualifikation(code, bezeichnung, "RICHTER")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedParcoursbauerQualifikationen() {
|
||||||
|
val qualis = listOf(
|
||||||
|
"P1" to "Einsteiger",
|
||||||
|
"P2" to "Fortgeschritten",
|
||||||
|
"P3" to "National",
|
||||||
|
"P4" to "Grand Prix"
|
||||||
|
)
|
||||||
|
qualis.forEach { (code, bezeichnung) ->
|
||||||
|
upsertQualifikation(code, bezeichnung, "PARCOURSBAUER")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun upsertQualifikation(code: String, bezeichnung: String, typ: String) {
|
||||||
|
val exists = FunktionaersQualifikationenTable.selectAll()
|
||||||
|
.where { (FunktionaersQualifikationenTable.code eq code) and (FunktionaersQualifikationenTable.typ eq typ) }
|
||||||
|
.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
FunktionaersQualifikationenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[FunktionaersQualifikationenTable.code] = code
|
||||||
|
it[FunktionaersQualifikationenTable.bezeichnung] = bezeichnung
|
||||||
|
it[FunktionaersQualifikationenTable.typ] = typ
|
||||||
|
}
|
||||||
|
log.debug("Qualifikation '{}' ({}) angelegt.", code, typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
-17
@@ -1,14 +1,11 @@
|
|||||||
package at.mocode.masterdata.service.config
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.*
|
import at.mocode.masterdata.infrastructure.persistence.*
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerQualifikationTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerQualifikationTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.QualifikationMasterTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaersQualifikationenTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
import at.mocode.masterdata.infrastructure.persistence.reiter.*
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterLizenzTable
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.BundeslandTable
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
import jakarta.annotation.PreDestroy
|
import jakarta.annotation.PreDestroy
|
||||||
@@ -46,22 +43,26 @@ class MasterdataDatabaseConfiguration(
|
|||||||
transaction {
|
transaction {
|
||||||
SchemaUtils.create(
|
SchemaUtils.create(
|
||||||
LandTable,
|
LandTable,
|
||||||
BundeslandTable,
|
BundeslaenderTable,
|
||||||
AltersklasseTable,
|
AltersklasseTable,
|
||||||
PlatzTable,
|
PlatzTable,
|
||||||
ReiterTable,
|
ReiterTable,
|
||||||
HorseTable,
|
HorseTable,
|
||||||
VereinTable,
|
VereinTable,
|
||||||
FunktionaerTable,
|
FunktionaerTable,
|
||||||
QualifikationMasterTable,
|
FunktionaersQualifikationenTable,
|
||||||
FunktionaerQualifikationTable,
|
FunktionaerQualifikationTable,
|
||||||
ReiterLizenzTable,
|
ReitLizenzenTable,
|
||||||
TurnierklasseTable,
|
FahrLizenzenTable,
|
||||||
|
StartkartenTable,
|
||||||
|
ReiterLizenzenZuordnungTable,
|
||||||
|
TurnierKlassenTable,
|
||||||
|
TurnierSpartenTable,
|
||||||
|
TurnierKategorienTable,
|
||||||
LicenseTable,
|
LicenseTable,
|
||||||
RichtverfahrenTable,
|
RichtverfahrenTable,
|
||||||
GebuehrTable,
|
GebuehrTable,
|
||||||
RegulationConfigTable,
|
RegulationConfigTable
|
||||||
ReiterSparteTable
|
|
||||||
)
|
)
|
||||||
log.info("Masterdata database schema initialized successfully")
|
log.info("Masterdata database schema initialized successfully")
|
||||||
}
|
}
|
||||||
@@ -95,22 +96,26 @@ class MasterdataTestDatabaseConfiguration {
|
|||||||
transaction {
|
transaction {
|
||||||
SchemaUtils.create(
|
SchemaUtils.create(
|
||||||
LandTable,
|
LandTable,
|
||||||
BundeslandTable,
|
BundeslaenderTable,
|
||||||
AltersklasseTable,
|
AltersklasseTable,
|
||||||
PlatzTable,
|
PlatzTable,
|
||||||
ReiterTable,
|
ReiterTable,
|
||||||
HorseTable,
|
HorseTable,
|
||||||
VereinTable,
|
VereinTable,
|
||||||
FunktionaerTable,
|
FunktionaerTable,
|
||||||
QualifikationMasterTable,
|
FunktionaersQualifikationenTable,
|
||||||
FunktionaerQualifikationTable,
|
FunktionaerQualifikationTable,
|
||||||
ReiterLizenzTable,
|
ReitLizenzenTable,
|
||||||
TurnierklasseTable,
|
FahrLizenzenTable,
|
||||||
|
StartkartenTable,
|
||||||
|
ReiterLizenzenZuordnungTable,
|
||||||
|
TurnierKlassenTable,
|
||||||
|
TurnierSpartenTable,
|
||||||
|
TurnierKategorienTable,
|
||||||
LicenseTable,
|
LicenseTable,
|
||||||
RichtverfahrenTable,
|
RichtverfahrenTable,
|
||||||
GebuehrTable,
|
GebuehrTable,
|
||||||
RegulationConfigTable,
|
RegulationConfigTable
|
||||||
ReiterSparteTable
|
|
||||||
)
|
)
|
||||||
log.info("Test masterdata database schema initialized successfully")
|
log.info("Test masterdata database schema initialized successfully")
|
||||||
}
|
}
|
||||||
|
|||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.BundeslaenderTable
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.LandTable
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Nationen (Länder) und Bundesländer.
|
||||||
|
* Stellt sicher, dass die für den ZNS-Import notwendigen Masterdaten vorhanden sind.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class MasterdataSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(MasterdataSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Master-Daten (Länder & Bundesländer)...")
|
||||||
|
transaction {
|
||||||
|
seedCountries()
|
||||||
|
seedAustrianBundeslaender()
|
||||||
|
fixReiterForeignKeys()
|
||||||
|
}
|
||||||
|
log.info("Seeding der Master-Daten abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fixReiterForeignKeys() {
|
||||||
|
// Falls Reiter bereits importiert wurden, bevor die Masterdaten da waren,
|
||||||
|
// versuchen wir hier die Verknüpfungen (FKs) zu heilen.
|
||||||
|
log.info("Prüfe und korrigiere Reiter-Fremdschlüssel (Heilung)...")
|
||||||
|
|
||||||
|
// 1. Bundesland-Links heilen
|
||||||
|
val states = BundeslaenderTable.selectAll().toList()
|
||||||
|
states.forEach { row ->
|
||||||
|
val bId = row[BundeslaenderTable.id]
|
||||||
|
val bNr = row[BundeslaenderTable.bundeslandNr]
|
||||||
|
if (bNr != null) {
|
||||||
|
ReiterTable.update({ (ReiterTable.bundeslandNummer eq bNr) and (ReiterTable.bundeslandId.isNull()) }) {
|
||||||
|
it[bundeslandId] = bId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Nation-Links heilen (ISO-Alpha3 Lookup)
|
||||||
|
val nations = LandTable.selectAll().toList()
|
||||||
|
nations.forEach { row ->
|
||||||
|
val nId = row[LandTable.id]
|
||||||
|
val iso3 = row[LandTable.isoAlpha3Code]
|
||||||
|
ReiterTable.update({ (ReiterTable.nation eq iso3) and (ReiterTable.nationId.isNull()) }) {
|
||||||
|
it[nationId] = nId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Verein-Links heilen (Lookup über Name)
|
||||||
|
log.info("Heile Reiter-Vereins-Verknüpfungen via Name...")
|
||||||
|
val vt = at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||||
|
val vereine = vt.selectAll().toList()
|
||||||
|
vereine.forEach { row ->
|
||||||
|
val vId = row[vt.id]
|
||||||
|
val vName = row[vt.vereinName]
|
||||||
|
ReiterTable.update({ (ReiterTable.vereinsName eq vName) and (ReiterTable.vereinId.isNull()) }) {
|
||||||
|
it[vereinId] = vId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedCountries() {
|
||||||
|
val countries = listOf(
|
||||||
|
// iso2, iso3, num, nameDe, nameEn, eu, ewr, sort
|
||||||
|
listOf("AT", "AUT", "040", "Österreich", "Austria", true, true, 1),
|
||||||
|
listOf("DE", "DEU", "276", "Deutschland", "Germany", true, true, 2),
|
||||||
|
listOf("CH", "CHE", "756", "Schweiz", "Switzerland", false, false, 3),
|
||||||
|
listOf("IT", "ITA", "380", "Italien", "Italy", true, true, 4),
|
||||||
|
listOf("CZ", "CZE", "203", "Tschechien", "Czech Republic", true, true, 6),
|
||||||
|
listOf("SK", "SVK", "703", "Slowakei", "Slovakia", true, true, 7),
|
||||||
|
listOf("SI", "SVN", "705", "Slowenien", "Slovenia", true, true, 8),
|
||||||
|
listOf("HU", "HUN", "348", "Ungarn", "Hungary", true, true, 9),
|
||||||
|
listOf("LI", "LIE", "438", "Liechtenstein", "Liechtenstein", false, true, 11)
|
||||||
|
)
|
||||||
|
|
||||||
|
countries.forEach { c ->
|
||||||
|
val iso2 = c[0] as String
|
||||||
|
val exists = LandTable.selectAll().where { LandTable.isoAlpha2Code eq iso2 }.any()
|
||||||
|
if (!exists) {
|
||||||
|
LandTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[isoAlpha2Code] = iso2
|
||||||
|
it[isoAlpha3Code] = c[1] as String
|
||||||
|
it[isoNumerischerCode] = c[2] as String
|
||||||
|
it[nameDeutsch] = c[3] as String
|
||||||
|
it[nameEnglisch] = c[4] as String
|
||||||
|
it[istEuMitglied] = c[5] as Boolean
|
||||||
|
it[istEwrMitglied] = c[6] as Boolean
|
||||||
|
it[sortierReihenfolge] = c[7] as Int
|
||||||
|
}
|
||||||
|
log.debug("Land '{}' angelegt.", iso2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedAustrianBundeslaender() {
|
||||||
|
val austria = LandTable.selectAll().where { LandTable.isoAlpha2Code eq "AT" }.singleOrNull()
|
||||||
|
if (austria == null) {
|
||||||
|
log.error("Österreich (AT) nicht gefunden, überspringe Bundesland-Seeding.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val austriaId = austria[LandTable.id]
|
||||||
|
|
||||||
|
val states = listOf(
|
||||||
|
// nr, name, kuerzel, oeps
|
||||||
|
listOf(1, "Wien", "W", "09"),
|
||||||
|
listOf(2, "Niederösterreich", "NÖ", "03"),
|
||||||
|
listOf(3, "Burgenland", "BGLD", "01"),
|
||||||
|
listOf(4, "Steiermark", "STMK", "06"),
|
||||||
|
listOf(5, "Kärnten", "KTN", "02"),
|
||||||
|
listOf(6, "Oberösterreich", "OÖ", "04"),
|
||||||
|
listOf(7, "Salzburg", "SBG", "05"),
|
||||||
|
listOf(8, "Tirol", "T", "07"),
|
||||||
|
listOf(9, "Vorarlberg", "VBG", "08"),
|
||||||
|
listOf(0, "Unbekannt", "UNK", "00")
|
||||||
|
)
|
||||||
|
|
||||||
|
states.forEach { s ->
|
||||||
|
val nr = s[0] as Int
|
||||||
|
val name = s[1] as String
|
||||||
|
val kuerzel = s[2] as String
|
||||||
|
val oeps = s[3] as String
|
||||||
|
|
||||||
|
val exists = BundeslaenderTable.selectAll().where {
|
||||||
|
(BundeslaenderTable.landId eq austriaId) and (BundeslaenderTable.bundeslandNr eq nr)
|
||||||
|
}.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
BundeslaenderTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[landId] = austriaId
|
||||||
|
it[bundeslandNr] = nr
|
||||||
|
it[BundeslaenderTable.name] = name
|
||||||
|
it[BundeslaenderTable.kuerzel] = kuerzel
|
||||||
|
it[oepsCode] = oeps
|
||||||
|
}
|
||||||
|
log.debug("Bundesland '{}' (Nr. {}) angelegt.", name, nr)
|
||||||
|
} else {
|
||||||
|
// Update falls vorhanden (Harmonisierung)
|
||||||
|
BundeslaenderTable.update({ (BundeslaenderTable.landId eq austriaId) and (BundeslaenderTable.bundeslandNr eq nr) }) {
|
||||||
|
it[BundeslaenderTable.name] = name
|
||||||
|
it[BundeslaenderTable.kuerzel] = kuerzel
|
||||||
|
it[oepsCode] = oeps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-86
@@ -1,86 +0,0 @@
|
|||||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
|
||||||
package at.mocode.masterdata.service.config
|
|
||||||
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.QualifikationMasterTable
|
|
||||||
import jakarta.annotation.PostConstruct
|
|
||||||
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
|
||||||
import org.jetbrains.exposed.v1.core.*
|
|
||||||
import org.jetbrains.exposed.v1.jdbc.*
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
import org.springframework.context.annotation.DependsOn
|
|
||||||
import org.springframework.context.annotation.Profile
|
|
||||||
import kotlin.uuid.Uuid
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Seeder für die offiziellen ÖTO/FEI Qualifikations-Kürzel.
|
|
||||||
* Befüllt die QualifikationMasterTable mit Standard-Werten.
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
@Profile("!test")
|
|
||||||
@DependsOn("masterdataDatabaseConfiguration")
|
|
||||||
class QualifikationMasterSeeder {
|
|
||||||
private val log = LoggerFactory.getLogger(QualifikationMasterSeeder::class.java)
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
fun seed() {
|
|
||||||
log.info("Starte Seeding der Qualifikations-Master-Daten (ÖTO/FEI)...")
|
|
||||||
transaction {
|
|
||||||
seedRichter()
|
|
||||||
seedParcoursbauer()
|
|
||||||
}
|
|
||||||
log.info("Seeding der Qualifikations-Master-Daten abgeschlossen.")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun seedRichter() {
|
|
||||||
val richterQualis = listOf(
|
|
||||||
"D" to "Dressur",
|
|
||||||
"S" to "Springen",
|
|
||||||
"DPF" to "Dressurpferde",
|
|
||||||
"SPF" to "Springpferde",
|
|
||||||
"G" to "Gelände",
|
|
||||||
"STW" to "Steward",
|
|
||||||
"DM" to "Dressur Master",
|
|
||||||
"SM" to "Springen Master",
|
|
||||||
"GA" to "Grundausbildung",
|
|
||||||
"G3" to "Gruppe 3",
|
|
||||||
"G2" to "Gruppe 2",
|
|
||||||
"G1" to "Gruppe 1"
|
|
||||||
)
|
|
||||||
|
|
||||||
richterQualis.forEach { (code, bezeichnung) ->
|
|
||||||
upsertQuali(code, bezeichnung, "RICHTER")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun seedParcoursbauer() {
|
|
||||||
val pbQualis = listOf(
|
|
||||||
"P1" to "Einsteiger",
|
|
||||||
"P2" to "Fortgeschritten",
|
|
||||||
"P3" to "National",
|
|
||||||
"P4" to "Grand Prix",
|
|
||||||
"SP" to "Springen",
|
|
||||||
"VS" to "Vielseitigkeit"
|
|
||||||
)
|
|
||||||
|
|
||||||
pbQualis.forEach { (code, bezeichnung) ->
|
|
||||||
upsertQuali(code, bezeichnung, "PARCOURSBAUER")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun upsertQuali(code: String, bezeichnung: String, typ: String) {
|
|
||||||
val exists = QualifikationMasterTable.selectAll()
|
|
||||||
.where { (QualifikationMasterTable.code eq code) and (QualifikationMasterTable.typ eq typ) }
|
|
||||||
.any()
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
QualifikationMasterTable.insert {
|
|
||||||
it[id] = Uuid.random()
|
|
||||||
it[QualifikationMasterTable.code] = code
|
|
||||||
it[QualifikationMasterTable.bezeichnung] = bezeichnung
|
|
||||||
it[QualifikationMasterTable.typ] = typ
|
|
||||||
}
|
|
||||||
log.debug("QualifikationMaster '{}' ({}) angelegt.", code, typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.FahrLizenzenTable
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.StartkartenTable
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.ReitLizenzenTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Reit-Lizenzen, Fahr-Lizenzen und Startkarten.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class ReitLizenzenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(ReitLizenzenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Lizenzen...")
|
||||||
|
transaction {
|
||||||
|
seedReitLizenzen()
|
||||||
|
seedFahrLizenzen()
|
||||||
|
seedStartkarten()
|
||||||
|
}
|
||||||
|
log.info("Seeding der Lizenzen abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedReitLizenzen() {
|
||||||
|
val lizenzen = listOf(
|
||||||
|
Triple("R1", "Reitlizenz R1", "SPRINGEN"),
|
||||||
|
Triple("RD1", "Reitlizenz RD1", "DRESSUR"),
|
||||||
|
Triple("RD2", "Reitlizenz RD2", "DRESSUR"),
|
||||||
|
Triple("RS2", "Reitlizenz RS2", "SPRINGEN")
|
||||||
|
)
|
||||||
|
lizenzen.forEach { (code, bez, sparte) ->
|
||||||
|
if (ReitLizenzenTable.selectAll().where { ReitLizenzenTable.code eq code }.none()) {
|
||||||
|
ReitLizenzenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[ReitLizenzenTable.code] = code
|
||||||
|
it[bezeichnung] = bez
|
||||||
|
it[ReitLizenzenTable.sparte] = sparte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedFahrLizenzen() {
|
||||||
|
val lizenzen = listOf(
|
||||||
|
Pair("F1", "Fahrlizenz F1"),
|
||||||
|
Pair("F2", "Fahrlizenz F2")
|
||||||
|
)
|
||||||
|
lizenzen.forEach { (code, bez) ->
|
||||||
|
if (FahrLizenzenTable.selectAll().where { FahrLizenzenTable.code eq code }.none()) {
|
||||||
|
FahrLizenzenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[FahrLizenzenTable.code] = code
|
||||||
|
it[bezeichnung] = bez
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedStartkarten() {
|
||||||
|
val karten = listOf(
|
||||||
|
Pair("S1", "Startkarte S1"),
|
||||||
|
Pair("S2", "Startkarte S2")
|
||||||
|
)
|
||||||
|
karten.forEach { (code, bez) ->
|
||||||
|
if (StartkartenTable.selectAll().where { StartkartenTable.code eq code }.none()) {
|
||||||
|
StartkartenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[StartkartenTable.code] = code
|
||||||
|
it[bezeichnung] = bez
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.TurnierKategorienTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Turnier-Kategorien (z.B. CSN-C, CDN-A).
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class TurnierKategorienSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(TurnierKategorienSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Turnier-Kategorien...")
|
||||||
|
transaction {
|
||||||
|
val kategorien = listOf(
|
||||||
|
Triple("CSN-C", "Nationales Springturnier Kategorie C", "SPRINGEN"),
|
||||||
|
Triple("CSN-C Neu", "Nationales Springturnier Kategorie C Neu", "SPRINGEN"),
|
||||||
|
Triple("CSN-B", "Nationales Springturnier Kategorie B", "SPRINGEN"),
|
||||||
|
Triple("CSN-A", "Nationales Springturnier Kategorie A", "SPRINGEN"),
|
||||||
|
Triple("CDN-C", "Nationales Dressurturnier Kategorie C", "DRESSUR"),
|
||||||
|
Triple("CDN-B", "Nationales Dressurturnier Kategorie B", "DRESSUR"),
|
||||||
|
Triple("CDN-A", "Nationales Dressurturnier Kategorie A", "DRESSUR")
|
||||||
|
)
|
||||||
|
|
||||||
|
kategorien.forEach { (code, bez, sparte) ->
|
||||||
|
if (TurnierKategorienTable.selectAll().where { TurnierKategorienTable.code eq code }.none()) {
|
||||||
|
TurnierKategorienTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[TurnierKategorienTable.code] = code
|
||||||
|
it[bezeichnung] = bez
|
||||||
|
it[TurnierKategorienTable.sparte] = sparte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.TurnierKlassenTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Turnierklassen (z.B. E, A, L, M, S) gemäß ÖTO.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class TurnierKlassenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(TurnierKlassenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Turnierklassen...")
|
||||||
|
transaction {
|
||||||
|
seedSpringenKlassen()
|
||||||
|
seedDressurKlassen()
|
||||||
|
}
|
||||||
|
log.info("Seeding der Turnierklassen abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedSpringenKlassen() {
|
||||||
|
val klassen = listOf(
|
||||||
|
Triple("E", "Einsteiger", 80),
|
||||||
|
Triple("A", "Anfänger", 105),
|
||||||
|
Triple("L", "Leicht", 115),
|
||||||
|
Triple("LM", "Leicht-Mittel", 125),
|
||||||
|
Triple("M", "Mittelschwer", 135),
|
||||||
|
Triple("S", "Schwer", 150)
|
||||||
|
)
|
||||||
|
klassen.forEach { (code, bez, hoehe) ->
|
||||||
|
upsertKlasse("SPRINGEN", code, bez, hoehe, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seedDressurKlassen() {
|
||||||
|
val klassen = listOf(
|
||||||
|
Triple("E", "Einsteiger", "Aufgaben E"),
|
||||||
|
Triple("A", "Anfänger", "Aufgaben A"),
|
||||||
|
Triple("L", "Leicht", "Aufgaben L"),
|
||||||
|
Triple("LM", "Leicht-Mittel", "Aufgaben LM"),
|
||||||
|
Triple("M", "Mittelschwer", "Aufgaben M"),
|
||||||
|
Triple("S", "Schwer", "Aufgaben S")
|
||||||
|
)
|
||||||
|
klassen.forEach { (code, bez, niveau) ->
|
||||||
|
upsertKlasse("DRESSUR", code, bez, null, niveau)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun upsertKlasse(sparte: String, code: String, bezeichnung: String, hoehe: Int?, niveau: String?) {
|
||||||
|
val exists = TurnierKlassenTable.selectAll()
|
||||||
|
.where { (TurnierKlassenTable.sparte eq sparte) and (TurnierKlassenTable.code eq code) }
|
||||||
|
.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
TurnierKlassenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[TurnierKlassenTable.sparte] = sparte
|
||||||
|
it[TurnierKlassenTable.code] = code
|
||||||
|
it[TurnierKlassenTable.bezeichnung] = bezeichnung
|
||||||
|
it[TurnierKlassenTable.maxHoehe] = hoehe
|
||||||
|
it[TurnierKlassenTable.aufgabenNiveau] = niveau
|
||||||
|
}
|
||||||
|
log.debug("Turnierklasse '{}' ({}) angelegt.", code, sparte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||||
|
package at.mocode.masterdata.service.config
|
||||||
|
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.TurnierSpartenTable
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.insert
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
|
import org.jetbrains.exposed.v1.core.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.DependsOn
|
||||||
|
import org.springframework.context.annotation.Profile
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeder für Turnier-Sparten (z.B. Dressur, Springen, Vielseitigkeit) gemäß ÖTO.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("!test")
|
||||||
|
@DependsOn("masterdataDatabaseConfiguration")
|
||||||
|
class TurnierSpartenSeeder {
|
||||||
|
private val log = LoggerFactory.getLogger(TurnierSpartenSeeder::class.java)
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
fun seed() {
|
||||||
|
log.info("Starte Seeding der Turnier-Sparten...")
|
||||||
|
transaction {
|
||||||
|
val sparten = listOf(
|
||||||
|
"D" to "Dressur",
|
||||||
|
"S" to "Springen",
|
||||||
|
"V" to "Vielseitigkeit",
|
||||||
|
"F" to "Fahren",
|
||||||
|
"R" to "Reiten",
|
||||||
|
"C" to "Voltigieren",
|
||||||
|
"W" to "Western",
|
||||||
|
"O" to "Orientierungsreiten"
|
||||||
|
)
|
||||||
|
sparten.forEach { (code, bezeichnung) ->
|
||||||
|
upsertSparte(code, bezeichnung)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("Seeding der Turnier-Sparten abgeschlossen.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun upsertSparte(code: String, bezeichnung: String) {
|
||||||
|
val exists = TurnierSpartenTable.selectAll()
|
||||||
|
.where { TurnierSpartenTable.code eq code }
|
||||||
|
.any()
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
TurnierSpartenTable.insert {
|
||||||
|
it[id] = Uuid.random()
|
||||||
|
it[TurnierSpartenTable.code] = code
|
||||||
|
it[TurnierSpartenTable.bezeichnung] = bezeichnung
|
||||||
|
}
|
||||||
|
log.debug("Turnier-Sparte '{}' angelegt.", bezeichnung)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,24 @@ spring:
|
|||||||
flyway:
|
flyway:
|
||||||
enabled: true
|
enabled: true
|
||||||
baseline-on-migrate: true
|
baseline-on-migrate: true
|
||||||
|
cloud:
|
||||||
|
consul:
|
||||||
|
host: ${SPRING_CLOUD_CONSUL_HOST:localhost}
|
||||||
|
port: ${SPRING_CLOUD_CONSUL_PORT:8500}
|
||||||
|
enabled: ${CONSUL_ENABLED:true}
|
||||||
|
discovery:
|
||||||
|
enabled: ${CONSUL_ENABLED:true}
|
||||||
|
register: ${CONSUL_ENABLED:true}
|
||||||
|
health-check-path: /actuator/health
|
||||||
|
health-check-interval: 10s
|
||||||
|
health-check-port: 8086
|
||||||
|
instance-id: ${spring.application.name}-${server.port}-${random.uuid}
|
||||||
|
service-name: ${spring.application.name}
|
||||||
|
port: 8091
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8086 # Spring Boot Management Port (Actuator & Tomcat)
|
port: 8086 # Spring Boot Management Port (Actuator & Tomcat)
|
||||||
address: 127.0.0.1 # Sicherheit: Nur lokal erreichbar
|
address: 0.0.0.0 # Erreichbar für Consul Health Checks
|
||||||
|
|
||||||
masterdata:
|
masterdata:
|
||||||
http:
|
http:
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
-- V013__Cleanup_and_Standardize_Masterdata.sql
|
||||||
|
-- Datum: 6. April 2026
|
||||||
|
|
||||||
|
-- 1. Bundesland -> bundeslaender
|
||||||
|
ALTER TABLE bundesland RENAME TO bundeslaender;
|
||||||
|
ALTER TABLE bundeslaender RENAME COLUMN id TO bundesland_id;
|
||||||
|
ALTER INDEX IF EXISTS pk_bundesland RENAME TO pk_bundeslaender;
|
||||||
|
ALTER INDEX IF EXISTS idx_bundesland_oeps RENAME TO idx_bundeslaender_oeps;
|
||||||
|
ALTER INDEX IF EXISTS idx_bundesland_iso RENAME TO idx_bundeslaender_iso;
|
||||||
|
ALTER INDEX IF EXISTS ux_bundesland_land_kuerzel RENAME TO ux_bundeslaender_land_kuerzel;
|
||||||
|
ALTER INDEX IF EXISTS bundesland_bundesland_nr_unique RENAME TO bundeslaender_bundesland_nr_unique;
|
||||||
|
|
||||||
|
-- 2. qualifikation_master -> funktionaers_qualifikationen
|
||||||
|
ALTER TABLE qualifikation_master RENAME TO funktionaers_qualifikationen;
|
||||||
|
-- Die Join-Tabelle funktionaer_qualifikation bleibt als solche bestehen,
|
||||||
|
-- referenziert aber nun funktionaers_qualifikationen.
|
||||||
|
-- (Der Name der Join-Tabelle ist bereits fast korrekt, wir lassen sie vorerst so,
|
||||||
|
-- da sie die Verknüpfung zw. Funktionär und Qualifikation darstellt.)
|
||||||
|
-- Update: Der User möchte "funktionaers_qualifikationen" als Name für die Qualifikationen.
|
||||||
|
|
||||||
|
-- 3. reiter_lizenz -> reit_lizenzen
|
||||||
|
ALTER TABLE reiter_lizenz RENAME TO reit_lizenzen;
|
||||||
|
ALTER INDEX IF EXISTS pk_reiter_lizenz RENAME TO pk_reit_lizenzen;
|
||||||
|
|
||||||
|
-- 4. reiter_sparte entfernen
|
||||||
|
DROP TABLE IF EXISTS reiter_sparte;
|
||||||
|
|
||||||
|
-- 5. turnierklasse -> turnier_klassen
|
||||||
|
ALTER TABLE turnierklasse RENAME TO turnier_klassen;
|
||||||
|
ALTER INDEX IF EXISTS pk_turnierklasse RENAME TO pk_turnier_klassen;
|
||||||
|
ALTER INDEX IF EXISTS idx_turnierklasse_sparte_code RENAME TO idx_turnier_klassen_sparte_code;
|
||||||
|
|
||||||
|
-- 6. turnier_sparten erstellen
|
||||||
|
CREATE TABLE IF NOT EXISTS turnier_sparten (
|
||||||
|
sparte_id UUID PRIMARY KEY,
|
||||||
|
code VARCHAR(10) UNIQUE NOT NULL, -- z.B. D, S, V, F, R, C
|
||||||
|
bezeichnung VARCHAR(100) NOT NULL, -- z.B. Dressur, Springen, Vielseitigkeit, Fahren, Reiten, Voltigieren
|
||||||
|
ist_aktiv BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 7. Constraints aktualisieren (falls nötig)
|
||||||
|
-- Da wir nur Tabellen umbenannt haben, bleiben die Foreign Keys in PostgreSQL erhalten
|
||||||
|
-- und zeigen automatisch auf die neuen Tabellennamen.
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
-- V014__Expand_Masterdata_Rider_and_Competitions.sql
|
||||||
|
-- Datum: 6. April 2026
|
||||||
|
|
||||||
|
-- 1. altersklasse -> altersklassen
|
||||||
|
ALTER TABLE altersklasse RENAME TO altersklassen;
|
||||||
|
ALTER INDEX IF EXISTS pk_altersklasse RENAME TO pk_altersklassen;
|
||||||
|
ALTER INDEX IF EXISTS idx_altersklasse_aktiv RENAME TO idx_altersklassen_aktiv;
|
||||||
|
ALTER INDEX IF EXISTS idx_altersklasse_sparte RENAME TO idx_altersklassen_sparte;
|
||||||
|
ALTER INDEX IF EXISTS idx_altersklasse_geschlecht RENAME TO idx_altersklassen_geschlecht;
|
||||||
|
ALTER INDEX IF EXISTS idx_altersklasse_alter RENAME TO idx_altersklassen_alter;
|
||||||
|
|
||||||
|
-- 2. turnier_klassen -> bewerbs_klassen
|
||||||
|
ALTER TABLE turnier_klassen RENAME TO bewerbs_klassen;
|
||||||
|
ALTER TABLE bewerbs_klassen RENAME COLUMN turnierklasse_id TO bewerbsklasse_id;
|
||||||
|
ALTER INDEX IF EXISTS pk_turnier_klassen RENAME TO pk_bewerbs_klassen;
|
||||||
|
ALTER INDEX IF EXISTS idx_turnier_klassen_sparte_code RENAME TO idx_bewerbs_klassen_sparte_code;
|
||||||
|
|
||||||
|
-- 3. turnier_kategorien erstellen
|
||||||
|
CREATE TABLE IF NOT EXISTS turnier_kategorien (
|
||||||
|
kategorie_id UUID PRIMARY KEY,
|
||||||
|
code VARCHAR(20) UNIQUE NOT NULL, -- z.B. CSN-C, CDN-A, CSN-C Neu
|
||||||
|
bezeichnung VARCHAR(100) NOT NULL,
|
||||||
|
sparte VARCHAR(20), -- SPRINGEN, DRESSUR, etc.
|
||||||
|
ist_aktiv BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 4. reit_lizenzen anpassen: Ein Reiter hat 0..1 Reit-Lizenz (Kürzel wie R1, RD1, etc.)
|
||||||
|
-- Die bestehende Tabelle reit_lizenzen (Join-Tabelle/Mehrfach) wird hier
|
||||||
|
-- beibehalten für fachspezifische Detail-Lizenzen, aber wir fügen
|
||||||
|
-- in der Reiter-Tabelle direkte Spalten für die Haupt-Lizenzen hinzu.
|
||||||
|
-- Fahr-Lizenzen und Startkarten ebenfalls als 0..1 Spalten beim Reiter.
|
||||||
|
|
||||||
|
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS fahr_lizenz_id UUID;
|
||||||
|
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS startkarte_id UUID;
|
||||||
|
|
||||||
|
-- 5. fahr_lizenzen Master-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS fahr_lizenzen (
|
||||||
|
lizenz_id UUID PRIMARY KEY,
|
||||||
|
code VARCHAR(20) UNIQUE NOT NULL, -- z.B. F1, F2
|
||||||
|
bezeichnung VARCHAR(100) NOT NULL,
|
||||||
|
ist_aktiv BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 6. startkarten Master-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS startkarten (
|
||||||
|
startkarte_id UUID PRIMARY KEY,
|
||||||
|
code VARCHAR(20) UNIQUE NOT NULL, -- z.B. S1, S2
|
||||||
|
bezeichnung VARCHAR(100) NOT NULL,
|
||||||
|
ist_aktiv BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 7. reit_lizenzen (Master-Tabelle für Kürzel-Definitionen)
|
||||||
|
-- Wir hatten reit_lizenzen als Join-Tabelle definiert in V013.
|
||||||
|
-- Wir behalten reit_lizenzen als Join-Tabelle (reiter_id, kuerzel) bei,
|
||||||
|
-- aber fügen eine Master-Tabelle für die Kürzel selbst hinzu.
|
||||||
|
-- Umbenennung der in V013 erstellten reit_lizenzen zu reiter_lizenzen_zuordnung
|
||||||
|
ALTER TABLE reit_lizenzen RENAME TO reiter_lizenzen_zuordnung;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS reit_lizenzen (
|
||||||
|
lizenz_id UUID PRIMARY KEY,
|
||||||
|
code VARCHAR(20) UNIQUE NOT NULL, -- z.B. R1, RD1, RS2
|
||||||
|
bezeichnung VARCHAR(100) NOT NULL,
|
||||||
|
sparte VARCHAR(20), -- SPRINGEN, DRESSUR, VIELSEITIGKEIT
|
||||||
|
ist_aktiv BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 8. Fremdschlüssel für Reiter Tabelle aktualisieren
|
||||||
|
ALTER TABLE reiter ADD CONSTRAINT fk_reiter_fahr_lizenz FOREIGN KEY (fahr_lizenz_id) REFERENCES fahr_lizenzen(lizenz_id);
|
||||||
|
ALTER TABLE reiter ADD CONSTRAINT fk_reiter_startkarte FOREIGN KEY (startkarte_id) REFERENCES startkarten(startkarte_id);
|
||||||
|
-- reit_lizenz_id hinzufügen für 0..1 Beziehung
|
||||||
|
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS reit_lizenz_id UUID;
|
||||||
|
ALTER TABLE reiter ADD CONSTRAINT fk_reiter_reit_lizenz FOREIGN KEY (reit_lizenz_id) REFERENCES reit_lizenzen(lizenz_id);
|
||||||
+6
-28
@@ -1,11 +1,6 @@
|
|||||||
package at.mocode.zns.import.service
|
package at.mocode.zns.import.service
|
||||||
|
|
||||||
import at.mocode.masterdata.domain.repository.*
|
import at.mocode.masterdata.domain.repository.*
|
||||||
import at.mocode.masterdata.infrastructure.persistence.*
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerExposedRepository
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseExposedRepository
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterExposedRepository
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinExposedRepository
|
|
||||||
import at.mocode.zns.importer.ZnsImportService
|
import at.mocode.zns.importer.ZnsImportService
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||||
import org.springframework.boot.runApplication
|
import org.springframework.boot.runApplication
|
||||||
@@ -14,27 +9,6 @@ import org.springframework.context.annotation.Bean
|
|||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
class ZnsImportServiceApplication {
|
class ZnsImportServiceApplication {
|
||||||
|
|
||||||
// Manuelle Bean-Definitionen für die Repositories, da diese in der Infrastruktur
|
|
||||||
// keine @Repository-Annotationen haben und wir MasterdataConfiguration nicht importieren wollen.
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun landRepository(): LandRepository = LandRepositoryImpl()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun bundeslandRepository(): BundeslandRepository = BundeslandRepositoryImpl()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun vereinRepository(): VereinRepository = VereinExposedRepository()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun reiterRepository(): ReiterRepository = ReiterExposedRepository()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun horseRepository(): HorseRepository = HorseExposedRepository()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun funktionaerRepository(): FunktionaerRepository = FunktionaerExposedRepository()
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun znsImportService(
|
fun znsImportService(
|
||||||
vereinRepository: VereinRepository,
|
vereinRepository: VereinRepository,
|
||||||
@@ -42,7 +16,9 @@ class ZnsImportServiceApplication {
|
|||||||
horseRepository: HorseRepository,
|
horseRepository: HorseRepository,
|
||||||
funktionaerRepository: FunktionaerRepository,
|
funktionaerRepository: FunktionaerRepository,
|
||||||
landRepository: LandRepository,
|
landRepository: LandRepository,
|
||||||
bundeslandRepository: BundeslandRepository
|
bundeslandRepository: BundeslandRepository,
|
||||||
|
licenseRepository: MasterdataLicenseRepository,
|
||||||
|
altersklassenRepository: AltersklassenRepository
|
||||||
): ZnsImportService {
|
): ZnsImportService {
|
||||||
return ZnsImportService(
|
return ZnsImportService(
|
||||||
vereinRepository,
|
vereinRepository,
|
||||||
@@ -50,7 +26,9 @@ class ZnsImportServiceApplication {
|
|||||||
horseRepository,
|
horseRepository,
|
||||||
funktionaerRepository,
|
funktionaerRepository,
|
||||||
landRepository,
|
landRepository,
|
||||||
bundeslandRepository
|
bundeslandRepository,
|
||||||
|
licenseRepository,
|
||||||
|
altersklassenRepository
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -1,6 +1,9 @@
|
|||||||
package at.mocode.zns.import.service.config
|
package at.mocode.zns.import.service.config
|
||||||
|
|
||||||
import at.mocode.masterdata.domain.repository.*
|
import at.mocode.masterdata.domain.repository.*
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.*
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.AltersklassenExposedRepository
|
||||||
|
import at.mocode.masterdata.infrastructure.persistence.reiter.MasterdataLicenseExposedRepository
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerExposedRepository
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerExposedRepository
|
||||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseExposedRepository
|
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseExposedRepository
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterExposedRepository
|
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterExposedRepository
|
||||||
@@ -11,6 +14,12 @@ import org.springframework.context.annotation.Configuration
|
|||||||
@Configuration
|
@Configuration
|
||||||
class RepositoryConfiguration {
|
class RepositoryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun landRepository(): LandRepository = LandRepositoryImpl()
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun bundeslandRepository(): BundeslandRepository = BundeslandRepositoryImpl()
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun vereinRepository(): VereinRepository = VereinExposedRepository()
|
fun vereinRepository(): VereinRepository = VereinExposedRepository()
|
||||||
|
|
||||||
@@ -22,4 +31,10 @@ class RepositoryConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun funktionaerRepository(): FunktionaerRepository = FunktionaerExposedRepository()
|
fun funktionaerRepository(): FunktionaerRepository = FunktionaerExposedRepository()
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun licenseRepository(): MasterdataLicenseRepository = MasterdataLicenseExposedRepository()
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun altersklassenRepository(): AltersklassenRepository = AltersklassenExposedRepository()
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -2,9 +2,9 @@ package at.mocode.zns.import.service.config
|
|||||||
|
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerQualifikationTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerQualifikationTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.QualifikationMasterTable
|
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaersQualifikationenTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
||||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
import at.mocode.masterdata.infrastructure.persistence.reiter.*
|
||||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
import org.jetbrains.exposed.v1.jdbc.Database
|
import org.jetbrains.exposed.v1.jdbc.Database
|
||||||
@@ -34,8 +34,12 @@ class ZnsImportDatabaseConfiguration(
|
|||||||
ReiterTable,
|
ReiterTable,
|
||||||
HorseTable,
|
HorseTable,
|
||||||
FunktionaerTable,
|
FunktionaerTable,
|
||||||
QualifikationMasterTable,
|
FunktionaersQualifikationenTable,
|
||||||
FunktionaerQualifikationTable
|
FunktionaerQualifikationTable,
|
||||||
|
ReitLizenzenTable,
|
||||||
|
FahrLizenzenTable,
|
||||||
|
StartkartenTable,
|
||||||
|
ReiterLizenzenZuordnungTable
|
||||||
)
|
)
|
||||||
statements.forEach { exec(it) }
|
statements.forEach { exec(it) }
|
||||||
log.info("Datenbank-Schema erfolgreich initialisiert ({} Statements)", statements.size)
|
log.info("Datenbank-Schema erfolgreich initialisiert ({} Statements)", statements.size)
|
||||||
|
|||||||
@@ -26,20 +26,20 @@ object ZnsReiterParser {
|
|||||||
val bundeslandNummer = reader.getIntOrNull(82, 2)
|
val bundeslandNummer = reader.getIntOrNull(82, 2)
|
||||||
val vereinsName = reader.getString(84, 50)
|
val vereinsName = reader.getString(84, 50)
|
||||||
val nation = reader.getString(134, 3)
|
val nation = reader.getString(134, 3)
|
||||||
val reiterLizenz = reader.getString(137, 4)
|
val reiterLizenzCode = reader.getString(137, 4).trim()
|
||||||
// Ab Stelle 137 weicht die Realität der ZNS.zip von der Spec 2.4 ab
|
val startkarteCode = reader.getString(141, 1).trim()
|
||||||
// Die Realität (Aichinger Ewald) zeigt:
|
val fahrLizenzCode = reader.getString(142, 2).trim()
|
||||||
// 134-136: AUT
|
|
||||||
// 137-140: R2
|
|
||||||
// 147-158: 206607000676 (Mitgliedsnummer 8 Stellen ab 147?)
|
|
||||||
// 160-166: 4825910 (Telefonnummer?)
|
|
||||||
// 177-180: 2023 (LastPayYear)
|
|
||||||
// 181: M (Geschlecht)
|
|
||||||
// 182-189: 19571010 (Geburtsdatum)
|
|
||||||
val startkarte = reader.getString(141, 1)
|
|
||||||
val fahrLizenz = reader.getString(142, 2)
|
|
||||||
val altersklasseJgJrU25 = reader.getString(144, 2)
|
val altersklasseJgJrU25 = reader.getString(144, 2)
|
||||||
val altersklasseY = reader.getString(146, 1)
|
val altersklasseY = reader.getString(146, 1)
|
||||||
|
|
||||||
|
val altersklasseEnum = when (altersklasseJgJrU25.uppercase()) {
|
||||||
|
"JG" -> at.mocode.core.domain.model.ReiterAltersKlasseE.JG
|
||||||
|
"JR" -> at.mocode.core.domain.model.ReiterAltersKlasseE.JR
|
||||||
|
"25" -> at.mocode.core.domain.model.ReiterAltersKlasseE.U25
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val altersklasseYEnum = if (altersklasseY.uppercase() == "Y") at.mocode.core.domain.model.ReiterAltersKlasseE.Y else null
|
||||||
|
|
||||||
val mitgliedsNummerStr = reader.getString(147, 8)
|
val mitgliedsNummerStr = reader.getString(147, 8)
|
||||||
val mitgliedsNummer = mitgliedsNummerStr.toIntOrNull()
|
val mitgliedsNummer = mitgliedsNummerStr.toIntOrNull()
|
||||||
val telefonNummer = reader.getString(155, 22).trim()
|
val telefonNummer = reader.getString(155, 22).trim()
|
||||||
@@ -50,7 +50,18 @@ object ZnsReiterParser {
|
|||||||
val feiId = reader.getString(190, 8)
|
val feiId = reader.getString(190, 8)
|
||||||
val sperrListe = reader.getString(198, 1)
|
val sperrListe = reader.getString(198, 1)
|
||||||
val lizenzInfo = reader.getString(201, 10)
|
val lizenzInfo = reader.getString(201, 10)
|
||||||
val lizenzKlasse = mapLizenz(reiterLizenz)
|
val lizenzKlasse = mapLizenz(reiterLizenzCode)
|
||||||
|
|
||||||
|
val lizenzen = mutableListOf<at.mocode.masterdata.domain.model.ReiterLizenz>()
|
||||||
|
if (reiterLizenzCode.isNotBlank()) {
|
||||||
|
lizenzen.add(at.mocode.masterdata.domain.model.ReiterLizenz(lizenzTyp = "REITERLIZENZ", kuerzel = reiterLizenzCode))
|
||||||
|
}
|
||||||
|
if (startkarteCode.isNotBlank()) {
|
||||||
|
lizenzen.add(at.mocode.masterdata.domain.model.ReiterLizenz(lizenzTyp = "STARTKARTE", kuerzel = startkarteCode))
|
||||||
|
}
|
||||||
|
if (fahrLizenzCode.isNotBlank()) {
|
||||||
|
lizenzen.add(at.mocode.masterdata.domain.model.ReiterLizenz(lizenzTyp = "FAHRLIZENZ", kuerzel = fahrLizenzCode))
|
||||||
|
}
|
||||||
|
|
||||||
return Reiter(
|
return Reiter(
|
||||||
personId = Uuid.random(),
|
personId = Uuid.random(),
|
||||||
@@ -60,11 +71,11 @@ object ZnsReiterParser {
|
|||||||
bundeslandNummer = bundeslandNummer,
|
bundeslandNummer = bundeslandNummer,
|
||||||
vereinsName = vereinsName.ifBlank { null },
|
vereinsName = vereinsName.ifBlank { null },
|
||||||
nation = nation.ifBlank { null },
|
nation = nation.ifBlank { null },
|
||||||
reiterLizenz = reiterLizenz.ifBlank { null },
|
reiterLizenz = reiterLizenzCode.ifBlank { null },
|
||||||
startkarte = startkarte.ifBlank { null },
|
startkarte = startkarteCode.ifBlank { null },
|
||||||
fahrLizenz = fahrLizenz.ifBlank { null },
|
fahrLizenz = fahrLizenzCode.ifBlank { null },
|
||||||
altersklasseJgJrU25 = altersklasseJgJrU25.ifBlank { null },
|
altersklasseJgJrU25 = altersklasseEnum,
|
||||||
altersklasseY = altersklasseY.ifBlank { null },
|
altersklasseY = altersklasseYEnum,
|
||||||
mitgliedsNummer = mitgliedsNummer,
|
mitgliedsNummer = mitgliedsNummer,
|
||||||
telefonNummer = telefonNummer.ifBlank { null },
|
telefonNummer = telefonNummer.ifBlank { null },
|
||||||
kader = kader.ifBlank { null },
|
kader = kader.ifBlank { null },
|
||||||
@@ -75,7 +86,8 @@ object ZnsReiterParser {
|
|||||||
sperrListe = sperrListe.ifBlank { null },
|
sperrListe = sperrListe.ifBlank { null },
|
||||||
lizenzInfo = lizenzInfo.ifBlank { null },
|
lizenzInfo = lizenzInfo.ifBlank { null },
|
||||||
lizenzKlasse = lizenzKlasse,
|
lizenzKlasse = lizenzKlasse,
|
||||||
datenQuelle = DatenQuelleE.IMPORT_ZNS
|
datenQuelle = DatenQuelleE.IMPORT_ZNS,
|
||||||
|
lizenzen = lizenzen
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ und über definierte Schnittstellen kommunizieren.
|
|||||||
#### 🧐 Agent: QA Specialist
|
#### 🧐 Agent: QA Specialist
|
||||||
|
|
||||||
* [x] **Actor Context Stabilization:** Funktionär-Datenmodell (Richter/Parcoursbauer) auf professionelle Master-Daten-Referenzierung umgestellt und mit Reiter-Daten verknüpft (Import-Idempotenz via `satzNummer`). Redundante Kontakt-/Adressdaten entfernt. Alle ZNS-Import-Tests (9/9) stabilisiert und verwaiste Parser-Reste entfernt.
|
* [x] **Actor Context Stabilization:** Funktionär-Datenmodell (Richter/Parcoursbauer) auf professionelle Master-Daten-Referenzierung umgestellt und mit Reiter-Daten verknüpft (Import-Idempotenz via `satzNummer`). Redundante Kontakt-/Adressdaten entfernt. Alle ZNS-Import-Tests (9/9) stabilisiert und verwaiste Parser-Reste entfernt.
|
||||||
|
* [x] **Masterdata Standardization:** Bereinigung und Standardisierung der Masterdaten-Tabellen (Mehrzahl-Konvention: `bundeslaender`, `funktionaers_qualifikationen`, `reit_lizenzen`, `turnier_klassen`).
|
||||||
|
* [x] **ÖTO Data Seeding:** Umfassende Seeder für Funktionärs-Qualifikationen, Turnierklassen und Turnier-Sparten gemäß ÖTO implementiert. Einführung der Tabelle `turnier_sparten`.
|
||||||
* [x] **ZNS-Import Optimization:** Automatische Verknüpfung von Funktionären mit Reitern (Reihenfolge: VEREIN -> LIZENZ -> PFERDE -> RICHT). `ZnsImportService` für sequentielle Imports in Tests gehärtet.
|
* [x] **ZNS-Import Optimization:** Automatische Verknüpfung von Funktionären mit Reitern (Reihenfolge: VEREIN -> LIZENZ -> PFERDE -> RICHT). `ZnsImportService` für sequentielle Imports in Tests gehärtet.
|
||||||
* [x] **Service Stability:** Port-Konflikt des `masterdata-service` (Spring Management Port 8081 vs. Gateway) durch Umzug auf Port 8086 und explizite Bind-Adressen (Spring: 127.0.0.1, Ktor: 0.0.0.0) dauerhaft gelöst.
|
* [x] **Service Stability:** Port-Konflikt des `masterdata-service` (Spring Management Port 8081 vs. Gateway) durch Umzug auf Port 8086 und explizite Bind-Adressen (Spring: 127.0.0.1, Ktor: 0.0.0.0) dauerhaft gelöst.
|
||||||
* [x] **Documentation:** `CHANGELOG.md` aktualisiert und Port-Konfiguration in `application.yml` dokumentiert.
|
* [x] **Documentation:** `CHANGELOG.md` aktualisiert und Port-Konfiguration in `application.yml` dokumentiert.
|
||||||
@@ -125,8 +127,10 @@ und über definierte Schnittstellen kommunizieren.
|
|||||||
|
|
||||||
#### 👷 Agent: Backend Developer
|
#### 👷 Agent: Backend Developer
|
||||||
|
|
||||||
* [x] **ZNS-Importer:** Support für Richter-Import (RICHT01.DAT) und Reiter-Refactoring (LIZENZ01.DAT) vervollständigt.
|
* [x] **ZNS-Importer:** Support für Richter-Import (RICHT01.DAT) und Reiter-Refactoring (LIZENZ01.DAT) vervollständigt. ✓
|
||||||
* [x] **Masterdata:** Qualifikations-System und Personen-Referenzen (Vereine, Bundesländer, Nationen) auf professionelle Master-Daten umgestellt.
|
* [x] **Masterdata:** Qualifikations-System und Personen-Referenzen (Vereine, Bundesländer, Nationen) stabilisiert (Consul & MasterdataSeeder). ✓
|
||||||
|
* [x] **Infrastruktur:** Service-Discovery (Consul) für alle Microservices (incl. Masterdata) aktiviert.
|
||||||
|
* [x] **Infrastruktur:** Bean-Definitionen und Dependency-Injection im `zns-import-service` bereinigt.
|
||||||
* [x] **Database:** Initialisierung der Funktionärs-Tabellen stabilisiert (PSQLException Fix).
|
* [x] **Database:** Initialisierung der Funktionärs-Tabellen stabilisiert (PSQLException Fix).
|
||||||
* [x] **`actor-context`:** Domain-Modelle für `Pferd`, `Funktionaer`, `Verein` implementiert.
|
* [x] **`actor-context`:** Domain-Modelle für `Pferd`, `Funktionaer`, `Verein` implementiert.
|
||||||
* [x] **`registration-context`:** `DomBewerb`, `DomAbteilung`, `DomStartliste` implementiert.
|
* [x] **`registration-context`:** `DomBewerb`, `DomAbteilung`, `DomStartliste` implementiert.
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ Dieses Dokument definiert die **Ubiquitous Language** (allgegenwärtige Sprache)
|
|||||||
|
|
||||||
* **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.
|
* **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.
|
* **Akteur:** Oberbegriff für alle Personen (Reiter, Richter, Besitzer) und Organisationen (Vereine), die im System interagieren.
|
||||||
|
* **Altersklasse (singular):** Domänenobjekt zur Klassifikation von Teilnehmern nach Alter. Schlüssel-Felder: `altersklasseId` (UUID), `altersklasseCode` (fachlicher Schlüssel, z.B. `JG`, `JR`, `25`, `Y`), `bezeichnung`, optionale Grenzen `minAlter`/`maxAlter`, optionale Filter `sparteFilter`/`geschlechtFilter`. Persistiert in Tabelle `altersklasse` (singular), Spalte `altersklasse_code` (einzigartig).
|
||||||
|
* **Altersklassen (plural):** Offizielle Altersklassen gemäß LIZENZ01.DAT. Unterstützte Kürzel: `JG` (Jugendlicher), `JR` (Junior), `25` (U25), `Y` (Junger Reiter). Ein Reiter hat 0..1 Altersklasse aus JG/JR/U25 und optional 0..1 aus Y.
|
||||||
* **Ausschreibung:** Das offizielle Dokument, das alle Bedingungen eines -> *Turniers* festlegt.
|
* **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.
|
* **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.
|
* **Event:** Der organisatorische Rahmen (z.B. "Pferdefest 2026"), der ein oder mehrere -> *Turniere* beinhalten kann.
|
||||||
@@ -27,18 +29,22 @@ Dieses Dokument definiert die **Ubiquitous Language** (allgegenwärtige Sprache)
|
|||||||
## K - O
|
## 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.
|
* **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.
|
* **Lizenz (Reit-Lizenz):** Die Qualifikationsstufe eines Reiters (z.B. `R1`, `RD1`, `RD2`, `RS2`). Ein Reiter hat 0..1 Reit-Lizenz. Wird in der Tabelle `reit_lizenzen` als Stammdaten geführt und am Reiter per `reit_lizenz_id` referenziert.
|
||||||
|
* **Fahr-Lizenz:** Eigenständige Lizenzkategorie für den Fahrsport (z.B. `F1`, `F2`). Ein Reiter hat 0..1 Fahr-Lizenz. Stammdaten-Tabelle `fahr_lizenzen`, Referenz am Reiter `fahr_lizenz_id`.
|
||||||
* **Nennung:** Die verbindliche Anmeldung eines Paares (Reiter & Pferd) zu einem -> *Bewerb*.
|
* **Nennung:** Die verbindliche Anmeldung eines Paares (Reiter & Pferd) zu einem -> *Bewerb*.
|
||||||
* **OEPS:** Österreichischer Pferdesportverband.
|
* **OEPS:** Österreichischer Pferdesportverband.
|
||||||
|
|
||||||
## P - T
|
## P - T
|
||||||
|
|
||||||
|
* **Reit-Lizenzen (Historie):** Optionale Historien-Zuordnungen in `reiter_lizenzen_zuordnung` (z.B. Jahreswechsel). Enthalten den Typ (`REITERLIZENZ`, `STARTKARTE`, `FAHRLIZENZ`), das Kürzel und optional `gültig_bis`.
|
||||||
* **Satznummer:**
|
* **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.**
|
* *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.
|
* *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).
|
* **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.
|
* **Startkarte:** Der Nachweis, dass die Jahresgebühr für die Lizenz bezahlt wurde. Ohne aktive Startkarte ist (national) kein Start möglich. Stammdaten-Tabelle `startkarten`, Referenz am Reiter `startkarte_id`.
|
||||||
* **Turnier:** Die administrative Einheit (z.B. "CSN-A"), die einem spezifischen Regelwerk (ÖTO oder FEI) unterliegt.
|
* **Turnier:** Die administrative Einheit (z.B. "CSN-A"), die einem spezifischen Regelwerk (ÖTO oder FEI) unterliegt.
|
||||||
|
* **Turnier-Kategorie:** Klassifikation eines Turniers (z.B. `CSN-C`, `CSN-C Neu`, `CSN-B`, `CSN-A`, `CDN-C`, `CDN-B`, `CDN-A`). Stammdaten-Tabelle `turnier_kategorien`.
|
||||||
|
* **Bewerbsklasse:** Früher „Turnierklasse“. Klassifiziert den Schwierigkeitsgrad eines Bewerbs (Springen: `E`, `A`, `L`, `LM`, `M`, `S`; Dressur: `E` bis `S`). Stammdaten-Tabelle `bewerbs_klassen`. API-Endpunkt: `GET /rules/turnierklassen` liefert dieselben Inhalte (Alias), technisch über `RegulationRepository.findAllTurnierklassen()` abgebildet.
|
||||||
|
|
||||||
## U - Z
|
## U - Z
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
|||||||
| Begriff | Definition | ÖTO-Referenz |
|
| Begriff | Definition | ÖTO-Referenz |
|
||||||
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|
|
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|
|
||||||
| **Kategorie** | Das Niveau eines Turniers und/oder seiner Bewerbe bzw. die Teilnahmeberechtigung daran. Nationale Kategorien: `C-NEU`, `C`, `B*`, `B`, `A`, `A*`. | ÖTO § 3 Abs. 4 |
|
| **Kategorie** | Das Niveau eines Turniers und/oder seiner Bewerbe bzw. die Teilnahmeberechtigung daran. Nationale Kategorien: `C-NEU`, `C`, `B*`, `B`, `A`, `A*`. | ÖTO § 3 Abs. 4 |
|
||||||
| **Klasse / Höhe** | Schwierigkeitsgrad eines Bewerbs. Springen: E0 (60–90 cm), A (105–110 cm), L, M, S. Dressur: E, A, L, M, S (nach Aufgabe). | ÖTO B-Teil |
|
| **Bewerbsklasse** | Früher „Turnierklasse“. Schwierigkeitsgrad eines Bewerbs. Springen: E0 (60–90 cm), A (105–110 cm), L, M, S. Dressur: E, A, L, M, S (nach Aufgabe). Stammdaten in `bewerbs_klassen`. | ÖTO B-Teil |
|
||||||
| **Kombination** | Zwei oder mehr Turniere (ggf. unterschiedlicher Sparten) die am selben Ort/Datum stattfinden. Jedes Turnier behält seine eigene Turniernummer. Genehmigung durch LFV/OEPS erforderlich. | ÖTO § 4 |
|
| **Kombination** | Zwei oder mehr Turniere (ggf. unterschiedlicher Sparten) die am selben Ort/Datum stattfinden. Jedes Turnier behält seine eigene Turniernummer. Genehmigung durch LFV/OEPS erforderlich. | ÖTO § 4 |
|
||||||
| **Kopfnummer** | *National (OEPS):* 4-stellige Registrierungsnummer eines Pferdes beim OEPS. **Nicht als eindeutige ID geeignet** – kann sich ändern. Dient zur schnellen Suche/Eingabe in der Meldestelle (Autocomplete), aber nicht als Datenbankschlüssel. *Turnier:* Temporäre Startnummer für das spezifische Turnier (ebenfalls nicht persistent). | – |
|
| **Kopfnummer** | *National (OEPS):* 4-stellige Registrierungsnummer eines Pferdes beim OEPS. **Nicht als eindeutige ID geeignet** – kann sich ändern. Dient zur schnellen Suche/Eingabe in der Meldestelle (Autocomplete), aber nicht als Datenbankschlüssel. *Turnier:* Temporäre Startnummer für das spezifische Turnier (ebenfalls nicht persistent). | – |
|
||||||
| **Konto** | Kontobasierte Abrechnung pro Zahler (nicht nur pro Reiter). Basis für das „Hansi-Szenario" (Guthaben bei Transfer). | Billing Context |
|
| **Konto** | Kontobasierte Abrechnung pro Zahler (nicht nur pro Reiter). Basis für das „Hansi-Szenario" (Guthaben bei Transfer). | Billing Context |
|
||||||
@@ -95,7 +95,9 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
|||||||
| Begriff | Definition | ÖTO-Referenz |
|
| Begriff | Definition | ÖTO-Referenz |
|
||||||
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------|
|
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------|
|
||||||
| **Lebensnummer** | 9-stellige (national) bzw. 15-stellige (international, UELN) Nummer, die ein Pferd bei der Geburt vom Zuchtverband erhält. Bei ausländischen Pferden im OEPS oft **generiert** → **nicht zur Suche geeignet**. Die ZNS-Daten zu Lebensnummern sind erfahrungsgemäß inkonsistent und widersprüchlich (z.B. Farbe `"Braun"` vs. `"Brauner"` für dasselbe Pferd). Primärer Schlüssel für den Datenaustausch bleibt die → *Satznummer*. | – |
|
| **Lebensnummer** | 9-stellige (national) bzw. 15-stellige (international, UELN) Nummer, die ein Pferd bei der Geburt vom Zuchtverband erhält. Bei ausländischen Pferden im OEPS oft **generiert** → **nicht zur Suche geeignet**. Die ZNS-Daten zu Lebensnummern sind erfahrungsgemäß inkonsistent und widersprüchlich (z.B. Farbe `"Braun"` vs. `"Brauner"` für dasselbe Pferd). Primärer Schlüssel für den Datenaustausch bleibt die → *Satznummer*. | – |
|
||||||
| **Lizenz** | Qualifikationsstufe eines Reiters (z.B. `R1`, `RD3`). Bestimmt Startberechtigung in bestimmten Klassen. | ÖTO Teilnahmeberechtigung |
|
| **Lizenz (Reit-Lizenz)** | Qualifikationsstufe eines Reiters (z.B. `R1`, `RD1`, `RD2`, `RS2`). Ein Reiter hat 0..1 Reit-Lizenz. Stammdaten in `reit_lizenzen`, Referenz am Reiter `reit_lizenz_id`. | ÖTO Teilnahmeberechtigung |
|
||||||
|
| **Fahr-Lizenz** | Lizenzkategorie für den Fahrsport (z.B. `F1`, `F2`). Ein Reiter hat 0..1 Fahr-Lizenz. Stammdaten in `fahr_lizenzen`, Referenz am Reiter `fahr_lizenz_id`. | ÖTO Teilnahmeberechtigung |
|
||||||
|
| **Startkarte** | Nachweis der Jahresgebühr. Ein Reiter hat 0..1 Startkarte. Stammdaten in `startkarten`, Referenz am Reiter `startkarte_id`. | ÖTO Teilnahmeberechtigung |
|
||||||
|
|
||||||
### M
|
### M
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user